2016-11-29 370 views
0

我使用xades4j和我得到這個例外試圖驗證簽名時的一部分,一個或多個證書:錯誤驗證簽名時:SigningCertificate屬性包含不屬於證書路徑

xades4j.verification.SigningCertificateCertsNotInCertPathException: Verification failed for property 'SigningCertificate': SigningCertificate property contains one or more certificates that are not part of the certification path. 

這裏我的代碼簽名:

public File sign(final X509Certificate x509, final PrivateKey priv, final Element elemToSign, final Document doc, final String fileName, final com.softexpert.crypto.document.Document document, List<X509Certificate> chain) throws Exception { 
    final KeyingDataProvider kp = new SEDirectKeyingDataProvider(x509, priv, chain); 
    XadesSigningProfile profile = new XadesBesSigningProfile(kp); 
    final SESignaturePropertiesProvider propProv = this.getPropertiesProvider(document); 

    profile = profile.withSignaturePropertiesProvider(propProv); 
    profile = profile.withAlgorithmsProvider(AlgorithmsProvider.class); 
    profile = profile.withTimeStampTokenProvider(TimeStampTokenProvider.class); 

    final SignerBES signer = (SignerBES) profile.newSigner(); 
    final IndividualDataObjsTimeStampProperty dataObjsTimeStamp = new IndividualDataObjsTimeStampProperty(); 
    final DataObjectDesc obj = new EnvelopedXmlObject(elemToSign.getFirstChild()).withDataObjectTimeStamp(dataObjsTimeStamp); 

    AllDataObjsCommitmentTypeProperty commitment = null; 
    if (document.isProofOfOrigin() != null && document.isProofOfOrigin()) { 
     commitment = AllDataObjsCommitmentTypeProperty.proofOfOrigin(); 
    } else { 
     commitment = AllDataObjsCommitmentTypeProperty.proofOfReceipt(); 
    } 

    SignedDataObjects dataObjs = new SignedDataObjects(obj).withCommitmentType(commitment); 
    dataObjs = dataObjs.withDataObjectsTimeStamp(); 

    signer.sign(dataObjs, elemToSign); 
    return this.outputDocument(doc, fileName); 
} 

private SESignaturePropertiesProvider getPropertiesProvider(com.softexpert.crypto.document.Document document) { 
    SESignaturePropertiesProvider propertiesProvider = new SESignaturePropertiesProvider(); 

    if (document.getRole() != null) { 
     final SignerRoleProperty signerRole = new SignerRoleProperty().withClaimedRole(document.getRole()); 
     propertiesProvider.setSignerRole(signerRole); 
    } 
    final SigningTimeProperty signingTime = new SigningTimeProperty(); 
    propertiesProvider.setSigningTime(signingTime); 

    if (document.getLocalityName() != null && document.getCountry() != null) { 
     final SignatureProductionPlaceProperty signatureProductionPlaceProperty = new SignatureProductionPlaceProperty(document.getLocalityName(), document.getCountry()); 
     propertiesProvider.setSignatureProductionPlaceProperty(signatureProductionPlaceProperty); 
    } 

    return propertiesProvider; 
} 

private File outputDocument(final Document doc, String fileName) throws Exception { 
    if (!fileName.endsWith(".dsg")) { 
     fileName += ".dsg"; 
    } 

    FileOutputStream out = null; 
    File f = null; 
    try { 
     final TransformerFactory tf = TransformerFactory.newInstance(); 
     f = new File(fileName); 
     if (!f.exists()) { 
      new File(f.getParent()).mkdirs(); 
      f.createNewFile(); 
     } 
     out = new FileOutputStream(f); 
     tf.newTransformer().transform(new DOMSource(doc), new StreamResult(out)); 
    } finally { 
     if(out != null) { 
      try { 
       out.close(); 
      } catch(IOException e) {} 
     } 
    } 

    return f; 
} 

,這裏是我的代碼來驗證:

