Skip to content

Instantly share code, notes, and snippets.

@bitbeans
Created May 20, 2015 09:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bitbeans/41e29b79a87420bf6649 to your computer and use it in GitHub Desktop.
Save bitbeans/41e29b79a87420bf6649 to your computer and use it in GitHub Desktop.
/*
* bitbeans.sodium.js
*
* Copyright (c) 2015 bitbeans
*
* Version: 1.0.0
*
* Uses:
* https://github.com/jedisct1/libsodium.js
* https://github.com/julien-maurel/jQuery-Storage-API
*/
var bitbeans = bitbeans || {};
bitbeans.global = new function() {
storage=$.sessionStorage;
// check if the browser can handle our safety standard
this.isCompatible = function () {
try {
// check for sodium support
var to_hex = sodium.to_hex
// also check for sessionStorage
if (typeof(sessionStorage) === 'undefined') {
throw new Error("sessionStorage not supported");
}
return true;
}
catch(err) {
return false;
}
};
}
bitbeans.security = new function() {
// this one should be called on the login script, so the user can
// encrypt and decrypt personal database fields locally before we store them.
// the password_hash should come as 64 byte blake2b hash.
this.prepareUserStorage = function (username, password_hash) {
if ((typeof username !== "undefined") && (typeof password_hash !== "undefined")) {
if (!storage.isSet('userdata.key')) {
if (password_hash.length == 128) {
// first generate a salt from the given username
var salt = sodium.crypto_generichash(sodium.crypto_pwhash_scryptsalsa208sha256_SALTBYTES, username, 'uint8array');
// next derive a key from the given password_hash and the salt
var key = sodium.crypto_pwhash_scryptsalsa208sha256(sodium.from_hex(password_hash), salt,
sodium.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE,
sodium.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE, 32);
// clear the salt
sodium.memzero(salt);
// save the key to the session storage
storage.set('userdata.key', sodium.to_hex(key));
// clear the key
sodium.memzero(key);
}
else {
throw new Error("password_hash seems to be of invalid length");
}
}
}
else {
throw new Error("missing parameters");
}
};
this.userEncrypt = function (userdata) {
if (typeof userdata !== "undefined") {
if (storage.isSet('userdata.key')) {
// retrieve the key from the session storage
var key = sodium.from_hex(storage.get('userdata.key'));
// generate a random nonce
var nonce = sodium.randombytes_buf(sodium.crypto_box_NONCEBYTES);
var encryptedUserData = sodium.to_hex(nonce) + sodium.to_hex(sodium.crypto_secretbox_easy(userdata, nonce, key));
sodium.memzero(key);
sodium.memzero(nonce);
return encryptedUserData;
}
else {
throw new Error("missing userdata.key");
}
}
else {
throw new Error("missing parameters");
}
};
this.userDecrypt = function (encryptedUserData) {
if (typeof encryptedUserData !== "undefined") {
if (storage.isSet('userdata.key')) {
// retrieve the key from the session storage
var key = sodium.from_hex(storage.get('userdata.key'));
// get the nonce from the encryptedUserData
var nonce = sodium.from_hex(encryptedUserData.substr(0, 48));
var cipher = sodium.from_hex(encryptedUserData.substr(48));
var decryptedUserData = sodium.crypto_secretbox_open_easy(cipher, nonce, key, 'text');
sodium.memzero(key);
sodium.memzero(nonce);
sodium.memzero(cipher);
return decryptedUserData;
}
else {
throw new Error("missing userdata.key");
}
}
else {
throw new Error("missing parameters");
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment