I'm just trying to digital sign a part of an XML.
The XML to sign is like this:
<Invoice>
<DataInvoice Id="data">
----
</DataInvoice>
<DataSignature>
<SignatureSeller Id="seller">
</SignatureSeller>
</DataInvoice>
</Invoice>
xml after signing
<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>
This is the code I'm using to try to sign it, but I need to sign only the part of XML and put the result inside this 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))
);
}
It can't work and shows error:
NOT_FOUND_ERR: An attempt is made to reference a node in a context where it does not exist. com.sun.org.apache.xerces.internal.dom.ParentNode.internalInsertBefore(Unknown Source)
Any help will be very appreciated. Regards