2016-11-29 41 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