2017-06-08 77 views
1

我使用智能卡進行簽名和SunMSCAPI提供程序和Windows密鑰存儲。 使用xades4j 1.3.2版本我唱歌的xml文件,如下所示,它是完美的工作和證書也包埋在密鑰信息的XML文件,xades4j驗證問題與嵌入x509證書

private Document signXMLData(Document doc) { 
     try { 
      XadesSigningProfile p; 
      p = new XadesBesSigningProfile(keyingDataProvider).withSignaturePropertiesProvider(new SignaturePropertiesProvider() { 
       @Override 
       public void provideProperties(SignaturePropertiesCollector signedPropsCol) { 
        signedPropsCol.setSignerRole(new SignerRoleProperty(SignerRole)); 
        signedPropsCol.setSignatureProductionPlace(new SignatureProductionPlaceProperty(City, State, PostalCode, Country)); 
        signedPropsCol.setSigningTime(new SigningTimeProperty()); 
       } 
      }); 
      XadesSigner signer = p.newSigner(); 
      Element elemToSign = doc.getDocumentElement(); 
      new Enveloped(signer).sign(elemToSign); 
      Log.LogOperation("XML signing completed successfully."); 
     } catch (Exception ex) { 
      Log.LogException(ex); 
      doc = null; 
     } 
     return doc; 
    } 

但我的問題是,在使用下面的代碼驗證,我收到以下錯誤,

代碼

public boolean VerifyXMLSign(String data) throws ParserConfigurationException, SAXException, IOException, TransformerConfigurationException, TransformerException, Exception { 
     InputSource isIn = new InputSource(); 
     isIn.setCharacterStream(new StringReader(data)); 

     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
     dbf.setNamespaceAware(true); 
     Document doc = dbf.newDocumentBuilder().parse(isIn); 
     //Document doc = dbf.newDocumentBuilder().parse(new FileInputStream("c:/xml.xml")); 
     DOMHelper.useIdAsXmlId(doc.getDocumentElement()); 

     KeyStore ks = KeyStore.getInstance("Windows-ROOT", "SunMSCAPI"); 
     ks.load(null, null); 

     X509Certificate x509Certificate = null; 
     PublicKey key = null; 
     DOMValidateContext valContext = new DOMValidateContext(new X509KeySelector(ks), getSigElement(doc)); 
     XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM"); 
     fac.newDigestMethod(DigestMethod.SHA256, null); 
     XMLSignature signature = fac.unmarshalXMLSignature(valContext); 
     KeyInfo keyInfo = signature.getKeyInfo(); 
     Iterator hKeyInfo = keyInfo.getContent().iterator(); 
     while (hKeyInfo.hasNext()) { 
      XMLStructure hX509Data = (XMLStructure) hKeyInfo.next(); 
      if (!(hX509Data instanceof X509Data)) { 
       continue; 
      } 
      X509Data x509Data = (X509Data) hX509Data; 
      Iterator hX509Certificate = x509Data.getContent().iterator(); 
      while (hX509Certificate.hasNext()) { 
       Object oX509Certificate = hX509Certificate.next(); 
       if (!(oX509Certificate instanceof X509Certificate)) { 
        continue; 
       } 
       x509Certificate = ((X509Certificate) oX509Certificate); 
       key = x509Certificate.getPublicKey(); 
      } 
     } 

     //FileSystemDirectoryCertStore certStore = createDirectoryCertStore("my"); 
     CertificateFactory cf = CertificateFactory.getInstance("X509"); 
     ks.setCertificateEntry("df", x509Certificate); 

     CertificateValidationProvider validationProviderMySigs = new PKIXCertificateValidationProvider(ks, false, null);//certStore.getStore()); 
     XadesVerificationProfile instance = new XadesVerificationProfile(validationProviderMySigs); 
     XadesVerifier verifier = instance.newVerifier(); 
     XAdESVerificationResult r = verifier.verify(getSigElement(doc), null); 

     System.out.println(r.getSignatureForm()); 
     System.out.println(r.getSignatureAlgorithmUri()); 
     System.out.println(r.getSignedDataObjects().size()); 
     System.out.println(r.getQualifyingProperties().all().size()); 
     return false; 
    } 

