Java Xades4j验证签名Xades-EPES:错误的XML签名
我正在使用Xades4J开发一个简单的Java程序,用XADES-EPES对XML进行签名和验证。签名过程似乎工作正常,并生成了有效的签名XML(尽管我们不需要其中的SignaturePolicyIdentifier部分) *options arguments来自joptsimple库,用于解析参数 这是我的符号功能:Java Xades4j验证签名Xades-EPES:错误的XML签名,java,xades4j,Java,Xades4j,我正在使用Xades4J开发一个简单的Java程序,用XADES-EPES对XML进行签名和验证。签名过程似乎工作正常,并生成了有效的签名XML(尽管我们不需要其中的SignaturePolicyIdentifier部分) *options arguments来自joptsimple库,用于解析参数 这是我的符号功能: void signXML(OptionSet options) { KeyingDataProvider kp; try { Signature
void signXML(OptionSet options) {
KeyingDataProvider kp;
try {
SignaturePolicyInfoProvider policyInfoProvider = new SignaturePolicyInfoProvider() {
public SignaturePolicyBase getSignaturePolicy() {
return new SignaturePolicyIdentifierProperty(
new ObjectIdentifier("oid:/1.2.4.0.9.4.5", IdentifierType.OIDAsURI, "Policy description"),
new ByteArrayInputStream("Test policy input stream".getBytes()))
.withLocationUrl("http://www.example.com/policy");
}
};
kp = new FileSystemKeyStoreKeyingDataProvider("pkcs12", options.valueOf("certificate").toString(),
new FirstCertificateSelector(), new DirectPasswordProvider(options.valueOf("password").toString()),
new DirectPasswordProvider(options.valueOf("password").toString()), false);
// SignaturePolicyInfoProvider spi = new
XadesSigningProfile p = new XadesEpesSigningProfile(kp, policyInfoProvider);
p.withBasicSignatureOptionsProvider(new SignatureOptionsProvider());
XadesSigner signer = p.newSigner();
// open file
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = null;
builder = factory.newDocumentBuilder();
Document doc1 = builder.parse(new File(options.valueOf("input").toString()));
Element elemToSign = doc1.getDocumentElement();
// sign whole document
new Enveloped(signer).sign(elemToSign);
// save output file
Transformer transformer = TransformerFactory.newInstance().newTransformer();
Result output = new StreamResult(new File(options.valueOf("output").toString()));
Source input = new DOMSource(doc1);
transformer.transform(input, output);
} catch (KeyStoreException | ParserConfigurationException | SAXException | IOException | XAdES4jException
| TransformerException e) {
e.printStackTrace();
}
}
这是它创建的一个示例签名:(具有
在base64值的每行末尾?)
如果有人能告诉我问题所在,我将不胜感激。谢谢
更新
检查堆栈跟踪后,我发现以下异常:
xades4j.xml.unmarshalling.UnmarshalException: Bad XML signature
at xades4j.verification.XadesVerifierImpl.verify(XadesVerifierImpl.java:130)
at com.qprotex.Main.verifyXML(Main.java:190)
at com.qprotex.Main.<init>(Main.java:99)
at com.qprotex.Main.main(Main.java:81)
Caused by: org.apache.xml.security.exceptions.XMLSecurityException: Cannot create a null:null from a http://www.w3.org/2000/09/xmldsig#:Signature element
java.lang.NullPointerException
at xades4j.xml.unmarshalling.FromXmlSignaturePolicyConverter.getLocationUrl(FromXmlSignaturePolicyConverter.java:71)
at xades4j.xml.unmarshalling.FromXmlSignaturePolicyConverter.convertFromObjectTree(FromXmlSignaturePolicyConverter.java:64)
at xades4j.xml.unmarshalling.FromXmlSignaturePolicyConverter.convertFromObjectTree(FromXmlSignaturePolicyConverter.java:1)
at xades4j.xml.unmarshalling.UnmarshallerModule.convertProperties(UnmarshallerModule.java:64)
at xades4j.xml.unmarshalling.DefaultQualifyingPropertiesUnmarshaller.unmarshalProperties(DefaultQualifyingPropertiesUnmarshaller.java:83)
at xades4j.verification.XadesVerifierImpl.verify(XadesVerifierImpl.java:175)
at com.qprotex.Main.verifyXML(Main.java:190)
at com.qprotex.Main.<init>(Main.java:99)
at com.qprotex.Main.main(Main.java:81)
但这不起作用,我得到了一个“xades4j.providers.CannotBuildCertificationPathException:信任锚密钥库没有受信任的证书条目”异常
FileInputStream fis = new FileInputStream(options.valueOf("certificate").toString());
KeyStore ks = KeyStore.getInstance("pkcs12");
ks.load(fis, options.valueOf("password").toString().toCharArray());
fis.close();
CertificateValidationProvider provider = new PKIXCertificateValidationProvider(ks, false);
- 您可能在库中发现了一个bug。我创建了一个跟踪这个。如果你想订阅的话
- 如果它真的是一个bug,那么它一定是在v1.4.0中引入的,所以现在,您可以尝试使用v1.3.2
- 既然你说你不需要签名身份识别器,为什么你要使用XAdES EPES?您可以使用
生成XAdES-BES签名xadesbessingprofile
- 假设您仍然需要XAdES EPE,请注意,您需要指定如何使用
上的XadesVerificationProfile
获取签名策略文档进行验证withPolicyDocumentProvider
- 我不确定base64字符串后的编码字符,但让我们拭目以待,看看这是否是一个问题
例外信息似乎很清楚。您的目标是使用签名证书作为信任锚?密钥库上的条目类型需要是“信任锚”。我想您应该添加两个条目:一个带有cert/key(类型“certificate”),另一个只带有cert(类型“trust-anchor”)。或者使用单独的密钥库。感谢您的帮助。我确实将我的签名函数改为使用XadesBesSigningProfile,现在它可以工作了,但我有一个小问题。请检查我的更新2。谢谢,你解决了吗?我也有类似的问题
java.lang.NullPointerException
at xades4j.xml.unmarshalling.FromXmlSignaturePolicyConverter.getLocationUrl(FromXmlSignaturePolicyConverter.java:71)
at xades4j.xml.unmarshalling.FromXmlSignaturePolicyConverter.convertFromObjectTree(FromXmlSignaturePolicyConverter.java:64)
at xades4j.xml.unmarshalling.FromXmlSignaturePolicyConverter.convertFromObjectTree(FromXmlSignaturePolicyConverter.java:1)
at xades4j.xml.unmarshalling.UnmarshallerModule.convertProperties(UnmarshallerModule.java:64)
at xades4j.xml.unmarshalling.DefaultQualifyingPropertiesUnmarshaller.unmarshalProperties(DefaultQualifyingPropertiesUnmarshaller.java:83)
at xades4j.verification.XadesVerifierImpl.verify(XadesVerifierImpl.java:175)
at com.qprotex.Main.verifyXML(Main.java:190)
at com.qprotex.Main.<init>(Main.java:99)
at com.qprotex.Main.main(Main.java:81)
KeyStore trustAnchors = KeyStore.getInstance("Windows-ROOT");
trustAnchors.load(null);
CertificateValidationProvider provider = new PKIXCertificateValidationProvider(trustAnchors, false);
FileInputStream fis = new FileInputStream(options.valueOf("certificate").toString());
KeyStore ks = KeyStore.getInstance("pkcs12");
ks.load(fis, options.valueOf("password").toString().toCharArray());
fis.close();
CertificateValidationProvider provider = new PKIXCertificateValidationProvider(ks, false);