嵌入 x509 证书的 xades4j 验证问题
xades4j verification issue with embeded x509 certificate
我正在使用智能卡进行签名和 SunMSCAPI 提供程序以及 windows 密钥库。
使用 xades4j 1.3.2 版本我唱了一个 xml 文件如下,它工作完美,证书也嵌入在 KeyInfo 的 xml 文件中,
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 中建议的方法,但也出现了同样的错误。
请指出我做错了什么。
从错误来看,它似乎与混淆安全提供程序有关,可能是因为您从 "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);
我正在使用智能卡进行签名和 SunMSCAPI 提供程序以及 windows 密钥库。 使用 xades4j 1.3.2 版本我唱了一个 xml 文件如下,它工作完美,证书也嵌入在 KeyInfo 的 xml 文件中,
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 中建议的方法,但也出现了同样的错误。
请指出我做错了什么。
从错误来看,它似乎与混淆安全提供程序有关,可能是因为您从 "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);