Enterprise Java

Signing SOAP Messages – Generation of Enveloped XML Signatures

Digital signing is a widely used mechanism to make digital contents authentic. By producing a digital signature for some content, we can let another party capable of validating that content. It can provide a guarantee that, is not altered after we signed it, with this validation. With this sample I am to share how to generate the a signature for SOAP envelope. But of course this is valid for any other content signing as well.

Here, I will sign

  • The SOAP envelope itself
  • An attachment
  • Place the signature inside SOAP header

With the placement of signature inside the SOAP header which is also signed by the signature, this becomes a demonstration of enveloped signature.

envelopedSignature

I am using Apache Santuario library for signing. Following is the code segment I used. I have shared the complete sample here to to be downloaded.

public static void main(String unused[]) throws Exception {

        String keystoreType = "JKS";
        String keystoreFile = "src/main/resources/PushpalankaKeystore.jks";
        String keystorePass = "pushpalanka";
        String privateKeyAlias = "pushpalanka";
        String privateKeyPass = "pushpalanka";
        String certificateAlias = "pushpalanka";
        File signatureFile = new File("src/main/resources/signature.xml");
        Element element = null;
        String BaseURI = signatureFile.toURI().toURL().toString();
        //SOAP envelope to be signed
        File attachmentFile = new File("src/main/resources/sample.xml");

        //get the private key used to sign, from the keystore
        KeyStore ks = KeyStore.getInstance(keystoreType);
        FileInputStream fis = new FileInputStream(keystoreFile);
        ks.load(fis, keystorePass.toCharArray());
        PrivateKey privateKey =

                (PrivateKey) ks.getKey(privateKeyAlias, privateKeyPass.toCharArray());
        //create basic structure of signature
        javax.xml.parsers.DocumentBuilderFactory dbf =
                javax.xml.parsers.DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        Document doc = dBuilder.parse(attachmentFile);
        XMLSignature sig =
                new XMLSignature(doc, BaseURI, XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1);

        //optional, but better
        element = doc.getDocumentElement();
        element.normalize();
        element.getElementsByTagName("soap:Header").item(0).appendChild(sig.getElement());

        {
            Transforms transforms = new Transforms(doc);
            transforms.addTransform(Transforms.TRANSFORM_C14N_OMIT_COMMENTS);
            //Sign the content of SOAP Envelope
            sig.addDocument("", transforms, Constants.ALGO_ID_DIGEST_SHA1);

            //Adding the attachment to be signed
            sig.addDocument("../resources/attachment.xml", transforms, Constants.ALGO_ID_DIGEST_SHA1);

        }

        //Signing procedure
        {
            X509Certificate cert =
                    (X509Certificate) ks.getCertificate(certificateAlias);
            sig.addKeyInfo(cert);
            sig.addKeyInfo(cert.getPublicKey());
            sig.sign(privateKey);
        }

        //write signature to file
        FileOutputStream f = new FileOutputStream(signatureFile);
        XMLUtils.outputDOMc14nWithComments(doc, f);
        f.close();
    }

At first it reads in the private key which is to be used in signing. To create a key pair for your own this post  will be helpful. Then it has created the signature and added the SOAP message and the attachment as the documents to be signed. Finally it performs signing  and write the signed document to a file.

The signed SOAP message looks as follows.

