How to Sign XML request with DSC certificate in java?
You need a private key
to perform the signing. I have added the code which could help you to sign and add the public certificate into the input XML. You need a keystore with private key and public certificate.
I used the following xml as an input for testing purpose.
<?xml version="1.0" encoding="UTF-8"?>
<Otp uid="608559509930" ac="STGPDL0001" sa="STGPDL0001" ver="2.5" txn="AUANSDL001:20221219170045" lk="MKfOOHltrbemb9dlt1As6uaMC42HiP3F4Ar6CJTC7s8CoIJRY8U" ts="2022-12-19T17:00:45" type="A">
<Opts ch="01" />
</Otp>
You don't need any external dependency to perform the signing. I just used java 8, created a test keystore with private key and certificate. Make sure to provide valid keystore file, keystore password and private key's pin.
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.io.StringReader;
import java.io.StringWriter;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.xml.XMLConstants;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
public class Application {
private final static String KEYSTORE_FILE = "keystore.p12";
private final static String KEYSTORE_PASSWORD = "password";
private final static String PRIVATE_KEY_PIN = "password";
public static void main(String[] args) throws Exception {
String inputXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n"
+ "<Otp uid=\"608559509930\" ac=\"STGPDL0001\" sa=\"STGPDL0001\" ver=\"2.5\" txn=\"AUANSDL001:20221219170045\" lk=\"MKfOOHltrbemb9dlt1As6uaMC42HiP3F4Ar6CJTC7s8CoIJRY8U\" ts=\"2022-12-19T17:00:45\" type=\"A\"><Opts ch=\"01\"/></Otp>";
System.out.println("Input XML:\n" + inputXML);
String signedXML = signXML(inputXML);
System.out.println("\nSigned XML:\n" + signedXML);
}
public static String signXML(String xml) throws Exception {
XMLSignatureFactory factory = XMLSignatureFactory.getInstance("DOM");
Reference ref = factory.newReference("", factory.newDigestMethod(DigestMethod.SHA1, null),
Collections.singletonList(factory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)),
null, null);
SignedInfo signedInfo = factory.newSignedInfo(
factory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null),
factory.newSignatureMethod(SignatureMethod.RSA_SHA1, null), Collections.singletonList(ref));
KeyStore ks = KeyStore.getInstance("pkcs12");
InputStream fis = new FileInputStream(KEYSTORE_FILE);
ks.load(fis, KEYSTORE_PASSWORD.toCharArray());
String alias = ks.aliases().nextElement();
PrivateKey key = (PrivateKey) ks.getKey(alias, PRIVATE_KEY_PIN.toCharArray());
Certificate[] chain = ks.getCertificateChain(alias);
X509Certificate cert = (X509Certificate) chain[0];
KeyInfoFactory keyInfoFactory = factory.getKeyInfoFactory();
List<Serializable> x509Content = new ArrayList<>();
x509Content.add(cert.getSubjectX500Principal().getName());
x509Content.add(cert);
X509Data x509Data = keyInfoFactory.newX509Data(x509Content);
KeyInfo keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(x509Data));
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Document doc = dbf.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
DOMSignContext dsc = new DOMSignContext(key, doc.getDocumentElement());
XMLSignature signature = factory.newXMLSignature(signedInfo, keyInfo);
signature.sign(dsc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
StringWriter writer = new StringWriter();
trans.transform(new DOMSource(doc), new StreamResult(writer));
return writer.toString();
}
}
Output after execution of above code: Signed XML
<?xml version="1.0" encoding="UTF-8"?><Otp ac="STGPDL0001" lk="MKfOOHltrbemb9dlt1As6uaMC42HiP3F4Ar6CJTC7s8CoIJRY8U" sa="STGPDL0001" ts="2022-12-19T17:00:45" txn="AUANSDL001:20221219170045" type="A" uid="608559509930" ver="2.5"><Opts ch="01"/><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=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><DigestValue>kVVjeAce1xEXIXqwDqOubFIjVxg=</DigestValue></Reference></SignedInfo><SignatureValue>KFA+Jcd+HmNzVL3LKmQ+E0B8EXnVSP8lFZyChBG74xU0T74827xuuHymCOrNhbffzBpzUJiibEhC
mtPPmMarvhRMtxtRzjyCaNetqDgRkesNV6fpeyHg4HIWuRvRsp1u+jchj3O04ng0TCbBxxK5C4Q4
TPEn/Rpa9YzEoDmmg1BstCvxRYK1naXdV63gBr1UhPfteVpHYY/bJbID/FldPNMIkJHHxzrY3CD6
mprroKD9svGbxvRFTh3aHqC3CJOoi+dkMaJiIwDlXHFoCqL1EutGWDbwJYNptDVhH9GuCA7P0jYW
wmSE1QOKeiJJMyrd3GExtRf79rCZCFHCBBbm/w==</SignatureValue><KeyInfo><X509Data><X509SubjectName>CN=Test,OU=NA,O=NA,L=NA,ST=NA,C=NA</X509SubjectName><X509Certificate>MIIDHDCCAgSgAwIBAgIEY62nqTANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJOQTELMAkGA1UE
CAwCTkExCzAJBgNVBAcMAk5BMQswCQYDVQQKDAJOQTELMAkGA1UECwwCTkExDTALBgNVBAMMBFRl
c3QwHhcNMjIxMjI5MTQ0MzUzWhcNMjMxMjI5MTQ0MzUzWjBQMQswCQYDVQQGEwJOQTELMAkGA1UE
CAwCTkExCzAJBgNVBAcMAk5BMQswCQYDVQQKDAJOQTELMAkGA1UECwwCTkExDTALBgNVBAMMBFRl
c3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDRGXlJ/+Gj8f4ID0zv6QIxqEl7EenC
79jS6elE5Zqp7Iofhep7KWVeqhJmgSsOfg/MXL/ZCMrhFd8rMWdWnWkkRg4fGXm5VNa/FOXu7FYl
jcCmizxAHmhVT2ln7HDOOfZ75wyjfT5crz9KlofvqK+gAByQee9Bv5A1HorHxzM4t/6GW7Yc5gHp
l4CQ3m28c74m5PmTg7C0cMAL+fj1vQezMFpSQp2kehylwVPMy1+SH3cbkIFDPmOKffYjh245Q0vD
+c4yRcM6srP9lW2yO7UbYUl2cV3fKGw7V56u3hhu/5U6Udc7Gn/vWX4+rcY45ZP0kzQfWRVi6rFW
P94Fk/s5AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAGiUORJhosazNJOwpi02VYR0Oedpq3apUiFV
dhWvTcH43mcXPCgf+w8oahahkow3zJJZBCYQxQ2jUWU6a+smixrik/+QUZrheV0EHjqXOxVJTWUu
V62fpXy0AZQlSvsq4hDdgsmMnK/U2Kcx5DpDkqE5CBe/cMoarcOOGZUsokMp+GVbpq9ZR16KWoBd
uehy4RdYLOWao6DqmOrqgHJqe0DOjqQmb2Lsvuel8tq8t3imIa4wu+VVq/WDaPNk68kr2aB0B3ed
Q3sB8L+tucYuYCw2MEXwz1+da9xVORrhQ/pgGKFtXhgyqddMvPKAvIxZO0FUyk7ZMXJMeCCYb40L
1Mk=</X509Certificate></X509Data></KeyInfo></Signature></Otp>
Test keystore file
keystore.p12