(function () { 'use strict'; var crypto = window.crypto; var Unibabel = window.Unibabel; function deriveKey(saltHex, passphrase, iter) { var keyLenBits = 128; var kdfname = "PBKDF2"; var aesname = "AES-CBC"; // AES-CTR is also popular // 100 - probably safe even on a browser running from a raspberry pi using pure js ployfill // 10000 - no noticeable speed decrease on my MBP // 100000 - you can notice // 1000000 - annoyingly long var iterations = iter || 100; // something a browser on a raspberry pi or old phone could do var hashname = "SHA-256"; var extractable = true; console.log(''); console.log('passphrase', passphrase); console.log('salt (hex)', saltHex); //console.log('salt (hex)', Unibabel.bufferToHex(saltBuf)); console.log('iterations', iterations); console.log('keyLen (bytes)', keyLenBits / 8); console.log('digest', hashname); // First, create a PBKDF2 "key" containing the password return crypto.subtle.importKey( "raw" , Unibabel.utf8ToBuffer(passphrase) , { "name": kdfname } , false , ["deriveKey"]). // Derive a key from the password then(function (passphraseKey) { return crypto.subtle.deriveKey( { "name": kdfname , "salt": Unibabel.hexToBuffer(saltHex) , "iterations": iterations , "hash": hashname } , passphraseKey // required to be 128 or 256 bits , { "name": aesname, "length": keyLenBits } // Key we want , extractable // Extractble , [ "encrypt", "decrypt" ] // For new key ); }). // Export it so we can display it then(function (aesKey) { return crypto.subtle.exportKey("raw", aesKey).then(function (arrbuf) { return new Uint8Array(arrbuf); }); }). catch(function (err) { window.alert("Key derivation failed: " + err.message); }); } function test() { // Part of the salt is application-specific (same on iOS, Android, and Web) var saltHex = '942c2db750b5f57f330226b2b498c6d3'; var passphrase = 'Pizzas are like children'; //var passphrase = "I'm a ☢ ☃ who speaks 中国语文!"; var iter = 1672; // NOTE: the salt will be truncated to the length of the hash algo being used return deriveKey(saltHex, passphrase, iter).then(function (keyBuf) { var hexKey = Unibabel.bufferToHex(keyBuf); console.log('[TEST] hexKey'); console.log(hexKey); }); } test(); }());