錯誤

Log Date Time:- 2017/06/08 14:38:01 
xades4j.utils.XadesProfileResolutionException: com.google.inject.internal.ComputationException: java.lang.SecurityException: class "org.bouncycastle.cms.jcajce.JcaX509CertSelectorConverter"'s signer information does not match signer information of other classes in the same package 
    at xades4j.utils.XadesProfileCore.getInstance(XadesProfileCore.java:223) 
    at xades4j.verification.XadesVerificationProfile.newVerifier(XadesVerificationProfile.java:147) 
    at slr.DigitalVerification.VerifyXMLSign(DigitalVerification.java:163) 
    at slr.Handlers$OpenEVerifierHandler.handle(Handlers.java:186) 
    at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77) 
    at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83) 
    at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:80) 
    at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:677) 
    at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77) 
    at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647) 
    at sun.net.httpserver.ServerImpl$DefaultExecutor.execute(ServerImpl.java:158) 
    at sun.net.httpserver.ServerImpl$Dispatcher.handle(ServerImpl.java:433) 
    at sun.net.httpserver.ServerImpl$Dispatcher.run(ServerImpl.java:398) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: com.google.inject.internal.ComputationException: .......... 

我嘗試了https://github.com/luisgoncalves/xades4j/issues/37中建議的方法,但也給出了相同的錯誤。

請建議我做錯了什麼。

回答

2

從它似乎與混合了安全提供商,可能是因爲你從「SunMSCAPI」創建KeyStore,然後X509Certificate通過在XML簽名,這似乎是充氣城堡使用的供應商創造了一種錯誤。

無論如何,由於簽名證書包含在簽名中,因此您不需要解析XML並查找它xades4j的目的是爲了讓你遠離那些東西。 xades4j將收集KeyInfo中的所有證書,並在驗證簽名證書時使用它們構建鏈(在此情況下可能只有一個)。

如果所有的中間證書,並驗證你的歌唱證書所需的根證書,無論是在Windows的ROOT或內KeyInfo,你只需要創建可信根KeyStore,並把它傳遞給PKIXCertificateValidationProvider原樣。如果需要包含其他證書,則可以使用PKIXCertificateValidationProvider構造函數的參數CertStore。因此,總而言之,您應該需要的所有代碼是第一個和最後一個部分。例如:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
dbf.setNamespaceAware(true); 
Document doc = dbf.newDocumentBuilder().parse(isIn); 
DOMHelper.useIdAsXmlId(doc.getDocumentElement()); 

KeyStore ks = KeyStore.getInstance("Windows-ROOT", "SunMSCAPI"); 
ks.load(null, null); 
CertificateValidationProvider validationProviderMySigs = new PKIXCertificateValidationProvider(ks, false, null); 
XadesVerificationProfile instance = new XadesVerificationProfile(validationProviderMySigs); 
XadesVerifier verifier = instance.newVerifier(); 
XAdESVerificationResult r = verifier.verify(getSigElement(doc), null); 
+0

謝謝你的寶貴意見。我嘗試了以上所有可能性。 X509Certificate由BC創建。我使用我的問題中的代碼嘗試密鑰庫值BKS,JKS和導入的證書。但是在所有情況下,XadesVerifier verifier = instance.newVerifier();都會出現同樣的錯誤。我也嘗試了上面的代碼,但那也拋出了相同的錯誤。有沒有其他解決方法? – Matt

+0

如果您不提供'KeyStore.getInstance()'調用的提供程序會怎麼樣? – lgoncalves

+0

如果你的意思是與KeyStore.DefaultProvider()相同的錯誤。 getinstance正在期待一些價值。 – Matt