XML Digital Signature in Java

Introduction

As you know XML plays a significant role in our product or project development and from an XML document we gather much of the information. Do you know that the data you are reading from a XML document is authentic? Are you sure that the XML document has come from a trusted source? There may be many questions about the authenticity or originality of the data from an XML file. It is a common practice that whenever we encounter an XML document we directly process the XML document by parsing the document, we hardly care about the data security. But there are situations where all the points and questions made in the preceding lines are relevant. Let us consider a real-world situation. Whenever we get a letter or mail from our Post Office, how do we know that the letter has come from our friends ? It is based upon his/her typical statements or words or address details. It may be his/her character signature. Now-a-days it is also possible that the letter we have received has been modified by an unknown person by adding an another page. For all those reasons we normally verify the handwriting signature of our friend. This is all about the normal Post Office letter. What about an electronic message? How can we verify that the electronic message is authentic? In this case we need to adopt the technology for digital signature. In this article I will present a brief glimpse at XML Digital Signatures that play a significant role for our data integrity. In this article I will show you how to attach a digital signature to an XML document and how to verify the XML document with the attached signature.

Technicalities

In the last couple of years XML Digital Signatures have gained momentum, particularly in the field of the financial sector. Before we jump into XML Digital Signatures, let us consider a typical scenario for our understanding. Think about a situation where an organization sends all the salary details of its employees to the Income Tax department in the form of a XML document. How does the Income Tax department verify the XML document? It means the IT department must verify the sensitive information of all the employees of the organization. The IT department must ensure that the XML document has come from a trusted source and the document has not yet been modified while coming to the IT department. It means the document has not been tampered with in between. First of all we need to understand the concept of digital signatures. A Digital Signature is an electronic signature that validates the authenticity of the document sent by a trusted person. It also provides assurance that the original content of the document has not been modified during transmission. A digital signature can be used with any message, whether it is encrypted or not, so that the receiver can be sure of the identity of the sender and that the message has not been altered by an unknown person. According to Wikipedia, a digital signature is a mathematical scheme for demonstrating the authenticity of a digital message or document. A valid digital signature gives a recipient reason to believe that the message was created by a known sender, such that the sender cannot deny having sent the message (authentication and non-repudiation) and that the message was not altered in transit (integrity). Digital signatures are commonly used for software distribution, financial transactions, and in other cases where it is important to detect forgery or tampering.

Let us see a complete XML document with a digital signature.

<?xml version="1.0" encoding="UTF-8" standalone="no"?><SalaryDeposit>

       <Organisation>

              <Name>DDLab Inc</Name>

              <AccountNo>SBC-12345789</AccountNo>

       </Organisation>

       <Employees>

              <Emp>

                     <Name>John Abraham</Name>

                     <AccountNo>SB-001</AccountNo>

                     <Amount>1234</Amount>

              </Emp>

              <Emp>

                     <Name>Bipasha Basu</Name>

                     <AccountNo>SB-002</AccountNo>

                     <Amount>2334</Amount>

              </Emp>

              <Emp>

                     <Name>Vidya Balan</Name>

                     <AccountNo>SB-003</AccountNo>

                     <Amount>3465</Amount>

              </Emp>

              <Emp>

                     <Name>Debadatta Mishra</Name>

                     <AccountNo>SB-007</AccountNo>

                     <Amount>5789</Amount>

              </Emp>

              <Emp>

                     <Name>Priti Zinta</Name>

                     <AccountNo>SB-009</AccountNo>

                     <Amount>1234</Amount>

              </Emp>

       </Employees>

       <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>bHS+6uf8KbJV4AGzoHNHLfnXvKM=</DigestValue>

                     </Reference>

              </SignedInfo>

              <SignatureValue>aUEMrCT5dzeOfSNaznzoT0If8WZ8KQcMNXDqtoeseonVk3NqOk9ctcxrf3QVX3wP6810DDRPdI6l

            e8ccG64Ge0HjkO+aYC5+c2L/qKBzwtSbl/olJEuFU2DVxBQO+K29TTUJfxpVzC9Zf2pvT+1NRj0f

            2/ofHujYZ01D6+YqI8c=

              </SignatureValue>

              <KeyInfo>

                     <KeyValue>

                           <RSAKeyValue>

                                  <Modulus>jfAd5uV38L36+lDZJrqfH9oLN86VJezXYfAeU+lrFoHlKAXVJLAi9hKvBHQRer4tPfdez6iSBKsl

                        6IHkPnVRAKt0xU99uxi5QpymsWAX3qnBqHlw9Z70PwyZ+Xysfw4Q2tK2HtSgUOhMuaUcIf9sbHvf

                        gbvcRPgxDZZqfIzDmDU=</Modulus>

                                  <Exponent>AQAB</Exponent>

                           </RSAKeyValue>

                     </KeyValue>

              </KeyInfo>

       </Signature>

