diff options
author | ausiv4 <ausiv4@eb105b4a-77de-11de-a249-6bf219df57d5> | 2009-08-12 17:01:23 +0000 |
---|---|---|
committer | ausiv4 <ausiv4@eb105b4a-77de-11de-a249-6bf219df57d5> | 2009-08-12 17:01:23 +0000 |
commit | 124ef39cb84dec12d21a36e98039e6a5042e7317 (patch) | |
tree | 91a0b28d2bf6b3b952d8b575a752d45193ca2d8b /javascript/cryptoHelpers.js | |
parent | 900dc01238f0c0f6830d487d93f9176e711104fe (diff) |
When upgrading the user from a non-srp account to an SRP account, the client must send the server the password. I wasn't happy about doing this
in plaintext, so I've incorporated slowAES on both the client and the server to encrypt the password before it is sent, using the key generated
in the first SRP transaction.
Diffstat (limited to 'javascript/cryptoHelpers.js')
-rw-r--r-- | javascript/cryptoHelpers.js | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/javascript/cryptoHelpers.js b/javascript/cryptoHelpers.js new file mode 100644 index 0000000..a77ee42 --- /dev/null +++ b/javascript/cryptoHelpers.js @@ -0,0 +1,185 @@ +/* + * cryptoHelpers.js: implements AES - Advanced Encryption Standard + * from the SlowAES project, http://code.google.com/p/slowaes/ + * + * Copyright (c) 2008 Josh Davis ( http://www.josh-davis.org ), + * Mark Percival ( http://mpercival.com ), + * Johan Sundstrom ( http://ecmanaut.blogspot.com ), + * John Resig ( http://ejohn.org ) + * + * Licensed under the Apache License, Version 2.0 + * http://www.apache.org/licenses/ + */ + + + +var cryptoHelpers = { + + // encodes a unicode string to UTF8 (8 bit characters are critical to AES functioning properly) + encode_utf8:function(s) + { + try{return unescape(encodeURIComponent(s));} + catch(e){throw 'error during utf8 encoding: cryptoHelpers.encode_utf8.';} + }, + + + // decodes a UTF8 string back to unicode + decode_utf8:function(s) + { + try{return decodeURIComponent(escape(s));} + catch(e){throw('error during utf8 decoding: cryptoHelpers.decode_utf8.');} + }, + + //convert a number array to a hex string + toHex:function() + { + var array = []; + if(arguments.length == 1 && arguments[0].constructor == Array) + array = arguments[0]; + else + array = arguments; + var ret = ''; + for(var i = 0;i < array.length;i++) + ret += (array[i] < 16 ? '0' : '') + array[i].toString(16); + return ret.toLowerCase(); + }, + + //convert a hex string to a number array + toNumbers:function(s) + { + var ret = []; + s.replace(/(..)/g,function(s){ + ret.push(parseInt(s,16)); + }); + return ret; + }, + + // get a random number in the range [min,max] + getRandom:function(min,max) + { + if(min === null) + min = 0; + if(max === null) + max = 1; + return Math.floor(Math.random()*(max+1)) + min; + }, + + generateSharedKey:function(len) + { + if(len === null) + len = 16; + var key = []; + for(var i = 0; i < len*2; i++) + key.push(this.getRandom(0,255)); + return key; + }, + + generatePrivateKey:function(s,size) + { + var sha = jsHash.sha2.arr_sha256(s); + return sha.slice(0,size); + }, + + convertStringToByteArray: function(s) + { + var byteArray = []; + for(var i = 0;i < s.length;i++) + { + byteArray.push(s.charCodeAt(i)); + } + return byteArray; + }, + + convertByteArrayToString: function(byteArray) + { + var s = ''; + for(var i = 0;i < byteArray.length;i++) + { + s += String.fromCharCode(byteArray[i]); + } + return s; + }, + + base64: { + // Takes a Nx16x1 byte array and converts it to Base64 + + chars: [ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/', + '=' // for decoding purposes + ], + + encode_line: function(flatArr){ + var b64 = ''; + + for (var i = 0; i < flatArr.length; i += 3){ + b64 += this.chars[flatArr[i] >> 2]; + b64 += this.chars[((flatArr[i] & 3) << 4) | (flatArr[i + 1] >> 4)]; + if (!(flatArr[i + 1] === null)){ + b64 += this.chars[((flatArr[i + 1] & 15) << 2) | (flatArr[i + 2] >> 6)]; + }else{ + b64 += '='; + } + if (!(flatArr[i + 2] === null)){ + b64 += this.chars[flatArr[i + 2] & 63]; + }else{ + b64 += '='; + } + } + return b64; + }, + + encode: function(flatArr) + { + var b64 = this.encode_line(flatArr); + // OpenSSL is super particular about line breaks + var broken_b64 = b64.slice(0, 64) + '\n'; + for (var i = 1; i < (Math.ceil(b64.length / 64)); i++) + { + broken_b64 += b64.slice(i * 64, i * 64 + 64) + (Math.ceil(b64.length / 64) == i + 1 ? '': '\n'); + } + return broken_b64; + }, + + decode: function(string) + { + string = string.replace(/[\r\n\t ]+/g, '') + '===='; // drop all whitespaces and pad with '=' (end of b64 marker) + var flatArr = []; + var c = []; + //var b = []; + for (var i = 0; true ; i = i + 4){ + c[0] = this.chars.indexOf(string.charAt(i)); + if(c[0] == 64){ + return flatArr; + } + c[1] = this.chars.indexOf(string.charAt(i + 1)); + c[2] = this.chars.indexOf(string.charAt(i + 2)); + c[3] = this.chars.indexOf(string.charAt(i + 3)); + + if( + (c[0] < 0) || // char1 is wrong + (c[1] < 0) || (c[1] == 64) || // char2 is wrong + (c[2] < 0) || // char3 is neither an valid char nor '=' + (c[3] < 0) // char4 is neither an valid char nor '=' + ){ + throw 'error during base64 decoding at pos '+i+': cryptoHelpers.base64.decode.'; + } + + flatArr.push((c[0] << 2) | (c[1] >> 4)); + if(c[2] >= 0 && c[2] < 64){ + flatArr.push(((c[1] & 15) << 4) | (c[2] >> 2)); + if(c[3] >= 0 && c[2] < 64){ + flatArr.push(((c[2] & 3) << 6) | c[3]); + } + } + } + } + } +}; + |