mirror of
https://github.com/keepassxreboot/keepassxc-browser.git
synced 2026-03-11 08:54:43 +00:00
181 lines
4.5 KiB
JavaScript
181 lines
4.5 KiB
JavaScript
/*
|
|
* 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; ; 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]);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
},
|
|
|
|
};
|