From 124ef39cb84dec12d21a36e98039e6a5042e7317 Mon Sep 17 00:00:00 2001 From: ausiv4 Date: Wed, 12 Aug 2009 17:01:23 +0000 Subject: 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. --- javascript/cryptoHelpers.js | 185 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 javascript/cryptoHelpers.js (limited to 'javascript/cryptoHelpers.js') 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]); + } + } + } + } + } +}; + -- cgit v1.2.3