Developer

Encrypt XML data with TEA

You can add an extra layer of security to your XML data applications with the Tiny Encryption Algorithm (TEA). Here's how.

This article originally appeared as a Web Development Zone e-newsletter.

By Phillip Perkins

One of the biggest problems with XML is that it's designed for humans to read. In some instances, this means that anyone spying on your data streams can see the data encased in your XML.

A great way to add an extra layer of security to your XML data applications is with the Tiny Encryption Algorithm (TEA), which has a small footprint and a low overhead. Its small size makes it easy to implement in JavaScript.

Two disclaimers about TEA

Although TEA is a valuable encryption algorithm, there's a method for cracking it, so refrain from relying on TEA for encrypting credit card or other sensitive information.

Another consideration is that you need to be extremely careful when you add encryption to Web pages. Since Web applications are stateless, it might be wise to avoid asking the user for his or her password repeatedly by storing it in a cookie or passing it as a form element. This defeats the purpose of securing the data, since anyone trying to break through your security measures will have easy access to the password.

In order to avoid this, you should have a setup screen where the user enters his or her username and password to create an account. The user is given an account ID that is stored in a database with his or her username and password. This account ID passes back and forth from client to server, decrypting the data on the server side by selecting the username and password from the database. Then the user can enter his or her username and password to create the encryption on the Web page.

Encrypting data before transmission

Now you have a Web application in which a user updates or adds information that you want to keep secure. This data is transmitted back to the server through a form submission or an XML proxy such as XMLHTTP. Before you transmit the data, you want to encrypt its contents. To do this, you need the user's username and password.

Here's how to set up the page for Mozilla browsers:

<xml id="xmlData" style="visibility:hidden;">
    <root>
        <user>
            <first_name></first_name>
            <last_name></last_name>
            <phone></phone>
        </user>
    </root>
</xml>
<form name="thisForm">
    First Name: <input type="textbox" name="txtFName" size="25"><br>
    Last Name: <input type="textbox" name="txtLName" size="25"><br>
    Phone: <input type="textbox" name="txtPhone" size="25"><br>
    Username: <input type="textbox" name="txtUName" size="25"><br>
    Password: <input type="password" name="txtPassword" size="25">
</form>
<form method="POST" action="page2.asp" name="thatForm">
    <input type="hidden" name="txtXMLEnc">
    <input type="hidden" name="txtAcctID" value="[AcctID]">
    <input type="button" value="Submit" onclick="thatForm_submit()">
</form>
</body>
</html>

I've coded the hidden <INPUT>s with the XML data and the AcctID because "thatForm" is going to be submitted to the server. We definitely don't want to send encrypted XML data and the source data in plain text.

Here's the onclick event handler for the button for Mozilla browsers:

function thatForm_submit() {
    //First, grab the XML data island in the page.  This returns the
    //DOM in Mozilla-based browsers.
    var xmlNode = window.document.getElementsByTagName('xml');
    var root = xmlNode[0].childNodes[1]; //root node
    var userNode = root.childNodes[1]; //user node
    var username = document.thisForm.txtUName.value;
    var password = document.thisForm.txtPassword.value;
    
    userNode.childNodes[2].nodeValue =
        encrypt(document.thisForm.txtFName.value,
                     username+password);
    userNode.childNodes[4].nodeValue =
        encrypt(document.thisForm.txtLName.value,
                     username+password);
    userNode.childNodes[6].nodeValue =
        encrypt(document.thisForm.txtPhone.value,
                     username+password);
    document.thatForm.txtXMLEnc.value = get_xml(root);
    document.thatForm.submit();
}
function get_xml(node) {
    var lt = "<";
    var lts = lt + "/";
    var gt = ">";
    var s = lt + node.nodeName + gt;
    if (node.nextSibling.nodeType == 3 && node.nextSibling.nodeValue != "")
        s += node.nextSibling.nodeValue;
    if (node.hasChildNodes()) {
        if (node.firstChild.nodeType == 3 && node.firstChild.nodeValue != "")
            s += node.firstChild.nodeValue;
        var i = 0;
        while (node.childNodes[i]) {
            if (node.childNodes[i].nodeType != 3) {
                s += get_xml(node.childNodes[i]);
            }
            i++;
        }
    }
    s += lts + node.nodeName + gt;
    return s;
}

When the onclick handler occurs for the Submit button, the XML data island is navigated and values are set for the individual nodes using the encrypt() method of the TEA. (For this portion of the sample, I used Chris Veness's JavaScript implementation of Block TEA.) Then I retrieve the XML data string by navigating the root node of the XML DOM Document and grabbing nodeNames and nodeValues. The txtXMLEnc form element value is set and the form is submitted. On the server, I'll use the user's AcctID to look up their username and password. I'll use these values to decrypt and save the data.

Making this example work in Internet Explorer

The JavaScript source code is intended for Mozilla browsers, but you can make this code work in Internet Explorer with a few adjustments. You simply need to use the selectSingleNode() method on the XML data island DOM Document to retrieve the individual nodes. Also, you don't need to run the get_xml() function to retrieve the XML string of the DOM Document. Finally, you use the XML property on the XML data island DOM Document.

Phillip Perkins is a contractor with Ajilon Consulting. His experience ranges from machine control and client/server to corporate intranet applications.

Editor's Picks