5

XMLSignatureをxmlドキュメントに適用するC#で実行されているプログラムがあります。どちらの場合(C#とJava)でも同じXMLドキュメントを使用していますが、同じダイジェスト値と署名値を取得できません。Cプログラムの結果が正しいことはわかっていますが、Javaで正しく取得できません。

ここにC#コードがあります:

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


        }

Javaコードは次のとおりです。

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

同じxmlドキュメント、証明書、秘密鍵を使用して、それぞれに次のダイジェスト値を取得しています。

  • Java:EZTMZuMvR9D0WSUgbT2AdFYTBh4=

  • C#:EsJDdWiUMIOaQp9CC26wQWA6kJ0=

なぜこれが起こるのですか?

4

3 に答える 3

3

この問題を解決するために私がしたことを追加するだけです:

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

したがって、ダイジェストと署名を計算する前に、ファイルからxmlをロードするときに空白とCRLFを削除する必要があります。そうしないと、.Netの結果と比較した署名とダイジェストが異なります。

于 2012-11-27T11:29:08.687 に答える
1

なぜこれが発生するのかわかりませんが、この問題の解決策は、ドキュメントを文字列に変換してから再度ドキュメントに変換することでした。これにより、期待されるダイジェストと署名の値が得られました。

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)));
于 2012-02-09T21:27:07.870 に答える
0

ダイジェストと署名を計算する前に、xmlを正規化する必要があります。C#コードの場合。

XmlDsigC14NTransform正規化=新しいXmlDsigC14NTransform(); reference.AddTransform(canonicalization);

于 2013-10-16T20:58:47.450 に答える