try { 
    final org.w3c.dom.Document doc = this.getDomDocument(); 
    doc.getDocumentElement().normalize(); 

    // Find Signature element 
    final NodeList nl = doc.getElementsByTagNameNS(javax.xml.crypto.dsig.XMLSignature.XMLNS, "Signature"); 
    final CertStore crls = ... // get CRLS 
    final CertStore certs = ... // get intermediate certs     
    final KeyStore ks = ... // get KS from Windows-ROOT 
    final PKIXCertificateValidationProvider cvp = new PKIXCertificateValidationProvider(ks, false, certs, crls); 
    final XadesVerificationProfile p = new XadesVerificationProfile(cvp); 
    p.withTimeStampTokenVerifier(SETimeStampTokenProvider.class); 
    final Element signatureElemntNode = (Element) nl.item(0); 
    final XadesVerifier verifier = p.newVerifier(); 
    XAdESVerificationResult verificationResult = verifier.verify(signatureElemntNode, null); // exception is thrown here 
} 

我搜索了這個錯誤,但找不到任何幫助我的東西。我怎樣才能解決這個錯誤?

在此先感謝。

回答

0

基於lgoncalve's answer,我已經改變了我的代碼一點點:

簽約:而不是使用證書的整個鏈條簽約,我只使用簽名證書,從而使SEDirectKeyingDataProvider.getSigningCertificateChain()只返回簽約CERT)。通過這種方法,我的xml現在只有一個屬性<SigningCertificate>,而不再是整個鏈。

驗證:用我上面的評論的辦法,我驗證證書時,有一個問題:在我的XML中,只有簽名證書正在財產<ds:X509Certificate>引用的,所以我無法驗證的整個鏈條。爲了解決這個問題,我不得不使用此代碼後調用XAdESVerificationResult result = verifier.verify(signatureElemntNode, null);

for(X509Certificate cert : chain) {   
    result.getSignature().addKeyInfo(cert); 
} 

使用此代碼,該鏈的每個證書是由物業<ds:X509Certificate>引用,我可以得到整個產業鏈,以驗證它是否值得信賴與否。

1

如錯誤消息所述,您的SigningCertificate屬性可能具有不屬於證書鏈一部分的證書。此規則在XAdES規範中定義。

關於簽名操作:

  • ,您在您的自定義SEDirectKeyingDataProvidergetSigningCertificateChain方法返回什麼證書嗎?
  • SigningCertificate屬性的最終XML中的證書元素是什麼?

返回的證書應該都是唱歌證書鏈的一部分,但是您不需要返回完整的鏈。您甚至可以返回僅包含簽名證書的列表,只要您使所有中間證書都可用於驗證(您似乎正在執行此操作)即可。如果你這樣做,SigningCertificate屬性的驗證應該通過。

+0

'getSigningCertificateChain'返回:CN = AC CASH V2,OU =根證書頒發機構巴西V2,O = ICP-巴西,C = BR CN =根證書頒發機構巴西V2,信息技術的OU =研究所 - ITI ,O = ICP-巴西,C = BR CN = AC CASH PF V2,OU =儲蓄經濟學刊聯邦,O = ICP-巴西,C = BR CN =證書頒發機構巴西根V2,OU =研究院信息技術 - ITI,ICP-巴西O = C = BR「 和財產SigningCertificate' 4示出了這些證書粘貼..我不能限制它becase的字符 – lucasdc

+0

certs'的」(包含中間證書可變)表示的那些證書4也。我注意到闕C = BR CN =根證書頒發機構巴西V2,信息技術的OU =研究所 - ITI,O = ICP-巴西,C = BR出現了兩次。你以爲闕,這可能是一個問題嗎? – lucasdc

+0

你似乎有重複的證書。驗證將失敗,因爲那([見這裏](https://github.com/luisgoncalves/xades4j/blob/master/src/main/java/xades4j/verification/SigningCertificateVerifier.java#L112))。注闕返回上'getSigningCertificateChain'重複是不正確的(和圖書館好好嘗試一下檢查)。也許驗證可能是一個有點聰明,但我認爲有重複的不是非常正確的。希望這有助於 – lgoncalves