Brigand
Brigand

Reputation: 86230

How can I password protect localstorage data?

Localstorage is stored without any protection. Web apps are becoming less dependant on servers.

How can an app which uses localstorage for data store it so that a password is required to read it.

Upvotes: 1

Views: 4631

Answers (1)

Brigand
Brigand

Reputation: 86230

Passwords on servers usually work by using a hash like SHA1 or SHA512. When the server receives a request with a password, it hashes that, and compares them. If they match, the server loads some data, processes it, and sends it back to the user. If we tried to do this with client-side JavaScript, we would have to already have the plain text available.

An alternative to hashing is a cipher, such as AES. There's a crypto-js library on Google which provides services like these. The stand-alone minified AES file is about 13kb before gzip.

One limitation of the library is JSON serialization of the AES data. Their documentation, does provide a solution to this.

Note: this doesn't JSON encode your object, it JSON encodes the data needed to decrypt your object (except the password, of course).

var JsonFormatter = {
    stringify: function (cipherParams) {
        var jsonObj = {ct: cipherParams.ciphertext.toString(CryptoJS.enc.Base64)};
        if (cipherParams.iv) {jsonObj.iv = cipherParams.iv.toString();}
        if (cipherParams.salt) {jsonObj.s = cipherParams.salt.toString();}
        return JSON.stringify(jsonObj);
    },

    parse: function (jsonStr) {
        var jsonObj = JSON.parse(jsonStr);
        var cipherParams = CryptoJS.lib.CipherParams.create({
            ciphertext: CryptoJS.enc.Base64.parse(jsonObj.ct)
        });
        if (jsonObj.iv) {cipherParams.iv = CryptoJS.enc.Hex.parse(jsonObj.iv)}
        if (jsonObj.s) {cipherParams.salt = CryptoJS.enc.Hex.parse(jsonObj.s)}
        return cipherParams;
    }
};

To store data, we could do this

var encoded = CryptoJS.AES.encrypt(JSON.stringify(data), password, {format: JsonFormatter}).ciphertext.toString();
localStorage.setItem("secret_stuff", encoded);

To get it back, we can do:

var stored = localStorage.getItem("secret_stuff");
var jsonString = CryptoJS.AES.decrypt(stored, password, {formatter: JsonFormatter}).toString();
var secretObject = JSON.parse(jsonString);

It might also be wise to "forget" the user's password if they haven't moved the mouse in a few minutes.

Upvotes: 5

Related Questions