2016-03-31 10 views
1

Ich habe eine digital signierte XML-Datei und ein öffentliches Zertifikat des Unterzeichners, ich möchte die Signatur validieren. Der ursprüngliche Inhalt von Antwort-XML gibt false zurück, aber wenn ich den XML-Code ändere, wird "Wahr" zurückgegeben. Mein Java-Code ist wie folgt: -XML-Signaturprüfung schlägt fehl in Java

import java.io.FileInputStream; 
import java.io.IOException; 
import java.security.GeneralSecurityException; 
import java.security.Security; 
import java.security.cert.CertificateFactory; 
import java.security.cert.X509Certificate; 
import javax.xml.crypto.dsig.XMLSignature; 
import javax.xml.crypto.dsig.XMLSignatureFactory; 
import javax.xml.crypto.dsig.dom.DOMValidateContext; 
import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import org.bouncycastle.jce.provider.BouncyCastleProvider; 
import org.w3c.dom.Document; 
import org.w3c.dom.NodeList; 
public class SignatureVerifierOneFile { 
    public static void main(String[] args){  
     Security.addProvider(new BouncyCastleProvider());  
     //Signed xml path 
     String signedXmlPath = "C:/signedXML.xml";  
     SignatureVerifierOneFile signatureVerifier = new SignatureVerifierOneFile(); 
     boolean signatureStatus = 
signatureVerifier.verify(signedXmlPath,"C:/Cert.cer"); 
     System.out.println("xml signature validateionis " + signatureStatus); 

    } 
    public boolean verify(String signedXml,String publicKeyFile) { 

     boolean verificationResult = false; 

     try { 

      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
      dbf.setNamespaceAware(true); 
      DocumentBuilder builder = dbf.newDocumentBuilder(); 
      Document doc = builder.parse(signedXml); 
      NodeList nl = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature"); 
      if (nl.getLength() == 0) { 
       throw new IllegalArgumentException("Cannot find Signature element"); 
      } 

      XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM"); 

      DOMValidateContext valContext = new DOMValidateContext(getCertificateFromFile(publicKeyFile).getPublicKey(), nl.item(0)); 
      XMLSignature signature = fac.unmarshalXMLSignature(valContext); 

      verificationResult = signature.validate(valContext); 

     } catch (Exception e) { 
      System.out.println("Error while verifying digital siganature" + e.getMessage()); 
      e.printStackTrace(); 
     } 

     return verificationResult; 
    } 

    private X509Certificate getCertificateFromFile(String certificateFile) throws GeneralSecurityException, IOException { 
     FileInputStream fis = null; 
     try { 
      CertificateFactory certFactory = CertificateFactory.getInstance("X.509", "BC"); 
      fis = new FileInputStream(certificateFile); 
      return (X509Certificate) certFactory.generateCertificate(fis); 
     } finally { 
      if (fis != null) { 
       fis.close(); 
      } 
     } 

    } 
} 

Meine ursprüngliche signierte XML ist wie folgt: -

<OTPResp resCode="25f341e7-8c72-47a6-b49b-46732e7b8494" status="1" ts="2016-03-31T10:54:07.575" txn="20160331052355192"><AadhaarResp>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxBZ2VudE90cFJlc3AgcmV0PSJ5IiB0cz0iMjAxNi0wMy0zMVQxMDo1NzoxMi41MzYrMDU6MzAiIGNvZGU9IjZkZjZhZTY1YzMwNjQzMmVhZTkyNzljYTgxZGNkNmJjIiB0eG49IjI1ZjM0MWU3LThjNzItNDdhNi1iNDliLTQ2NzMyZTdiODQ5NCIvPg==</AadhaarResp><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></CanonicalizationMethod><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></SignatureMethod><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></Transform></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod><DigestValue>vOND//Y2bsHBIkxkUfjH3d/CYC4=</DigestValue></Reference></SignedInfo><SignatureValue>HJG1vPQ4CSycCJ4B065faSeBaHGad9XYDUCOj9a/Fa/bWUUFYOpi9/jxVRCngSJACEIEVwUfcCKs9uUEr3DPcDiTB1UqM9BwUCVL28Tghn/HUSg53IQZziDrI3Ta2VyB7oHEoE/8cloArAbu44gDL/selJDD4ZtAsLAecO3NFiugMG3okV7hGcX50lIDm1on7ziFTxFfL1215gmcCfwJhF/zKI0GVBV6FcCDZxLeY7qMGp0Mj4EzicQm1LIZDHIfVskh97NrWi3MKBAv9dPGOevB3XaVw7dt9nct1VEirZaprM/dl5frCDTuwtmNlZN01dnBGHDCRi/+534mvN4oUQ==</SignatureValue></Signature></OTPResp> 