</SalaryDeposit>

The preceding XML file is a digitally signed one which can be verified at any point of time. The preceding XML file contains information about the employee name, account number and salary amount. But the actual digital signature is attached within the tag <Signature></Signature>. The information lying inside <Signature> provides the authenticity of the document. As you are able to see the data, you can freely change the data, but it will fail in the case of a signature verification process. Now let us see the skeletal structure of a XML Digital Signature below.

<Signature xmlns="">

      <SignedInfo>

            <CanonicalizationMethod

                  Algorithm="" />

            <SignatureMethod Algorithm="" />

            <Reference URI="">

                  <Transforms>

                        <Transform Algorithm="" />

                  </Transforms>

                  <DigestMethod Algorithm="" />

                  <DigestValue></DigestValue>

            </Reference>

      </SignedInfo>

      <SignatureValue></SignatureValue>

      <KeyInfo>

            <KeyValue>

                  <RSAKeyValue>

                        <Modulus></Modulus>

                        <Exponent></Exponent>

                  </RSAKeyValue>

            </KeyValue>

      </KeyInfo>

</Signature>

The XML tag <Signature> basically contains 3 children tags. It can be viewed as:

<Signature>

                <SignedInfo></SignedInfo>

                <SignatureValue></SignatureValue>

                <KeyInfo></KeyInfo>

</Signature>

Here <Signature> is the root element of the XML Digital Signature and it is a protocol that must be followed as instructed by W3C. The <SignedInfo> element is the information that you signed. <SignatureValue> contains the actual signature with Base64-encoded content and finally <KeyInfo> indicates the public key. Again let us look into the <SignedInfo> tag. The structure of <SignedInfo> is given below.
 

<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>bHS+6uf8KbJV4AGzoHNHLfnXvKM=</DigestValue>

    </Reference>

</SignedInfo>

While creating XML Digital Signature in Java , a SignedInfo object is used to create an element inside the Signature tag of the digital signature. This is also part of the XML Digital Signature protocol as suggested by W3C.

Now let us look into the XML tag <KeyInfo> structure below.
 

<KeyInfo>

                <KeyValue>

                                <RSAKeyValue>

                                                <Modulus></Modulus>

                                                <Exponent></Exponent>

                                </RSAKeyValue>

                </KeyValue>

</KeyInfo>

The <KeyInfo> tag contains the information that is calculated mathematically and basically it caontains a modulus and exponent of the Public Key.

In order to create an XML Digital Signature, use the following
procedure:

  1. Generate a pair of Keys called Private Key and Pubic Key.

  2. Obtain the original XML document.

  3. Sign the original XML document using both Private and Public key by Java API and generate another document that has a XML Digital Signature.

Let us see a brief Java code snippet for generating a XML Digital Signature.
 

