Search code examples
javascriptjqueryajaxencryptioncryptojs

Using crypto-js to encrypt password and send form via ajax (and decrypt in java), I get : TypeError: Cannot read property 'words' of undefined


I am trying to secure the password that i am sending from an HTML form to a Java Servlet (via ajax). I use crypto-js in my js to encrypt the password. When the code reaches the ajax call, I get the error:

Uncaught TypeError: Cannot read property 'words' of undefined (aes.js:8)

(I already made sure that the key I'm sending is not null)

This is my code:


login.jsp:

<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>Login</title>
<link rel="stylesheet" href="css/style.css">
<script src="jquery-1.11.2.min.js"></script>
<script type='text/javascript'>
localStorage.setItem('loggedin', false);
</script>
<script src="login.js"></script>
<script src="http://crypto-    js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/pbkdf2.js"></script>
<script type="text/javascript">
function convertAndSubmit()
{
    var salt = CryptoJS.lib.WordArray.random(128/8);
    var iv = CryptoJS.lib.WordArray.random(128/8);           
    console.log('salt  '+ salt );
    console.log('iv  '+ iv );
    var key128Bits100Iterations = CryptoJS.PBKDF2('1234567890987654', salt,         { keySize: 256/32, iterations: 100 });
    console.log( 'key128Bits100Iterations '+ key128Bits100Iterations);
    var encrypted = CryptoJS.AES.encrypt($("#pwd").val(), key128Bits100Iterations, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7  }).toString();
    checkLogin(encrypted, randkey, salt, iv);
}
    </script>
  </head>

  <body>

<div class="container">
  <div id="login-form">
    <h3>Login</h3>

    <fieldset>
      <form action="javascript:void(0);" method="get" name="login">
        <input type="email" id="email" name="email" required value="Email"      onBlur="if(this.value=='')this.value='Email'" onFocus="if(this.value=='Email')this.value='' ">
        <input type="password" id="pwd" name="pwd" required value="Password" onBlur="if(this.value=='')this.value='Password'" onFocus="if(this.value=='Password')this.value='' "> 
        <input type="submit" value="Login" id="login" onclick="javascript:convertAndSubmit()">
      </form>
    </fieldset>

  </div> <!-- end login-form -->
</div>
<div id="output"></div>
  </body>
</html>

login.js:

function ajaxLogin(credentials) {
    var retData = null;
    $.ajax({ //this is where the code generates the error
        async: false,
        type: 'GET',
        data: credentials,
        url: "http://localhost:8080/AtlasServices/Login",
        success: function(data) {
            retData = data;
        }
    });
    return retData;
}

function checkLogin(encrypted, key, s, i) {
    var credentials = {
        email: $("#email").val(),
        pass: encrypted,
        key: key,
        salt: s,
        iv: i
    };

    var res = window.ajaxLogin(credentials);
    if (res["userlogged"] !== "true") {
        alert("Failed to log in");
        $("#email").val("");
        $("#pwd").val("");
        localStorage.setItem('loggedin', false);
    } else {
        localStorage.setItem('loggedin', true);
        window.location = "http://localhost:8080/AtlasServices/main.html";
    }
}

I was searching for a long time for a solution...will really love some help, thanks:)


Solution

  • CryptoJS.lib.WordArray.random(..) creates WordArray object.

    From your code :

    var salt = CryptoJS.lib.WordArray.random(128/8);
    var iv = CryptoJS.lib.WordArray.random(128/8);    
    

    This means salt and iv is an object not a string.

    You are able to log salt and iv as encoded because console.log calls toString internally from salt and iv which encodes the WordArray

    All you need to do is encode these explicitly:

    checkLogin(encrypted, randkey, salt.toString(), iv.toString());
    

    Note: The error you've got is related with the JQuery; while building url parameters JQuery reads all objects, sub-objects, arrays and functions etc... , When you send WordArray as an object jQuery tries to call it's functions to fetch return value into the url parameter.

    In your case it is calling the concat function with an undefined parameters, which leads to the error you get. You can simply reproduce this error by calling $.param(salt) (or for iv).