Mofidied XML, die ich in der Lage bin zu validieren ist, wie folgend

<OTPResp resCode="25f341e7-8c72-47a6-b49b-46732e7b8494" status="1" ts="2016-03-31T10:54:07.575" txn="20160331052355192"><AadhaarResp>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxBZ2VudE90cFJlc3AgcmV0PSJ5IiB0cz0iMjAxNi0wMy0zMVQxMDo1NzoxMi41MzYrMDU6MzAiIGNvZGU9IjZkZjZhZTY1YzMwNjQzMmVhZTkyNzljYTgxZGNkNmJjIiB0eG49IjI1ZjM0MWU3LThjNzItNDdhNi1iNDliLTQ2NzMyZTdiODQ5NCIvPg==</AadhaarResp><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> 
<SignedInfo> 
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></CanonicalizationMethod> 
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></SignatureMethod> 
<Reference URI=""> 
<Transforms> 
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></Transform> 
</Transforms> 
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod> 
<DigestValue>vOND//Y2bsHBIkxkUfjH3d/CYC4=</DigestValue> 
</Reference> 
</SignedInfo> 
<SignatureValue> 
HJG1vPQ4CSycCJ4B065faSeBaHGad9XYDUCOj9a/Fa/bWUUFYOpi9/jxVRCngSJACEIEVwUfcCKs 
9uUEr3DPcDiTB1UqM9BwUCVL28Tghn/HUSg53IQZziDrI3Ta2VyB7oHEoE/8cloArAbu44gDL/se 
lJDD4ZtAsLAecO3NFiugMG3okV7hGcX50lIDm1on7ziFTxFfL1215gmcCfwJhF/zKI0GVBV6FcCD 
ZxLeY7qMGp0Mj4EzicQm1LIZDHIfVskh97NrWi3MKBAv9dPGOevB3XaVw7dt9nct1VEirZaprM/d 
l5frCDTuwtmNlZN01dnBGHDCRi/+534mvN4oUQ== 
</SignatureValue> 
</Signature></OTPResp> 

Ich kann nicht herausfinden, was ich bin falsch machen? Vielen Dank im Voraus.

Antwort

1

Blick auf Ihre XML-Dokumente, der einzige Unterschied, der für mich wichtig ist, ist die tatsächliche <SignatureValue> Inhalt. Obwohl es in Bezug auf die Base64-Sequenz identisch ist, beachten Sie, dass es in Ihrem modifizierten XML Zeilenumbrüche enthält.

Blick durch die XML DSIG spec wir diese finden: http://www.w3.org/TR/xmldsig-core/#sec-SignatureValue

Das SignatureValue Element enthält den aktuellen Wert der digitalen Signatur; es wird immer verschlüsselt base64 [MIME]

Es dann verweist RFC 2045. Hier ist der Link: http://www.ietf.org/rfc/rfc2045.txt

Wenn man durch Abschnitt 6.8, der die Base64-Codierung gibt an, es erwähnt:

Der codierte Ausgabestrom muss in Zeilen von statt jeweils 76 Zeichen dargestellt werden.

Und genau das haben Sie in Ihrem modifizierten XML getan. Wenn Sie das XML in ein DOM umwandeln, wird der Textinhalt der Elemente genau wie im Eingabedokument beibehalten, einschließlich der Zeilenumbrüche. Meine Vermutung ist, dass der Base64-Decoder, der von den Java-XML-Crypto-Paketen verwendet wird, sich strikt an die Spezifikation hält und die Signatur in Ihrem ursprünglichen XML-Dokument nicht vollständig analysieren kann.

Ich schlage vor, dass nach dem Erhalt Ihrer XMLSignature in Methode verify, versuchen Sie getSignatureValue() darauf aufrufen. Dies sollte Ihnen eine XMLSignature.SignatureValue geben. Versuchen Sie, das Byte-Array daraus zu ermitteln. Wenn es leer ist, schneidet zu früh ab, die XMLSignature.SignatureValue Failes ganz zu bekommen, das oben genannte ist wahrscheinlich das Problem.

+1

@ G_H Ich stimme dir zu "Der kodierte Ausgabestrom muss in Zeilen mit nicht mehr als 76 Zeichen dargestellt werden", eigentlich ist die Verifikationsquelle korrekt, das Problem war im Lesemechanismus von signedXML, beim Lesen von signedXML wurde Newline gelöscht Charakter. – dpilwal