Question

Je signe une partie d'un document XML à l'aide de l'API Java XML DSig. J'essaie de comprendre comment il arrive à la valeur Digest.

Mon document est:

<?xml version=\"1.0\" encoding=\"UTF-8\"?><PurchaseOrder><foo>bar</foo></PurchaseOrder>

Mon expression XPath est:

PurchaseOrder/foo/text()

Ce que je tente de faire est:

  1. Appelez la bibliothèque Java DSIG et afficher la valeur du digest généré.
  2. Utiliser la classe MessageDigest (SHA-1) à digérer la valeur "bar".
  3. Vérifiez que les digestions de jeu 1 et 2.

Quand je fais cela, 1 et 2 produits différents valeurs digest. Soit je fais quelque chose tout à fait mal avec mon code DSIG, ou je ne comprends pas comment fonctionne DSIG. Toutes les idées?

Voici mon code de test (désolé il est si longtemps ... Je devrais revenir à Perl):

public class GenerateXmlSignature2 {
    private static final String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><PurchaseOrder><foo>bar</foo></PurchaseOrder>";
    private static final String xpath  = "PurchaseOrder/foo/text()";

    public static void main(String[] args) throws Exception {
        Base64 base64 = new Base64();
        // Create a DOM XMLSignatureFactory that will be used to
        // generate the enveloped signature.
        final XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

        // Create a Reference to the enveloped document (in this case,
        // you are signing the whole document, so a URI of "" signifies
        // that, and also specify the SHA1 digest algorithm and
        // the ENVELOPED Transform.
        final List<XPathType> xpaths = new ArrayList<XPathType>() {
            {
                add(new XPathType(xpath, XPathType.Filter.UNION));
            }
        };
        List<Transform> transforms = new ArrayList<Transform>() {{
             add(fac.newTransform(
                Transform.XPATH2,
                new XPathFilter2ParameterSpec(xpaths)
            )
            );
        }};
        Reference ref = fac.newReference
                ("", fac.newDigestMethod(DigestMethod.SHA1, null),
                        transforms,
                        null, null);


        // Create the SignedInfo.
        SignedInfo si = fac.newSignedInfo
                (fac.newCanonicalizationMethod
                        (CanonicalizationMethod.INCLUSIVE,
                                (C14NMethodParameterSpec) null),
                        fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
                        Collections.singletonList(ref));


        // Load the KeyStore and get the signing key and certificate.
        KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(new FileInputStream("mykeystore.jks"), "changeit".toCharArray());
        KeyStore.PrivateKeyEntry keyEntry =
                (KeyStore.PrivateKeyEntry) ks.getEntry
                        ("mykey", new KeyStore.PasswordProtection("changeit".toCharArray()));
        X509Certificate cert = (X509Certificate) keyEntry.getCertificate();

        // Create the KeyInfo containing the X509Data.
        KeyInfoFactory kif = fac.getKeyInfoFactory();
        List x509Content = new ArrayList();
        x509Content.add(cert.getSubjectX500Principal().getName());
        x509Content.add(cert);
        X509Data xd = kif.newX509Data(x509Content);
        KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));

        // Instantiate the document to be signed.
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        Document doc = dbf.newDocumentBuilder().parse
                (new ByteArrayInputStream(xml.getBytes()));

        // Create a DOMSignContext and specify the RSA PrivateKey and
        // location of the resulting XMLSignature's parent element.
        DOMSignContext dsc = new DOMSignContext
                (keyEntry.getPrivateKey(), doc.getDocumentElement());

        // Create the XMLSignature, but don't sign it yet.
        XMLSignature signature = fac.newXMLSignature(si, ki);



        // Marshal, generate, and sign the enveloped signature.
        signature.sign(dsc);

        // Output the resulting document.
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer trans = tf.newTransformer();
        trans.transform(new DOMSource(doc), new StreamResult(System.out));



        System.out.println("\n\n*** SHA-1 Digest ***");
        XPathExpression xpathExpression = XPathFactory.newInstance().newXPath().compile(xpath);
        String data = xpathExpression.evaluate(new InputSource(new StringReader(xml)));
        System.out.println("Xpath: " + data);
        MessageDigest md;
        md = MessageDigest.getInstance("SHA");
        byte[] sha1hash;
        md.update(data.getBytes(), 0, data.length());
        sha1hash = md.digest();
        String base64Sha1OfCanonicalXml = new String(base64.encode(sha1hash));
        System.out.println("Digest:   " + base64Sha1OfCanonicalXml);
    }
}
Était-ce utile?

La solution

Après un exemple à: http://markmail.org/message/tdgioazns7l4yg6d#query:java%20xpath%20xml%20dsig%20bug+page:1+mid:tgw5kr7uscwkcran+state:results , je trouve que je nécessaire pour changer le XPathType.Filter.UNION à XPathType.FILTER.INTERSECT. Cela semble avoir résolu mon problème. La bibliothèque XML DSig utilise maintenant la valeur correcte que je m'y attendais.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top