签署 XML 时出现 ResourceResolverException
ResourceResolverException while signing an XML
我正在拼命尝试使用 X509 证书签署 XML 文档。
我必须在我的文档中签署多个元素,所以我给出了我的 SignedInfo 的参考列表。
我面临的问题发生在签名本身。我收到一个异常,说它无法解析具有我提供的 ID 的元素。
在研究寻找解决方案时,我偶然发现了这张票(这是 OpenJDK 1.7 的错误):https://bugs.openjdk.java.net/browse/JDK-8017171
我正在使用 Oracle JDK 1.8,但仍然有问题。
代码 :
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(unsignedXml));
List<Reference> refs = new ArrayList<Reference>();
refs.add(fac.newReference(
"#TS",
fac.newDigestMethod("http://www.w3.org/2000/09/xmldsig#sha1", null),
Collections.singletonList(fac.newTransform("http://www.w3.org/2001/10/xml-exc-c14n#",(TransformParameterSpec) null)),
null, null));
SignedInfo si = fac.newSignedInfo(
fac.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE,
(C14NMethodParameterSpec) null),
fac.newSignatureMethod("http://www.w3.org/2000/09/xmldsig#rsa-sha1", null),
refs);
FileInputStream input = new FileInputStream(keystoreFile);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(input, password.toCharArray());
Key key = ks.getKey(alias, password.toCharArray());
if (key instanceof PrivateKey) {
Certificate cert = ks.getCertificate(alias);
PublicKey publicKey = cert.getPublicKey();
keyPair = new KeyPair(publicKey, (PrivateKey) key);
}
KeyInfoFactory kif = fac.getKeyInfoFactory();
KeyValue kv = kif.newKeyValue(keyPair.getPublic());
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));
DOMSignContext dsc = new DOMSignContext(keyPair.getPrivate(), doc.getDocumentElement());
XMLSignature signature = fac.newXMLSignature(si, ki);
signature.sign(dsc);
OutputStream out = new FileOutputStream(signedXml);
异常:
Exception in thread "main" javax.xml.crypto.dsig.XMLSignatureException: javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID TS
at org.jcp.xml.dsig.internal.dom.DOMReference.dereference(DOMReference.java:431)
at org.jcp.xml.dsig.internal.dom.DOMReference.digest(DOMReference.java:359)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.digestReference(DOMXMLSignature.java:496)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(DOMXMLSignature.java:379)
at testsig.testsig.Signature.sign(Signature.java:131)
at testsig.testsig.App.main(App.java:32)
Caused by: javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID TS
at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:134)
at org.jcp.xml.dsig.internal.dom.DOMReference.dereference(DOMReference.java:425)
... 5 more
Caused by: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID TS
at com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverFragment.engineResolveURI(ResolverFragment.java:89)
at com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver.resolve(ResourceResolver.java:313)
at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:126)
... 6 more
javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID TS
at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:134)
at org.jcp.xml.dsig.internal.dom.DOMReference.dereference(DOMReference.java:425)
at org.jcp.xml.dsig.internal.dom.DOMReference.digest(DOMReference.java:359)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.digestReference(DOMXMLSignature.java:496)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(DOMXMLSignature.java:379)
at testsig.testsig.Signature.sign(Signature.java:131)
at testsig.testsig.App.main(App.java:32)
Caused by: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID TS
at com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverFragment.engineResolveURI(ResolverFragment.java:89)
at com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver.resolve(ResourceResolver.java:313)
at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:126)
... 6 more
我的问题至少可以通过以下问题的一个答案来解决:
有解决方法吗?
是否有其他签署 XML 文件的方法?
此致
我最终找到了解决方法而不是解决方案。我的想法是使用 XMLHelper 使用 DOM 获取我需要的元素,从元素中获取 ID Attr。然后我将带有 setIdAttributeNode() 的属性添加到我的元素中。
以这种方式操作元素时,向 XMLSignatureFactory.
添加新引用时不会抛出异常
NodeList list = doc.getElementsByTagName("wsu:Timestamp");
Node node = list.item(0);
Element tempEl = XMLHelper.getChildElementsByTagName(doc.getDocumentElement(), "Header").get(0);
Element securityElement = XMLHelper.getChildElementsByTagName(tempEl, "Security").get(0);
tempEl = XMLHelper.getChildElementsByTagName(securityElement, "Assertion").get(0);
Attr attr = (Attr)tempEl.getAttributes().getNamedItem("AssertionID");
tempEl.setIdAttributeNode(attr, true);
String ref = "#" + attr.getValue();
List<Reference> refs = new ArrayList<Reference>();
refs.add(fac.newReference(
ref,
fac.newDigestMethod("http://www.w3.org/2000/09/xmldsig#sha1", null),
Collections.singletonList(fac.newTransform("http://www.w3.org/2001/10/xml-exc-c14n#",(TransformParameterSpec) null)),
null,
null));
我认为这不是一个理想的解决方案,因为它与 XML 的 DOM 关系太大。但我想这是我能找到的唯一解决方案,可以让它工作并解决 JDK.
中的已知错误
我正在拼命尝试使用 X509 证书签署 XML 文档。 我必须在我的文档中签署多个元素,所以我给出了我的 SignedInfo 的参考列表。
我面临的问题发生在签名本身。我收到一个异常,说它无法解析具有我提供的 ID 的元素。
在研究寻找解决方案时,我偶然发现了这张票(这是 OpenJDK 1.7 的错误):https://bugs.openjdk.java.net/browse/JDK-8017171
我正在使用 Oracle JDK 1.8,但仍然有问题。
代码 :
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(unsignedXml));
List<Reference> refs = new ArrayList<Reference>();
refs.add(fac.newReference(
"#TS",
fac.newDigestMethod("http://www.w3.org/2000/09/xmldsig#sha1", null),
Collections.singletonList(fac.newTransform("http://www.w3.org/2001/10/xml-exc-c14n#",(TransformParameterSpec) null)),
null, null));
SignedInfo si = fac.newSignedInfo(
fac.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE,
(C14NMethodParameterSpec) null),
fac.newSignatureMethod("http://www.w3.org/2000/09/xmldsig#rsa-sha1", null),
refs);
FileInputStream input = new FileInputStream(keystoreFile);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(input, password.toCharArray());
Key key = ks.getKey(alias, password.toCharArray());
if (key instanceof PrivateKey) {
Certificate cert = ks.getCertificate(alias);
PublicKey publicKey = cert.getPublicKey();
keyPair = new KeyPair(publicKey, (PrivateKey) key);
}
KeyInfoFactory kif = fac.getKeyInfoFactory();
KeyValue kv = kif.newKeyValue(keyPair.getPublic());
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));
DOMSignContext dsc = new DOMSignContext(keyPair.getPrivate(), doc.getDocumentElement());
XMLSignature signature = fac.newXMLSignature(si, ki);
signature.sign(dsc);
OutputStream out = new FileOutputStream(signedXml);
异常:
Exception in thread "main" javax.xml.crypto.dsig.XMLSignatureException: javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID TS
at org.jcp.xml.dsig.internal.dom.DOMReference.dereference(DOMReference.java:431)
at org.jcp.xml.dsig.internal.dom.DOMReference.digest(DOMReference.java:359)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.digestReference(DOMXMLSignature.java:496)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(DOMXMLSignature.java:379)
at testsig.testsig.Signature.sign(Signature.java:131)
at testsig.testsig.App.main(App.java:32)
Caused by: javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID TS
at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:134)
at org.jcp.xml.dsig.internal.dom.DOMReference.dereference(DOMReference.java:425)
... 5 more
Caused by: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID TS
at com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverFragment.engineResolveURI(ResolverFragment.java:89)
at com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver.resolve(ResourceResolver.java:313)
at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:126)
... 6 more
javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID TS
at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:134)
at org.jcp.xml.dsig.internal.dom.DOMReference.dereference(DOMReference.java:425)
at org.jcp.xml.dsig.internal.dom.DOMReference.digest(DOMReference.java:359)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.digestReference(DOMXMLSignature.java:496)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(DOMXMLSignature.java:379)
at testsig.testsig.Signature.sign(Signature.java:131)
at testsig.testsig.App.main(App.java:32)
Caused by: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID TS
at com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverFragment.engineResolveURI(ResolverFragment.java:89)
at com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver.resolve(ResourceResolver.java:313)
at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:126)
... 6 more
我的问题至少可以通过以下问题的一个答案来解决: 有解决方法吗? 是否有其他签署 XML 文件的方法?
此致
我最终找到了解决方法而不是解决方案。我的想法是使用 XMLHelper 使用 DOM 获取我需要的元素,从元素中获取 ID Attr。然后我将带有 setIdAttributeNode() 的属性添加到我的元素中。 以这种方式操作元素时,向 XMLSignatureFactory.
添加新引用时不会抛出异常NodeList list = doc.getElementsByTagName("wsu:Timestamp");
Node node = list.item(0);
Element tempEl = XMLHelper.getChildElementsByTagName(doc.getDocumentElement(), "Header").get(0);
Element securityElement = XMLHelper.getChildElementsByTagName(tempEl, "Security").get(0);
tempEl = XMLHelper.getChildElementsByTagName(securityElement, "Assertion").get(0);
Attr attr = (Attr)tempEl.getAttributes().getNamedItem("AssertionID");
tempEl.setIdAttributeNode(attr, true);
String ref = "#" + attr.getValue();
List<Reference> refs = new ArrayList<Reference>();
refs.add(fac.newReference(
ref,
fac.newDigestMethod("http://www.w3.org/2000/09/xmldsig#sha1", null),
Collections.singletonList(fac.newTransform("http://www.w3.org/2001/10/xml-exc-c14n#",(TransformParameterSpec) null)),
null,
null));
我认为这不是一个理想的解决方案,因为它与 XML 的 DOM 关系太大。但我想这是我能找到的唯一解决方案,可以让它工作并解决 JDK.
中的已知错误