<soap:Envelope xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:pj="http://www.pjxml.org/namespaces/messageHeader"
               xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance">
    <soap:Header>
        <pj:MessageHeader pj:version="1.0" soap:mustUnderstand="1">
            <pj:From>
                <pj:PartyId pj:type="ABCDE">FUN</pj:PartyId>
            </pj:From>
            <pj:To>
                <pj:PartyId pj:type="ABCDE">PARTY</pj:PartyId>
            </pj:To>
            <pj:CPAId>uri:www.pjxml.org/socialService/Ping</pj:CPAId>
            <pj:ConversationId>FUN PARTY FUN 59c64t0087fg3kfs000003n9</pj:ConversationId>
            <pj:Service>uri:www.pjxml.org/socialService/</pj:Service>
            <pj:Action>Ping</pj:Action>
            <pj:MessageData>
                <pj:MessageId>FUN 59c64t0087fg3kfs000003n9</pj:MessageId>
                <pj:Timestamp>2013-10-22T17:12:20</pj:Timestamp>
            </pj:MessageData>
        </pj:MessageHeader>
        <pj:Via pj:id="59c64t0087fg3ki6000003na" pj:syncReply="False" pj:version="1.0"
                soap:actor="http://schemas.xmlsoap.org/soap/actor/next" soap:mustUnderstand="1">
            <pj:Service>uri:www.pjxml.org/socialService/</pj:Service>
            <pj:Action>Ping</pj:Action>
        </pj:Via>
        <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            <ds:SignedInfo>
                <ds:CanonicalizationMethod
                        Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></ds:CanonicalizationMethod>
                <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod>
                <ds:Reference URI="">
                    <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
                    <ds:DigestValue>9RXY9kp/Klx36gd4BULvST4qffI=</ds:DigestValue>
                </ds:Reference>
                <ds:Reference URI="../resources/attachment.xml">
                    <ds:Transforms>
                        <ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></ds:Transform>
                    </ds:Transforms>
                    <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
                    <ds:DigestValue>3JcccO8+0bCUUR3EJxGJKJ+Wrbc=</ds:DigestValue>
                </ds:Reference>
            </ds:SignedInfo>
            <ds:SignatureValue>d0hBQLIvZ4fwUZlrsDLDZojvwK2DVaznrvSoA/JTjnS7XZ5oMplN9  THX4xzZap3+WhXwI2xMr3GKO................x7u+PQz1UepcbKY3BsO8jB3dxWN6r+F4qTyWa+xwOFxqLj546WX35f8zT4GLdiJI5oiYeo1YPLFFqTrwg==
            </ds:SignatureValue>
            <ds:KeyInfo>
                <ds:X509Data>
   <ds:X509Certificate>                MIIDjTCCAnWgAwIBAgIEeotzFjANBgkqhkiG9w0BAQsFADB3MQswCQYDVQQGEwJMSzEQMA4GA1UE...............qXfD/eY+XeIDyMQocRqTpcJIm8OneZ8vbMNQrxsRInxq+DsG+C92b
                    </ds:X509Certificate>
                </ds:X509Data>
                <ds:KeyValue>
                    <ds:RSAKeyValue>
                        <ds:Modulus>
                            k5y0amGgOQ2O/St0Kc2/xye80tX2fDEKs2YOlM/zCknL8VgK0CbAKVAwvJoycQL9mGRkPDmbitHe............StGofmsoKURzo8hofYEn41rGsq5wCuqJhhHYGDrPpFcuJiuI3SeXgcMtBnMwsIaKv2uHaPRbNX31WEuabuv6Q==
                        </ds:Modulus>
                        <ds:Exponent>AQAB</ds:Exponent>
                    </ds:RSAKeyValue>
                </ds:KeyValue>
            </ds:KeyInfo>
        </ds:Signature>
    </soap:Header>
    <soap:Body>
        <pr:GetPriceResponse xmlns:pr="http://www.pushpalankajaya.com/prices">
            <pr:Price>1.90</pr:Price>
        </pr:GetPriceResponse>
    </soap:Body>
</soap:Envelope>

In a next post lets see how to verify this signature, so that we can guarantee signed documents are not changed.

Cheers!
 

Pushpalanka

Pushpalanka is an undergraduate in Computer Science and Engineering and working on variety of middle-ware solutions. She is an open-source enthusiastic having interests in the fields of Big Data, Distributed Systems and Web Security.She has successfully participated in Google Summer of Code 2012 program.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

6 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Gahininath Shinde
Gahininath Shinde
8 years ago

Thanks a lot for writing such a useful blog..!!!!! It worked for my application..

Pushpalanka Jayawardhana

Good to hear it was useful to you… :)

Gahininath Shinde
Gahininath Shinde
8 years ago

Hi Pushpalanka,

Could you please provide next post that is how to verify signature and how to invoke service?

Thanks,
Gahininath

David Perez
David Perez
8 years ago

Where do the values “privateKeyAlias”, “privateKeyPass”, “certificateAlias” come from?

David Perez
David Perez
8 years ago

The provided Ubuntu One link for the code is not valid any more.
Could you please place it somewhere?

Arun
Arun
5 years ago

Hi, thanks for great tutorial. I am using this to send signed soap message from my web application but getting Server.75275 exception back. My code works as standalone but fails on web server.

Please can you guide me here.

Back to top button