java - 如何仅签署 XML 文件的一部分 - Java XMLSignature - 但出现错误
问题描述
我只是想对 XML 的一部分进行数字签名。
要签名的 XML 如下所示:
<Invoice>
<DataInvoice Id="data">
----
</DataInvoice>
<DataSignature>
<SignatureSeller Id="seller">
</SignatureSeller>
</DataInvoice>
</Invoice>
签名后的xml
<Invoice>
<DataInvoice Id="data">
----
</DataInvoice>
<DataSignature>
<SignatureSeller Id="seller">
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="data">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>49uyshWL+fnQ2UetAe2t3BNQqnA=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>
VWI03lBKlE/wVT//uHME4qLyUs2PqxOgq0KBYaGYcR6z3QZdnXqOZClu9EVMT2V3RBA7hr+QQy2cCHVsdtb85B2gsNsRdxHPjj9KfLetTFx1lL8nlC6L5SA0x6k9Lh7xNBZTJl275IT4hnSnNe8q+9dWskgE/6We24DKBLMrOLg=
</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>
MIIEDzCCAvegAwIBAgIQVAT//rcDP7MW1nIgG4H6OjANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJWTjESMBAGA1UEBwwJSMOgIE7hu5lpMRYwFAYDVQQKEw1WaWV0dGVsIEdyb3VwMRMwEQYDVQQDEwpWaWV0dGVsLUNBMB4XDTIwMDYwODA5NDMyNFoXDTIxMDYwODA5NDMyNFowgYoxITAfBgkqhkiG9w0BCQEWEmh1b25nbnRAbWF0YmFvLmNvbTEeMBwGCgmSJomT8ixkAQEMDk1TVDowMzAyNzEyNTcxMSgwJgYDVQQDDB9Dw5RORyBUWSBD4buUIFBI4bqmTiBN4bquVCBCw4NPMQ4wDAYDVQQHDAVUUEhDTTELMAkGA1UEBhMCVk4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJQ3aZioAdDIU1rQOO5tN7ORCqAWDWkQvP24gqD8LzRhA1Ui27DcOukuTp2bG8zSB3vGUMoFxV8qOpkfpt4/YUFhrMR6fG3k7J4YAKhkI/Ear3m3cEHo/MKxKsMbWHriI2CrKbG7Ih51iafRyt/mLGI66fNfnIwAoSIeXvLXi5YDAgMBAAGjggEuMIIBKjA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnZpZXR0ZWwtY2Eudm4wHQYDVR0OBBYEFHQbrRodIeEnE0sMBLuNyp+lCsvhMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAU/stBFOldp9kyDeSyCFzxXOy2srUwgZIGA1UdHwSBijCBhzCBhKAuoCyGKmh0dHA6Ly9jcmwudmlldHRlbC1jYS52bi9WaWV0dGVsLUNBLXYzLmNybKJSpFAwTjETMBEGA1UEAwwKVmlldHRlbC1DQTEWMBQGA1UECgwNVmlldHRlbCBHcm91cDESMBAGA1UEBwwJSMOgIE7hu5lpMQswCQYDVQQGEwJWTjAOBgNVHQ8BAf8EBAMCBeAwDQYJKoZIhvcNAQEFBQADggEBAJInz1BLmnJIfl8juAs+StPAl4a5bd9Gf4B6eksmYOBFLeUzc/B78LcO9B2z3fpOVcqOvsK9rCFMO81+TePa6KZODk4xnP2HjgpuiN+E/qdYucUSMQNNVH2BDa/BraK41H1ySVVuqxvQ5fAvkIfhgBuyt3RVRmBpWkRT1faJ1hh5o9sq3SBqTmqd+W5PmA4hOUHj/Rb4xcQF3hMywWIBnVXZAwJ+GTbF4T/XkFavxb54UObTuebaQ8deB4hIOMvM6SKagFofBVeurS7CELMQtHKBjVRndlzecK0zR6vzKDLBukL6W4K7s9u55A2563Vv5HhZJhQHnftlrmJ59bBUHx0=
</X509Certificate>
</X509Data>
</KeyInfo>
<Object xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignatureProperties>
<SignatureProperty>
<SigningTime>2021-05-27T14:13:48</SigningTime>
</SignatureProperty>
</SignatureProperties>
</Object>
</Signature>
</SignatureSeller>
</DataInvoice>
</Invoice>
这是我用来尝试对其进行签名的代码,但我只需要对 XML 的一部分进行签名并将结果放入此 Id 中
public String xmlSign(String xml, String idData, String signBy) throws
NoSuchAlgorithmException, InvalidAlgorithmParameterException, InterruptedException,
UnrecoverableKeyException, KeyStoreException, SAXException, IOException, ParserConfigurationException,
XPathExpressionException, MarshalException, XMLSignatureException
{
PublicKey publicKey = null;
PrivateKey privateKey = null;
if (!(cert instanceof Certificate)) {
Map<String, Certificate> aliases = store.getAliases();
for (Map.Entry<String, Certificate> item : aliases.entrySet()) {
Certificate tmpCert = item.getValue();
publicKey = tmpCert.getCertificate().getPublicKey();
privateKey = (PrivateKey) store.getKeyStore().getKey(tmpCert.getAlias(), null);
if (publicKey instanceof PublicKey && privateKey instanceof PrivateKey) {
cert = tmpCert;
break;
}
}
} else {
publicKey = cert.getCertificate().getPublicKey();
privateKey = (PrivateKey) store.getKeyStore().getKey(cert.getAlias(), null);
}
if (publicKey == null || privateKey == null) {
return null;
}
// Load factory
XMLSignatureFactory factory = XMLSignatureFactory.getInstance("DOM");
XPathFactory xpf = XPathFactory.newInstance();
XPath xpath = xpf.newXPath();
// Load xml document
Document document = this.importXML(this.ignoreLineBreak(xml));
XMLObject xmlObject = factory.newXMLObject(Collections.singletonList(new DOMStructure(createTimestamp(document))), null, null, null);
XPathExpression exprAssertion = xpath.compile(String.format("//*[@Id='%s']", idData));
Element assertionNode = (Element) exprAssertion.evaluate(document, XPathConstants.NODE);
assertionNode.setIdAttribute("Id", true);
// Retreive Subject Node because the signature will be inserted before.
XPathExpression exprAssertionSubject = xpath.compile(String.format("//*[@Id='%s']", "seller"));
Node insertionNode = (Node) exprAssertionSubject.evaluate(document, XPathConstants.NODE);
DOMSignContext signContext = new DOMSignContext(privateKey, assertionNode, insertionNode);
// Create transform
List<Transform> transformList = new ArrayList<Transform>();
Transform exc14nTranform = ((XMLSignatureFactory) factory).newTransform("http://www.w3.org/TR/2001/REC-xml-c14n-20010315", (TransformParameterSpec) null);
Transform envTransform = ((XMLSignatureFactory) factory).newTransform(Transform.ENVELOPED, (TransformParameterSpec) null);
transformList.add(exc14nTranform);
transformList.add(envTransform);
// Create reference
DigestMethod digestMethod = factory.newDigestMethod(DigestMethod.SHA1, null);
Reference reference = factory.newReference("#" + idData, digestMethod, transformList, null, (signBy != null ? "#" + signBy : null));
// Create key info
KeyInfoFactory kif = ((XMLSignatureFactory) factory).getKeyInfoFactory();
List<X509Certificate> x509Content = new ArrayList<X509Certificate>();
x509Content.add(cert.getCertificate());
X509Data xd = kif.newX509Data(x509Content);
KeyInfo keyInfo = kif.newKeyInfo(Collections.singletonList(xd));
// Create signature info
SignedInfo signInfo = ((XMLSignatureFactory) factory).newSignedInfo(
((XMLSignatureFactory) factory).newCanonicalizationMethod(
CanonicalizationMethod.INCLUSIVE,
(C14NMethodParameterSpec) null
),
((XMLSignatureFactory) factory).newSignatureMethod(
SignatureMethod.RSA_SHA1,
null
),
Collections.singletonList(reference)
);
XMLSignature signature = factory.newXMLSignature(signInfo, keyInfo, Collections.singletonList(xmlObject), null, null);
signature.sign(signContext);
return this.ignoreLineBreak(
this.exportXML(new DOMSource(document))
);
}
它无法工作并显示错误:
NOT_FOUND_ERR:尝试在不存在的上下文中引用节点。com.sun.org.apache.xerces.internal.dom.ParentNode.internalInsertBefore(未知来源)
任何帮助将不胜感激。问候
解决方案
推荐阅读
- powershell - Powershell - 在 Add-Content Cmdlet 内的 .log 文件中包含 Get-Date
- typescript - Vue with Typescript:将 Vue 应用程序从 JavaScript 转换为 TypeScript 时遇到的问题
- c# - C#如何将非数字值设置为0
- python - 从具有不同扩展名的旧二进制文件创建精确的新二进制文件
- javascript - 如何过滤包含特定字符串模式的单词数组和另一个数组中的单词?
- docker - 读取 Docker 容器中 shell 脚本的输入
- python - 使帮助命令打印未排序的命令
- consul - Envoy sidecar-proxy 公共监听器
- macos - 显示 gnuplot 终端的字体
- angular - 根据 ngxdaterangepicker angular 8 中的 minDate 设置 maxDate