无法解析签名参考 (Apache Santuario)
Signature Reference can not be resolved (Apache Santuario)
我想使用 apache santuario lib 创建一个 xml 签名,并通过引用该元素将自定义元素包含到签名计算中。这是我到目前为止得到的,并且工作正常:
public void signXmlNode(Node n) {
try {
Reference qSigRef = sigFactory.newReference(
"#SignatureProperties", sigFactory.newDigestMethod(
this.refAlgo, null), Collections
.singletonList(sigFactory.newTransform(
CanonicalizationMethod.EXCLUSIVE,
(TransformParameterSpec) null)),
"http://uri.etsi.org/01903#SignedProperties",
"Reference-SignedProperties-1497606229690");
SignedInfo signedInfo = sigFactory.newSignedInfo(sigFactory
.newCanonicalizationMethod(
CanonicalizationMethod.EXCLUSIVE,
(C14NMethodParameterSpec) null), sigFactory
.newSignatureMethod(this.sigAlgo, null), Arrays.asList(
qSigRef));
Element qSig = createXades(n.getOwnerDocument());
XMLObject xmlObject = sigFactory.newXMLObject(
Collections.singletonList(new DOMStructure(qSig)),
"SignatureProperties", null, null);
KeyInfoFactory keyInfoFactory = sigFactory.getKeyInfoFactory();
List<Object> x509Content = new ArrayList<>();
x509Content.add(signerCert);
X509Data xd = keyInfoFactory.newX509Data(x509Content);
KeyInfo keyInfo = keyInfoFactory.newKeyInfo(Collections
.singletonList(xd));
XMLSignature xmlSignature = sigFactory.newXMLSignature(signedInfo,
keyInfo, Collections.singletonList(xmlObject), "Signature-"
+ SIGNATURE_ID, null);
DOMSignContext signContext = new DOMSignContext(signerKey, n);
signContext.setDefaultNamespacePrefix("ds");
xmlSignature.sign(signContext);
final Transformer t = TransformerFactory.newInstance()
.newTransformer();
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
t.setOutputProperty(OutputKeys.INDENT, "yes");
final StringWriter w = new StringWriter();
t.transform(new DOMSource(n), new StreamResult(w));
System.out.println(w.toString());
} catch (MarshalException ex) {
log.log(Level.WARNING, "MarshalException in handler!", ex);
} catch (XMLSignatureException ex) {
log.log(Level.WARNING, "XMLSignatureException in handler!", ex);
} catch (InvalidAlgorithmParameterException ex) {
log.log(Level.SEVERE, "InvalidAlgorithmParameterException "
+ "while signing message!", ex);
logSecurityProviders();
} catch (NoSuchAlgorithmException ex) {
log.log(Level.SEVERE, "NoSuchAlgorithmException "
+ "while signing message!", ex);
logSecurityProviders();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerFactoryConfigurationError e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
}
private Element createXades(Document doc) {
Element qualifyingProperties = doc.createElementNS(
"http://uri.etsi.org/01903/v1.3.2#",
"xades:QualifyingProperties");
qualifyingProperties.setAttribute("Target", "#Signature-"
+ SIGNATURE_ID);
Element signedProperties = qualifyingProperties.getOwnerDocument()
.createElementNS("http://uri.etsi.org/01903/v1.3.2#",
"xades:SignedProperties");
signedProperties.setAttribute("Id", "SignedProperties-" + SIGNATURE_ID);
Element signedSignatureProperties = signedProperties.getOwnerDocument()
.createElementNS("http://uri.etsi.org/01903/v1.3.2#",
"xades:SignedSignatureProperties");
signedProperties.appendChild(signedSignatureProperties);
qualifyingProperties.appendChild(signedProperties);
return qualifyingProperties;
}
现在,我想要参考 qSigRef 引用 xml 元素 <xades:SignedProperties Id="SignedProperties-0123456789">
而不是 <Object ID="SignatureProperties">
。将 URI 从“#SignatureProperties”更改为 "SignedProperties-0123456789"(如下所示):
Reference qSigRef = sigFactory.newReference(
"#SignatureProperties", sigFactory.newDigestMethod(
this.refAlgo, null), Collections
.singletonList(sigFactory.newTransform(
CanonicalizationMethod.EXCLUSIVE,
(TransformParameterSpec) null)),
"http://uri.etsi.org/01903#SignedProperties",
"Reference-SignedProperties-1497606229690");
到
Reference qSigRef = sigFactory.newReference(
"#SignedProperties-0123456789", sigFactory.newDigestMethod(
this.refAlgo, null), Collections
.singletonList(sigFactory.newTransform(
CanonicalizationMethod.EXCLUSIVE,
(TransformParameterSpec) null)),
"http://uri.etsi.org/01903#SignedProperties",
"Reference-SignedProperties-1497606229690");
抛出 XMLSignatureException 声明:
javax.xml.crypto.dsig.XMLSignatureException: javax.xml.crypto.URIReferenceException: org.apache.xml.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID SignedProperties-0123456789
因为找不到任何解决方案,也找不到抛出异常的原因,所以我决定在这里问这个问题。
我解决了这个问题。
我必须注册 SignedProperties 元素的 id 属性。
这是通过调用相关元素的 setIdAttributeNS() 隐式存档的:
Element signedProperties = qualifyingProperties.getOwnerDocument()
.createElementNS("http://uri.etsi.org/01903/v1.3.2#",
"xades:SignedProperties");
signedProperties.setAttributeNS("", "Id", "SignedProperties-"
+ SIGNATURE_ID);//Set ID attribute
signedProperties.setIdAttributeNS("", "Id", true);//register attribute as id
我想使用 apache santuario lib 创建一个 xml 签名,并通过引用该元素将自定义元素包含到签名计算中。这是我到目前为止得到的,并且工作正常:
public void signXmlNode(Node n) {
try {
Reference qSigRef = sigFactory.newReference(
"#SignatureProperties", sigFactory.newDigestMethod(
this.refAlgo, null), Collections
.singletonList(sigFactory.newTransform(
CanonicalizationMethod.EXCLUSIVE,
(TransformParameterSpec) null)),
"http://uri.etsi.org/01903#SignedProperties",
"Reference-SignedProperties-1497606229690");
SignedInfo signedInfo = sigFactory.newSignedInfo(sigFactory
.newCanonicalizationMethod(
CanonicalizationMethod.EXCLUSIVE,
(C14NMethodParameterSpec) null), sigFactory
.newSignatureMethod(this.sigAlgo, null), Arrays.asList(
qSigRef));
Element qSig = createXades(n.getOwnerDocument());
XMLObject xmlObject = sigFactory.newXMLObject(
Collections.singletonList(new DOMStructure(qSig)),
"SignatureProperties", null, null);
KeyInfoFactory keyInfoFactory = sigFactory.getKeyInfoFactory();
List<Object> x509Content = new ArrayList<>();
x509Content.add(signerCert);
X509Data xd = keyInfoFactory.newX509Data(x509Content);
KeyInfo keyInfo = keyInfoFactory.newKeyInfo(Collections
.singletonList(xd));
XMLSignature xmlSignature = sigFactory.newXMLSignature(signedInfo,
keyInfo, Collections.singletonList(xmlObject), "Signature-"
+ SIGNATURE_ID, null);
DOMSignContext signContext = new DOMSignContext(signerKey, n);
signContext.setDefaultNamespacePrefix("ds");
xmlSignature.sign(signContext);
final Transformer t = TransformerFactory.newInstance()
.newTransformer();
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
t.setOutputProperty(OutputKeys.INDENT, "yes");
final StringWriter w = new StringWriter();
t.transform(new DOMSource(n), new StreamResult(w));
System.out.println(w.toString());
} catch (MarshalException ex) {
log.log(Level.WARNING, "MarshalException in handler!", ex);
} catch (XMLSignatureException ex) {
log.log(Level.WARNING, "XMLSignatureException in handler!", ex);
} catch (InvalidAlgorithmParameterException ex) {
log.log(Level.SEVERE, "InvalidAlgorithmParameterException "
+ "while signing message!", ex);
logSecurityProviders();
} catch (NoSuchAlgorithmException ex) {
log.log(Level.SEVERE, "NoSuchAlgorithmException "
+ "while signing message!", ex);
logSecurityProviders();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerFactoryConfigurationError e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
}
private Element createXades(Document doc) {
Element qualifyingProperties = doc.createElementNS(
"http://uri.etsi.org/01903/v1.3.2#",
"xades:QualifyingProperties");
qualifyingProperties.setAttribute("Target", "#Signature-"
+ SIGNATURE_ID);
Element signedProperties = qualifyingProperties.getOwnerDocument()
.createElementNS("http://uri.etsi.org/01903/v1.3.2#",
"xades:SignedProperties");
signedProperties.setAttribute("Id", "SignedProperties-" + SIGNATURE_ID);
Element signedSignatureProperties = signedProperties.getOwnerDocument()
.createElementNS("http://uri.etsi.org/01903/v1.3.2#",
"xades:SignedSignatureProperties");
signedProperties.appendChild(signedSignatureProperties);
qualifyingProperties.appendChild(signedProperties);
return qualifyingProperties;
}
现在,我想要参考 qSigRef 引用 xml 元素 <xades:SignedProperties Id="SignedProperties-0123456789">
而不是 <Object ID="SignatureProperties">
。将 URI 从“#SignatureProperties”更改为 "SignedProperties-0123456789"(如下所示):
Reference qSigRef = sigFactory.newReference(
"#SignatureProperties", sigFactory.newDigestMethod(
this.refAlgo, null), Collections
.singletonList(sigFactory.newTransform(
CanonicalizationMethod.EXCLUSIVE,
(TransformParameterSpec) null)),
"http://uri.etsi.org/01903#SignedProperties",
"Reference-SignedProperties-1497606229690");
到
Reference qSigRef = sigFactory.newReference(
"#SignedProperties-0123456789", sigFactory.newDigestMethod(
this.refAlgo, null), Collections
.singletonList(sigFactory.newTransform(
CanonicalizationMethod.EXCLUSIVE,
(TransformParameterSpec) null)),
"http://uri.etsi.org/01903#SignedProperties",
"Reference-SignedProperties-1497606229690");
抛出 XMLSignatureException 声明:
javax.xml.crypto.dsig.XMLSignatureException: javax.xml.crypto.URIReferenceException: org.apache.xml.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID SignedProperties-0123456789
因为找不到任何解决方案,也找不到抛出异常的原因,所以我决定在这里问这个问题。
我解决了这个问题。
我必须注册 SignedProperties 元素的 id 属性。
这是通过调用相关元素的 setIdAttributeNS() 隐式存档的:
Element signedProperties = qualifyingProperties.getOwnerDocument()
.createElementNS("http://uri.etsi.org/01903/v1.3.2#",
"xades:SignedProperties");
signedProperties.setAttributeNS("", "Id", "SignedProperties-"
+ SIGNATURE_ID);//Set ID attribute
signedProperties.setIdAttributeNS("", "Id", true);//register attribute as id