Question

I have a program running in C# which applies an XMLSignature to an xml document. I have the same XML documents in both cases (C# and Java), but I am not getting the same digest and signature values. I know that the results from my C program are correct, but I dont get to get them correctly in Java.

Here the C# code:

      public void SignXml(XmlDocument xmlDoc, RSA Key)
        {
            // Check arguments.
            if (xmlDoc == null)
                throw new ArgumentException("xmlDoc");
            if (Key == null)
                throw new ArgumentException("Key");

            // Create a SignedXml object.
            SignedXml signedXml = new SignedXml(xmlDoc);

            // Add the key to the SignedXml document.
            signedXml.SigningKey = Key;

            // Create a reference to be signed.
            Reference reference = new Reference();
            reference.Uri = "";

            // Add an enveloped transformation to the reference.
            XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
            reference.AddTransform(env);

            // Add the reference to the SignedXml object.
            signedXml.AddReference(reference);

            KeyInfo ki = new KeyInfo();
            KeyInfoX509Data clause = new KeyInfoX509Data();
            clause.AddCertificate(x509_2);
            clause.AddIssuerSerial(x509_2.Issuer, x509_2.GetSerialNumberString());
            ki.AddClause(clause);
            signedXml.KeyInfo = ki;

            // Compute the signature.
            signedXml.ComputeSignature();

            // Get the XML representation of the signature and save
            // it to an XmlElement object.
            XmlElement xmlDigitalSignature = signedXml.GetXml();

            //xmlDoc.Save("antes_firma.xml");
            // Append the element to the XML document.
            xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));


        }

The Java code is the following:

DOMSignContext dsc = new DOMSignContext (pk, doc.getDocumentElement()); 
            XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

            Reference ref = fac.newReference ("", fac.newDigestMethod(DigestMethod.SHA1, null), 
                        Collections.singletonList
                        (fac.newTransform(Transform.ENVELOPED,
                        (TransformParameterSpec) null)), null, null);

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

            KeyInfoFactory kif = fac.getKeyInfoFactory();
            X509IssuerSerial issuerSerial = kif.newX509IssuerSerial(cert2.getIssuerDN().getName(), cert.getSerialNumber());
            List x509Content = new ArrayList();
            x509Content.add(issuerSerial);
            x509Content.add(cert2);
            X509Data xd = kif.newX509Data(x509Content);
            KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));

            XMLSignature signature = fac.newXMLSignature(si, ki);

            signature.sign(dsc);

With the same xml document, certificate and private key I am getting the following Digest Values in each one:

  • Java: EZTMZuMvR9D0WSUgbT2AdFYTBh4=

  • C#: EsJDdWiUMIOaQp9CC26wQWA6kJ0=

Why does this happen?

Was it helpful?

Solution 2

I dont know why this happens, but the solution to this problem was converting the Document to String and then to Document again and by doing that I got the expected digest and signature values.

TransformerFactory transfac = TransformerFactory.newInstance();
            Transformer trans = transfac.newTransformer();


            //CREAR STRING DEL ARBOL XML
            StringWriter sw = new StringWriter();
            StreamResult result = new StreamResult(sw);
            DOMSource source = new DOMSource(doc);
            trans.transform(source, result);
            String xmlString = sw.toString();
            System.out.println(xmlString);

            dbfac = DocumentBuilderFactory.newInstance();
            dbfac.setNamespaceAware(true);
            doc = dbfac.newDocumentBuilder().parse(new InputSource(new StringReader(xmlString)));

OTHER TIPS

Just to add what I did to solve this problem:

String thisLine = "";
String xmlString = "";
BufferedReader br = new BufferedReader(new FileReader(xmlFile));
while ((thisLine = br.readLine()) != null) {
    xmlString = xmlString + thisLine.trim();
}
br.close();

ByteArrayInputStream xmlStream = new ByteArrayInputStream(xmlString.getBytes());
xmlDocument = docBuilder.parse(xmlStream);

So, before computing digest and signature, you need to strip whitespace and CRLF when loading xml from file. Otherwise, signature and digest compared to .Net result would be different.

You should canonicalize the xml before calculate digest and signature. for the C# codes.

XmlDsigC14NTransform canonicalization = new XmlDsigC14NTransform(); reference.AddTransform(canonicalization);

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top