javascriptajaxencryptionsjcl

JS: Decryption not possible after storing in database (SJCL)


I'm experimenting with the Stanford Javascript Crypto Library (SJCL) and want to encrypt and later decrypt a string.

The following code works fine:

var pw = "password";
var message = "message";
var encrypted = sjcl.encrypt(pw, message);
alert(encrypted);

var decrypted = sjcl.decrypt(pw, encrypted)
alert(decrypted);

The first alert show the encrypted data and the second alert shows "message". However I need to store var encrypted in a SQL database so I send it through ajax to the server which stores it in a table.

I later request the encrypted message (again through ajax) and store it in the variable encrypted. After that I want to decrypt it:

var decrypted = sjcl.decrypt(pw, encrypted);
alert(decrypted);

But I don't get an alert which contains the string "messages", the console only displays "uncaught exception: CORRUPT: ccm: tag doesn't match".

I didn't change the encrypted text, the only difference between the two examples is that I got the variable encrypted from the server.

Any ideas what is wrong?

EDIT:

The ajax code to store it in the DB:

var url = "action.php?action=r&n="+name+"&pw="+pw_hashed+"&encrypted="+encrypted;
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function()
{
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
    {
        if(xmlhttp.responseText == "success")
        {
            alert("success");
        }
    }
}

And the ajax code to receive the data:

var url = "action.php?action=l&n="+name+"&pw="+pw_hashed;
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function()
{
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
    {
        if(xmlhttp.responseText == "success")
        {
            var encrypted = xmlhttp.responseText;;
        }
    }
}

I also compared the the encrypted string right after the encryption with the string on the server and with the one on the client side (for the decryption): all are the same.


Solution

  • The issue is almost-certainly in how you are constructing your query parameters. You need to encode each parameters value using encodeURIComponent, as the data may contain characters such as + which will be converted into as space unless properly encoded.

    Your storage URL using encodeURIComponent:

    var url = "action.php?action=r&n="+encodeURIComponent(name)+"&pw="+encodeURIComponent(pw_hashed)+"&encrypted="+encodeURIComponent(encrypted);
    

    And your retrieval URL:

    var url = "action.php?action=l&n="+encodeURIComponent(name)+"&pw="+encodeURIComponent(pw_hashed);