2010-02-11 4 views
19

Ich habe eine XML-ähnlicheXML-Signatur: Wie wird der Digest-Wert berechnet?

<?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> 

Wie der Digest-Wert (WqpRWHxXA0YgH + p3Sxy6hRo1XIk =) in der Referenz erstellt wird? Ich meine, wie kann ich diesen Wert manuell berechnen?

+0

Warum wollen Sie es manuell berechnen? Das wird ein langwieriger und fehleranfälliger Prozess sein. – HerbN

+0

Ich verwende .net-Funktionen, um die Signatur zu validieren. Es gibt zurück, dass die Signatur nicht gültig ist. Also ich möchte es manuell überprüfen, oder wenn es ein Werkzeug gab, um die Signatur zu überprüfen ... – user252816

+0

Ich verstehe, dass Sie den Fehler "Digestüberprüfung für Referenz fehlgeschlagen" gelöst haben? Wäre es möglich, eine detaillierte Erklärung zu erhalten, wie Sie es tatsächlich getan haben? Ich habe dieses Problem mit einer signierten Soap-Nachricht mit Metro, und eine .Net-WCF-Anwendung erkennt den Digest-Wert nicht. –

Antwort

-1

This Dokument sollte enthalten, wie der Digest-Wert berechnet wird.

Ich hoffe, es hilft!

2

Ich habe genau dieses Problem selbst festgestellt: Ich erzeugte eine XML-Signatur in Java & Validierung in. NET, und die Validierung immer fehlgeschlagen. In meinem Fall war die Ursache die Funktion 'XML in Datei drucken' XMLWrite.m (ja, in MATLAB *), die den XML-Code 'hübsch druckte', Tabulator-, Leerzeichen- und Zeilenumbrüche einfügte, wie es für richtig hielt. Da diese Teile Teil des Dokuments sind, ist die Validierung natürlich fehlgeschlagen (auch in Java fehlgeschlagen). Wenn du deine Quelle betrachtest, könnte dir das passieren. Verwenden Sie einen Transformer (javax.xml.transform. *), Um Ihr DOM ordnungsgemäß zu serialisieren, ohne den Inhalt zu ändern.

* Sie wussten, dass MATLAB auch Java versteht? Sie können Java-Anweisungen einfach in die Interpreter-Konsole & eingeben, sie werden wie nativer M-Code ausgeführt.

+2

Dies wird bereits durch XML-Signatur behoben, die auf XML-Kanonisierung basiert. XML wird zuerst normalisiert und die syntaktischen Unterschiede (Leerzeichen, Namespaces usw.) werden korrekt behandelt. – ewernli

+1

Wahr: Aber es ist das DOM, nicht seine Seralisierung, die kanonisiert wurde. Die zusätzlichen Leerraumzeichen wurden während der Serialisierung (in die Datei) eingefügt, NACHDEM der Digest berechnet wurde, und sie waren immer noch da, als der Validierungscode sein DOM erzeugte, es kanonisierte und den Digest neu berechnete. Leerzeichen sind in analysierten Zeichendatenknoten von Bedeutung. – Max

16

Ich bin auf diese Frage gestoßen, als ich versuchte, genau dasselbe herauszufinden. Ich habe später herausgefunden, wie es geht, also habe ich mir gedacht, ich würde die Antwort hier posten.

Die Dinge, die passieren müssen, sind:

  • Kanonisierung
  • erstellen Digest-Wert, in der Regel SHA1 (aber könnte unter anderem SHA256 werden)
  • base64 kodieren

Die Kanonisierung Teil war ziemlich einfach, wie die Java-Bibliotheken das für mich taten. Womit ich kämpfte, war das nächste Bit, das Erstellen des Digests, weil ich einen fatalen Fehler machte, indem der SHA1-Digest, den ich erzeugte, der SHA1 in HEX-Form war. SHA1 ist 160 Bits, also 20 Bytes, aber wenn Sie diese 160 Bits in HEX ausgeben, erhalten Sie 40 Zeichen. Wenn Sie dann Base64 kodieren, erhalten Sie total den falschen Wert verglichen mit dem, was im DigestValue sein sollte.

Stattdessen sollten Sie den SHA1-Digest und base64 den 20-Byte-Ausgang codieren. Versuchen Sie nicht, die 20 Bytes an STDOUT auszugeben, da es sehr unwahrscheinlich ist, dass sie lesbar sind (weshalb die Leute oft die HEX-Entsprechung ausgeben, da sie lesbar ist). Stattdessen kodieren Sie nur Base64 die 20 Bytes und das ist Ihr DigestValue.

+0

Ich dachte das gleiche, aber ich bekomme auch einen anderen Wert. Haben Sie direkt Canonicalization Bytes oder die verdauten String Bytes verarbeitet? –

+0

SHA1 Verdau von was? – lonelyloner

0

ist sehr einfach, die Verwendung von OpenSSL in der Konsole:

openssl DGST -binary -sha1 Datei | openssl enc -base64

Geschehen

+0

OP hat 'manuell' nicht als 'programmgesteuert' angegeben. Dies ist auf jeden Fall eine gute Möglichkeit zu überprüfen. – Vbakke

0

Dies ist eine JAVA-Lösung, die die folgenden Gläser erfordert:

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

Diese Lösung http://www.w3.org/2001/10/xml-exc-c14n# als Kanonisierungsprobleme Algorithmus verwendet, und verwendet SHA256 als Hashing-Algorithmus und Base64-Kodierung.

Hinweis: document stellt das XML-Dokument als ein DOM-Objekt in JAVA.

Codebeispiel:

 // 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);