public void generateXMLDigitalSignature(String originalXmlFilePath,

            String destnSignedXmlFilePath, String privateKeyFilePath, String publicKeyFilePath) {

        //Get the XML Document object

        Document doc = getXmlDocument(originalXmlFilePath);

        //Create XML Signature Factory

        XMLSignatureFactory xmlSigFactory = XMLSignatureFactory.getInstance("DOM");

        PrivateKey privateKey = new KryptoUtil().getStoredPrivateKey(privateKeyFilePath);

        DOMSignContext domSignCtx = new DOMSignContext(privateKey, doc.getDocumentElement());

        Reference ref = null;

        SignedInfo signedInfo = null;

        try {

            ref = xmlSigFactory.newReference("", xmlSigFactory.newDigestMethod(DigestMethod.SHA1, null),

                    Collections.singletonList(xmlSigFactory.newTransform(Transform.ENVELOPED,

                    (TransformParameterSpec) null)), null, null);

            signedInfo = xmlSigFactory.newSignedInfo(

                    xmlSigFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,

                    (C14NMethodParameterSpec) null),

                    xmlSigFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null),

                    Collections.singletonList(ref));

        } catch (NoSuchAlgorithmException ex) {

            ex.printStackTrace();

        } catch (InvalidAlgorithmParameterException ex) {

            ex.printStackTrace();

        }

        //Pass the Public Key File Path

        KeyInfo keyInfo = getKeyInfo(xmlSigFactory, publicKeyFilePath);

        //Create a new XML Signature

        XMLSignature xmlSignature = xmlSigFactory.newXMLSignature(signedInfo, keyInfo);

        try {

            //Sign the document

            xmlSignature.sign(domSignCtx);

        } catch (MarshalException ex) {

            ex.printStackTrace();

        } catch (XMLSignatureException ex) {

            ex.printStackTrace();

        }

        //Store the digitally signed document inta a location

        storeSignedDoc(doc, destnSignedXmlFilePath);

    }

To verify a signed XML document, use the following
procedure:

  1. Obtain both signed XML document and Public key.

  2. Verifying the digital signature of the <SignedInfo> element

  3. Calculate the digest of the <SignedInfo> element and compare the values.

Let us see the brief Java code snippet of XML Digital Signature verification.

public static boolean isXmlDigitalSignatureValid(String signedXmlFilePath,

            String pubicKeyFilePath) throws Exception {

      boolean validFlag = false;

      Document doc = getXmlDocument(signedXmlFilePath);

      NodeList nl = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");

      if (nl.getLength() == 0) {

            throw new Exception("No XML Digital Signature Found, document is discarded");

      }

      PublicKey publicKey = new KryptoUtil().getStoredPublicKey(pubicKeyFilePath);

      DOMValidateContext valContext = new DOMValidateContext(publicKey, nl.item(0));

      XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

      XMLSignature signature = fac.unmarshalXMLSignature(valContext);

validFlag = signature.validate(valContext);

      return validFlag;

}

For a more complete understanding, download the complete Netbeans project having the complete source code from this site.

Configuration

You can download the complete project on XML Digital Signature in Java from this site.

You can configure this project in your favorite Java IDE and run the standalone program available inside the test source folder. This project already contains both Private Key and Public Key. If you want to generate it then run the Java class "TestGenerateKeys" to generate a pair of keys. You can also provide the path of your own XML file to see how a XML Digital Signature is generated.

Conclusion

I hope you have enjoyed my article about the XML Digital Signature in Java. There are also many ways you can create a XML Digital Signature, I have provided one of the ways using the Java API. You can follow the various reference sites below. Download the complete project and go through the source code to understand the concept and its usage. Based upon the complexity and design, you can decide whether to use this concept. For any kind of issues and errors you can contact me at debadatta.mishra@gmail.com .

Resource and Reference

http://en.wikipedia.org/wiki/XML_Signature
http://msdn.microsoft.com/en-us/library/ms996502.aspx
http://www.xml.com/pub/a/2001/08/08/xmldsig.html