javaandroiddigital-signaturex509certificatedsa

How to Sign XML request with DSC certificate in java or android


Actually I'm working on a project where I have a XML code And I want to do Digital Signature of that particular XML. Can anyone help me in that?

O60\<?xml version="1.0" encoding="UTF-8" standalone="yes"?\>\<Otp uid="608559509930" ac="STGPDL0001" sa="STGPDL0001" ver="2.5" txn="AUANSDL001:20221219170045" lk="MKfOOHltrbemb9dlt1As6uaMC42HiP3F4Ar6CJTC7s8CoIJRY8U" ts="2022-12-19T17:00:45" type="A" xmlns="http://www.uidai.gov.in/authentication/otp/1.0"\>\<Opts ch="01"/\>

I have this block of code

and I want like this

O60<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Otp uid="608559509930" ac="STGPDL0001" sa="STGPDL0001" ver="2.5" txn="AUANSDL001:20221219162103" lk="MKfOOHltrbemb9dlt1As6uaMCniP3F4Ar6CJTC7s8CoIJRY8U" ts="2022-12-19T16:21:03" type="A" xmlns="http://www.uidai.gov.in/authentication/otp/1.0"><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#WithComments"/><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>vWmg/+0CO6BsWzMlcne+FRPMGS8=</DigestValue></Reference></SignedInfo><SignatureValue>UD7m2YQStmwaUerMDEdJfhqtCl2V4EZAH6G4pNCYqW2YYTt58yviobqFwGQydDXWJlQFm4GNiMtIZiNwSRweTMPn5X7hvVysL+nIFjR80OaeshUzJbitGHzN4d7KEp3yUlGAhcS66kcrYjH4cS8wQ2X7vi9CgTQ2OIpih1hOp/55YhFvGrXP3brrGR6bkLlwPUbjo2eNsbGDQMnWRoJPT5dEPhdj2a1wRs4/aGyOg/57svlKjoYtM65LLbLYqt6Xqh3vUiemm/2S0Wg+/OptRuiF+QDIqQI/dzIr5zciXk6zHUdzCZgw8CioVcaCyn4bu11XUbxze0d/mgIxGB4Rg==</SignatureValue><KeyInfo><X509Data><X509SubjectName>OID.2.5.4.65=4497104453fb4a27896fb19cea63c468, L=AGRA, CN=DS PAISALO DIGITAL LIMITED, SERIALNUMBER=89507f93cc805e639f7fc0041c047f367b9b045535f94ddc07fbdef5d8f99fc5, S=UTTAR PRADESH, PostalCode=282002, Phone=52cc883ad0fc4dcf59e2e71efe6e1cfd46456a5493651902bd117e0f30232df8, OU=PAISALO DIGITAL LIMITED, O=PAISALO DIGITAL LIMITED, C=IN</X509SubjectName> <X509Certificate>encrypted string</X509Certificate> </X509Data></KeyInfo></Signature></Otp>

I also tried this with chilkat library but it did not work for me

if some one have any idea about any type of library which is compatible with android It will too good for me but if some one has solution in java, will also acceptable

Thanks


Solution

  • 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