web-dev-qa-db-fra.com

Signature XML: comment calculer la valeur de résumé?

J'ai un XML comme celui-ci

<?xml version="1.0" encoding="utf-8"?>
<foo>
  <bar>
    <value>A</value>
  </bar>
  <bar>
    <value>B</value>
  </bar>
  <baz>
    <value>C</value>
  </baz><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /><DigestValue>WqpRWHxXA0YgH+p3Sxy6hRo1XIk=</DigestValue></Reference></SignedInfo><SignatureValue>EoRk/GhR4UA4D+8AzGPPkeim1dZrlSy88eF73n/T9Lpeq9IxoGRHNUA8FEwuDNJuz3IugC0n2RHQQpQajiYvhlY3XG+z742pgsdMfFE4Pddk4gF1T8CVS1rsF7bjX+FKT/c8B2/C8FNgmfkxDlB/ochtbRvuAGPQGtgJ3h/wjSg=</SignatureValue><KeyInfo><X509Data><X509Certificate>MIIB8zCCAVygAwIBAgIQgfzbrIjhLL9FobStI2ub3zANBgkqhkiG9w0BAQQFADATMREwDwYDVQQDEwhUZXN0ZUFjbjAeFw0wMDAxMDEwMDAwMDBaFw0zNjAxMDEwMDAwMDBaMBMxETAPBgNVBAMTCFRlc3RlQWNuMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO+yAZ8/qJbhSVH/+2wMmzix3jM/CExb6sTgaiPwe6ylcHgF45zeQDq06OSJZCSns34em/ULINZddDf8z0b9uk/2sOGr1pYqsunLLBvw2FkvWJQDkhx2SzCm8v4xGX2kyXNbjiY/K56oPOMjpayKoAFnnvk7p2iFAxNZK/6lpZ7wIDAQABo0gwRjBEBgNVHQEEPTA7gBCOOHcajwnATYZ0t6w7LVU0oRUwEzERMA8GA1UEAxMIVGVzdGVBY26CEIH826yI4Sy/RaG0rSNrm98wDQYJKoZIhvcNAQEEBQADgYEABL9Qhi6f1Z+/t8oKXBQFx3UUsNF9N2o4k6q1c3CKZYqx2E/in+nARIYRdh5kbeLfomi6GIyVFeXExp8crob3MAzOQMvXf9+ByuezimMPIHDvv0u3kmmeITXfoZrHCDxLoWWlESN1owBfKPqe7JKAuu9ORDC0pUiUfCHWxCoqNos=</X509Certificate></X509Data></KeyInfo></Signature>
</foo>

Comment la valeur de résumé (WqpRWHxXA0YgH + p3Sxy6hRo1XIk =) dans la référence est créée? Je veux dire comment puis-je calculer cette valeur manuellement?

23
user252816

Je suis tombé sur cette question en essayant de découvrir exactement la même chose. Plus tard, j'ai trouvé comment le faire, alors j'ai pensé publier la réponse ici.

Les choses qui doivent arriver sont:

  • canonisation
  • créer une valeur de résumé, généralement SHA1 (mais pourrait être SHA256 entre autres)
  • base64 l'encode

La partie de canonisation était assez simple, comme les bibliothèques Java l'ont fait pour moi. Ce que j'ai lutté, c'était le bit suivant, la création du résumé, car j'ai fait une erreur fatale en ce que le SHA1 le résumé que j'ai généré était le SHA1 sous forme HEX. SHA1 fait 160 bits, donc 20 octets, mais si vous sortez ces 160 bits en HEX, vous obtenez 40 caractères. Si vous codez en base64, vous obtenez totalement faux value par rapport à ce qui devrait être dans DigestValue.

Au lieu de cela, vous devez générer le résumé SHA1 et coder en base64 la sortie de 20 octets. N'essayez pas de sortir les 20 octets vers STDOUT car il est très peu probable qu'ils soient lisibles (c'est pourquoi les gens sortent souvent l'équivalent HEX, car il est lisible). Au lieu de cela, il suffit de coder en base64 les 20 octets et c'est votre DigestValue.

24
Kenny

Est très simple, utilisez openssl dans la console:

openssl dgst -binary -sha1 file | openssl enc -base64

Terminé

6
user3273546

J'ai moi-même rencontré exactement ce problème: je générais une signature XML dans Java et validais dans .NET, et la validation échouait toujours. Dans mon cas, la cause était le 'print XML to file' la fonction XMLWrite.m (oui, dans MATLAB *) qui "imprimait assez" le XML, insérant les tabulations, les espaces et les nouvelles lignes comme bon lui semblait. Comme cela fait partie du document, naturellement la validation a échoué (elle a échoué en Java, Cela peut vous arriver aussi. En utilisant votre transformateur (javax.xml.transform. *) pour sérialiser correctement votre DOM sans changer le contenu.

* Vous saviez que MATLAB comprend également Java? Vous pouvez simplement taper Java instructions dans la console d'interpréteur et elles seront exécutées comme du code m natif).

3
Max

Il s'agit d'une solution Java qui nécessite les pots suivants:

  • commons-logging-1.2.jar
  • commons-codec-1.6.jar
  • Saxon-HE-9.4.jar
  • xmlsec-1.3.0.jar

Cette solution utilise http://www.w3.org/2001/10/xml-exc-c14n# comme algorithme de canonisation et utilise SHA256 comme algorithme de hachage et encodage base64.

Remarque: document représente le document XML en tant qu'objet DOM en Java.

Exemple de code:

        // create the transformer in order to transform the document from
        // DOM Source as a Java document class, into a character stream (StreamResult) of
        // type String writer, in order to be converted to a string later on
        TransformerFactory tf = new net.sf.saxon.TransformerFactoryImpl();
        Transformer transformer = tf.newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

        // create the string writer and transform the document to a character stream
        StringWriter sw = new StringWriter();
        transformer.transform(new DOMSource(document), new StreamResult(sw));

        String documentAsString = sw.toString();

        // initialize the XML security object, which is necessary to run the Apache canonicalization
        com.Sun.org.Apache.xml.internal.security.Init.init();

        // canonicalize the document to a byte array and convert it to string
        Canonicalizer Canon = Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
        byte canonXmlBytes[] = Canon.canonicalize(documentAsString.getBytes());
        String canonXmlString = new String(canonXmlBytes);

        // get instance of the message digest based on the SHA-256 hashing algorithm
        MessageDigest digest = MessageDigest.getInstance("SHA-256");

        // call the digest method passing the byte stream on the text, this directly updates the message
        // being digested and perform the hashing
        byte[] hash = digest.digest(canonXmlString.getBytes(StandardCharsets.UTF_8));

        // encode the endresult byte hash
        byte[] encodedBytes = Base64.encodeBase64(hash);

        return new String(encodedBytes);
3
KAD