Created
May 20, 2015 09:24
-
-
Save bitbeans/41e29b79a87420bf6649 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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