Recently with the bank to do the interface, the XML file needs to do a sign-and-check operation, the local development environment is the version of Mac 10.10,JDK is 1.6.0.65. A little sign code, has been error, but a long time can not find a solution, the online information is very small, the error record as follows:
1 javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID FIQReq
2 Exception in thread "main" java.lang.RuntimeException: javax.xml.crypto.dsig.XMLSignatureException: javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID FIQReq
3 at util.xml.XMLSigner.sign(XMLSigner.java:111)
4 at test.TestSign.main(TestSign.java:34)
5 Caused by: javax.xml.crypto.dsig.XMLSignatureException: javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID FIQReq
6 at org.jcp.xml.dsig.internal.dom.DOMReference.dereference(DOMReference.java:412)
7 at org.jcp.xml.dsig.internal.dom.DOMReference.digest(DOMReference.java:338)
8 at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.digestReference(DOMXMLSignature.java:471)
9 at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(DOMXMLSignature.java:367)
10 at util.xml.XMLSigner.sign(XMLSigner.java:108)
11 ... 1 more
12 Caused by: javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID FIQReq
13 at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:124)
14 at org.jcp.xml.dsig.internal.dom.DOMReference.dereference(DOMReference.java:404)
15 ... 5 more
16 Caused by: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID FIQReq
17 at com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverFragment.engineResolve(ResolverFragment.java:90)
18 at com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver.resolve(ResourceResolver.java:283)
19 at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:117)
20 ... 6 more
The only thing that's more right is this bug record: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8017171
The problem is caused by the id attribute of the XML document node can not be located to the corresponding node, so when the signature will be prompted to not resolve the ID, then how can I let him according to the ID of my node, parse and locate the corresponding node, let us first look at the code in my project:
The first is the XML file to be signed:
1 javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID FIQReq
2 Exception in thread "main" java.lang.RuntimeException: javax.xml.crypto.dsig.XMLSignatureException: javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID FIQReq
3 at util.xml.XMLSigner.sign(XMLSigner.java:111)
4 at test.TestSign.main(TestSign.java:34)
5 Caused by: javax.xml.crypto.dsig.XMLSignatureException: javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID FIQReq
6 at org.jcp.xml.dsig.internal.dom.DOMReference.dereference(DOMReference.java:412)
7 at org.jcp.xml.dsig.internal.dom.DOMReference.digest(DOMReference.java:338)
8 at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.digestReference(DOMXMLSignature.java:471)
9 at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(DOMXMLSignature.java:367)
10 at util.xml.XMLSigner.sign(XMLSigner.java:108)
11 ... 1 more
12 Caused by: javax.xml.crypto.URIReferenceException: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID FIQReq
13 at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:124)
14 at org.jcp.xml.dsig.internal.dom.DOMReference.dereference(DOMReference.java:404)
15 ... 5 more
16 Caused by: com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID FIQReq
17 at com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverFragment.engineResolve(ResolverFragment.java:90)
18 at com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver.resolve(ResourceResolver.java:283)
19 at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:117)
20 ... 6 more
Code to add:
1 public void sign(Document doc, PrivateKey privateKey, String referenceId, Node signNode) {
2 if(!isInit){
3 throw new RuntimeException("XMLSigner is not init !");
4 }
5 try{
6 //Create a <Reference> element that references the node with the specified ID, the <Signature> element will not be counted
7 Reference refToRootDoc = signFactory.newReference("#"+referenceId,
8 sha1DigMethod, Collections.singletonList(envelopedTransform), null, null);
9 //Create a <SignedInfo> element
10 SignedInfo signedInfo = signFactory.newSignedInfo(c14nWithCommentMethod,
11 rsa_sha1SigMethod, Collections.singletonList(refToRootDoc));
12 //Create a signature instance
13 XMLSignature signature = signFactory.newXMLSignature(signedInfo, null);
14 //Create a signature context, generate on the specified node
15 DOMSignContext dsc = new DOMSignContext(privateKey, signNode);
16 / / set the signature domain namespace prefix
17 if (defaultNamespacePrefix != null) {
18 dsc.setDefaultNamespacePrefix(defaultNamespacePrefix);21 }
22 //Signature
23 signature.sign(dsc);
24 }catch(Exception e){
25 System.out.println(e.getMessage());
26 throw new RuntimeException(e);
27 }
28 }
Method outside the XML document tree, the private key that needs to do the add-on processing, the ID of the node that needs to be signed, here is the ID content of the fiqreq node in the XML above (fiqreq), and a node is the signature generated by the the parent element of SignedInfo, which is to write the signedinfo node under that node.
Executing this code will then report the error code as shown above.
In the http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8017171 described above, there are three suggestions for resolution:
There are 3 potential workarounds that you can apply:
1. Use a validating schema which will register the elements with ID references.
2. Register the ID elements with the DOMValidateContext.setIdAttributeNS method before validating the signature
3. Implement a custom URIDereferencer which can find these references and override the builtin URIDereferencer with the DOMValidateContext.setURIDereferencer method.
But it does not seem particularly intuitive to solve the problem at once. But the direction of the problem was given, and the point I took to solve the problem was the second one:
2. Register the ID elements with the Domvalidatecontext.setidattributens method before validating the signature
The tag code described above, although there is no Domvalidatecontext object participation, but there is domsigncontext, he also has setidattributens method, so we are to make a fuss in this way:
Add the following two code on the add-on code above to resolve the problem:
element element = (Element) Doc.getelementsbytagname (Referenceid). Item (0null, "id");
The whole code after adding these two lines of code becomes:
/**
* XML signature
* <p>Signatures are embedded in the specified node using inline mode</p>
* @param doc XML document
* @param privateKey private key
* @param referenceId The element identifier to be signed
* @param signNode generates the signed node
*/
Public void sign(Document doc, PrivateKey privateKey, String referenceId, Node signNode) {
If(!isInit){
Throw new RuntimeException("XMLSigner is not init !");
}
Try{
//Create a <Reference> element that references the node with the specified ID, the <Signature> element will not be counted
Reference refToRootDoc = signFactory.newReference("#"+referenceId,
sha1DigMethod, Collections.singletonList(envelopedTransform), null, null);
//Create a <SignedInfo> element
SignedInfo signedInfo = signFactory.newSignedInfo(c14nWithCommentMethod,
rsa_sha1SigMethod, Collections.singletonList(refToRootDoc));
/ / Create a signature instance
XMLSignature signature = signFactory.newXMLSignature(signedInfo, null);
/ / Create a signature context, generated on the specified node
DOMSignContext dsc = new DOMSignContext(privateKey, signNode);
/ / Set the signature domain namespace prefix
If (defaultNamespacePrefix != null) {
dsc.setDefaultNamespacePrefix(defaultNamespacePrefix);
Element element = (Element)doc.getElementsByTagName(referenceId).item(0);
dsc.setIdAttributeNS(element, null, "id");
}
//signature
Signature.sign(dsc);
}catch(Exception e){
System.out.println(e.getMessage());
Throw new RuntimeException(e);
}
}
After you run the program again, the problem is resolved.
Specific instructions for adding and signing instructions, see the following documents:
Http://www.apihome.cn/api/java/XMLSignatureFactory.html (English)
Http://docs.oracle.com/javase/6/docs/technotes/guides/security/xmldsig/XMLDigitalSignature.html (English, but the introduction of more detailed, directly copied out can be)
XML signature cannot resolve element with ID XXXX solution