mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-06-02 08:09:36 +00:00
Update OSCrypto lib
This commit is contained in:
@@ -366,7 +366,9 @@ function GetWindowsPasswordsResource(aProfileFolder) {
|
||||
_rowToLoginInfo(row) {
|
||||
let loginInfo = {
|
||||
username: row.getResultByName("username_value"),
|
||||
password: crypto.decryptData(row.getResultByName("password_value")),
|
||||
password: crypto.
|
||||
decryptData(crypto.arrayToString(row.getResultByName("password_value")),
|
||||
null),
|
||||
hostName: NetUtil.newURI(row.getResultByName("origin_url")).prePath,
|
||||
submitURL: null,
|
||||
httpRealm: null,
|
||||
|
||||
@@ -11,14 +11,27 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ctypes", "resource://gre/modules/ctypes.jsm");
|
||||
|
||||
const FLAGS_NOT_SET = 0;
|
||||
|
||||
const wintypes = {
|
||||
BOOL: ctypes.bool,
|
||||
BYTE: ctypes.uint8_t,
|
||||
DWORD: ctypes.uint32_t,
|
||||
PBYTE: ctypes.unsigned_char.ptr,
|
||||
PCHAR: ctypes.char.ptr,
|
||||
PDWORD: ctypes.uint32_t.ptr,
|
||||
PVOID: ctypes.voidptr_t,
|
||||
WORD: ctypes.uint16_t,
|
||||
}
|
||||
|
||||
function OSCrypto() {
|
||||
this._structs = {};
|
||||
this._functions = new Map();
|
||||
this._libs = new Map();
|
||||
this._structs.DATA_BLOB = new ctypes.StructType("DATA_BLOB",
|
||||
[
|
||||
{cbData: ctypes.uint32_t},
|
||||
{pbData: ctypes.uint8_t.ptr}
|
||||
{cbData: wintypes.DWORD},
|
||||
{pbData: wintypes.PVOID}
|
||||
]);
|
||||
|
||||
try {
|
||||
@@ -29,31 +42,30 @@ function OSCrypto() {
|
||||
this._functions.set("CryptProtectData",
|
||||
this._libs.get("crypt32").declare("CryptProtectData",
|
||||
ctypes.winapi_abi,
|
||||
ctypes.uint32_t,
|
||||
wintypes.DWORD,
|
||||
this._structs.DATA_BLOB.ptr,
|
||||
ctypes.voidptr_t,
|
||||
ctypes.voidptr_t,
|
||||
ctypes.voidptr_t,
|
||||
ctypes.voidptr_t,
|
||||
ctypes.uint32_t,
|
||||
wintypes.PVOID,
|
||||
wintypes.PVOID,
|
||||
wintypes.PVOID,
|
||||
wintypes.PVOID,
|
||||
wintypes.DWORD,
|
||||
this._structs.DATA_BLOB.ptr));
|
||||
|
||||
this._functions.set("CryptUnprotectData",
|
||||
this._libs.get("crypt32").declare("CryptUnprotectData",
|
||||
ctypes.winapi_abi,
|
||||
ctypes.uint32_t,
|
||||
wintypes.DWORD,
|
||||
this._structs.DATA_BLOB.ptr,
|
||||
ctypes.voidptr_t,
|
||||
ctypes.voidptr_t,
|
||||
ctypes.voidptr_t,
|
||||
ctypes.voidptr_t,
|
||||
ctypes.uint32_t,
|
||||
wintypes.PVOID,
|
||||
wintypes.PVOID,
|
||||
wintypes.PVOID,
|
||||
wintypes.PVOID,
|
||||
wintypes.DWORD,
|
||||
this._structs.DATA_BLOB.ptr));
|
||||
this._functions.set("LocalFree",
|
||||
this._libs.get("kernel32").declare("LocalFree",
|
||||
ctypes.winapi_abi,
|
||||
ctypes.uint32_t,
|
||||
ctypes.voidptr_t));
|
||||
wintypes.DWORD,
|
||||
wintypes.PVOID));
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
this.finalize();
|
||||
@@ -62,18 +74,101 @@ function OSCrypto() {
|
||||
}
|
||||
OSCrypto.prototype = {
|
||||
/**
|
||||
* Decrypt an array of numbers using the windows CryptUnprotectData API.
|
||||
* @param {number[]} array - the encrypted array that needs to be decrypted.
|
||||
* @returns {string} the decryption of the array.
|
||||
* Convert an array containing only two bytes unsigned numbers to a string.
|
||||
* @param {number[]} arr - the array that needs to be converted.
|
||||
* @returns {string} the string representation of the array.
|
||||
*/
|
||||
decryptData(array) {
|
||||
arrayToString(arr) {
|
||||
let str = "";
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
str += String.fromCharCode(arr[i]);
|
||||
}
|
||||
return str;
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert a string to an array.
|
||||
* @param {string} str - the string that needs to be converted.
|
||||
* @returns {number[]} the array representation of the string.
|
||||
*/
|
||||
stringToArray(str) {
|
||||
let arr = [];
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
arr.push(str.charCodeAt(i));
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculate the hash value used by IE as the name of the registry value where login details are
|
||||
* stored.
|
||||
* @param {string} data - the string value that needs to be hashed.
|
||||
* @returns {string} the hash value of the string.
|
||||
*/
|
||||
getIELoginHash(data) {
|
||||
// return the two-digit hexadecimal code for a byte
|
||||
function toHexString(charCode) {
|
||||
return ("00" + charCode.toString(16)).slice(-2);
|
||||
}
|
||||
|
||||
// the data needs to be encoded in null terminated UTF-16
|
||||
data += "\0";
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
|
||||
createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-16";
|
||||
// result is an out parameter,
|
||||
// result.value will contain the array length
|
||||
let result = {};
|
||||
// dataArray is an array of bytes
|
||||
let dataArray = converter.convertToByteArray(data, result);
|
||||
// calculation of SHA1 hash value
|
||||
let cryptoHash = Cc["@mozilla.org/security/hash;1"].
|
||||
createInstance(Ci.nsICryptoHash);
|
||||
cryptoHash.init(cryptoHash.SHA1);
|
||||
cryptoHash.update(dataArray, dataArray.length);
|
||||
let hash = cryptoHash.finish(false);
|
||||
|
||||
let tail = 0; // variable to calculate value for the last 2 bytes
|
||||
// convert to a character string in hexadecimal notation
|
||||
for (let c of hash) {
|
||||
tail += c.charCodeAt(0);
|
||||
}
|
||||
hash += String.fromCharCode(tail % 256);
|
||||
|
||||
// convert the binary hash data to a hex string.
|
||||
let hashStr = [toHexString(hash.charCodeAt(i)) for (i in hash)].join("");
|
||||
return hashStr.toUpperCase();
|
||||
},
|
||||
|
||||
/**
|
||||
* Decrypt a string using the windows CryptUnprotectData API.
|
||||
* @param {string} data - the encrypted string that needs to be decrypted.
|
||||
* @param {?string} entropy - the entropy value of the decryption (could be null). Its value must
|
||||
* be the same as the one used when the data was encrypted.
|
||||
* @returns {string} the decryption of the string.
|
||||
*/
|
||||
decryptData(data, entropy = null) {
|
||||
let array = this.stringToArray(data);
|
||||
let decryptedData = "";
|
||||
let encryptedData = ctypes.uint8_t.array(array.length)(array);
|
||||
let encryptedData = wintypes.BYTE.array(array.length)(array);
|
||||
let inData = new this._structs.DATA_BLOB(encryptedData.length, encryptedData);
|
||||
let outData = new this._structs.DATA_BLOB();
|
||||
let entropyParam;
|
||||
if (entropy) {
|
||||
let entropyArray = this.stringToArray(entropy);
|
||||
entropyArray.push(0);
|
||||
let entropyData = wintypes.WORD.array(entropyArray.length)(entropyArray);
|
||||
let optionalEntropy = new this._structs.DATA_BLOB(entropyData.length * 2,
|
||||
entropyData);
|
||||
entropyParam = optionalEntropy.address();
|
||||
} else {
|
||||
entropyParam = null;
|
||||
}
|
||||
|
||||
let status = this._functions.get("CryptUnprotectData")(inData.address(), null,
|
||||
null, null, null, 0,
|
||||
outData.address());
|
||||
entropyParam,
|
||||
null, null, FLAGS_NOT_SET,
|
||||
outData.address());
|
||||
if (status === 0) {
|
||||
throw new Error("decryptData failed: " + status);
|
||||
}
|
||||
@@ -81,32 +176,43 @@ OSCrypto.prototype = {
|
||||
// convert byte array to JS string.
|
||||
let len = outData.cbData;
|
||||
let decrypted = ctypes.cast(outData.pbData,
|
||||
ctypes.uint8_t.array(len).ptr).contents;
|
||||
wintypes.BYTE.array(len).ptr).contents;
|
||||
for (let i = 0; i < decrypted.length; i++) {
|
||||
decryptedData += String.fromCharCode(decrypted[i]);
|
||||
}
|
||||
|
||||
this._functions.get("LocalFree")(outData.pbData);
|
||||
return decryptedData;
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Encrypt a string using the windows CryptProtectData API.
|
||||
* @param {string} string - the string that is going to be encrypted.
|
||||
* @returns {number[]} the encrypted string encoded as an array of numbers.
|
||||
* @param {string} data - the string that is going to be encrypted.
|
||||
* @param {?string} entropy - the entropy value of the encryption (could be null). Its value must
|
||||
* be the same as the one that is going to be used for the decryption.
|
||||
* @returns {string} the encrypted string.
|
||||
*/
|
||||
encryptData(string) {
|
||||
let encryptedData = [];
|
||||
let decryptedData = ctypes.uint8_t.array(string.length)();
|
||||
encryptData(data, entropy = null) {
|
||||
let encryptedData = "";
|
||||
let decryptedData = wintypes.BYTE.array(data.length)(this.stringToArray(data));
|
||||
|
||||
for (let i = 0; i < string.length; i++) {
|
||||
decryptedData[i] = string.charCodeAt(i);
|
||||
let inData = new this._structs.DATA_BLOB(data.length, decryptedData);
|
||||
let outData = new this._structs.DATA_BLOB();
|
||||
let entropyParam;
|
||||
if (!entropy) {
|
||||
entropyParam = null;
|
||||
} else {
|
||||
let entropyArray = this.stringToArray(entropy);
|
||||
entropyArray.push(0);
|
||||
let entropyData = wintypes.WORD.array(entropyArray.length)(entropyArray);
|
||||
let optionalEntropy = new this._structs.DATA_BLOB(entropyData.length * 2,
|
||||
entropyData);
|
||||
entropyParam = optionalEntropy.address();
|
||||
}
|
||||
|
||||
let inData = new this._structs.DATA_BLOB(string.length, decryptedData);
|
||||
let outData = new this._structs.DATA_BLOB();
|
||||
let status = this._functions.get("CryptProtectData")(inData.address(), null,
|
||||
null, null, null, 0,
|
||||
entropyParam,
|
||||
null, null, FLAGS_NOT_SET,
|
||||
outData.address());
|
||||
if (status === 0) {
|
||||
throw new Error("encryptData failed: " + status);
|
||||
@@ -115,12 +221,8 @@ OSCrypto.prototype = {
|
||||
// convert byte array to JS string.
|
||||
let len = outData.cbData;
|
||||
let encrypted = ctypes.cast(outData.pbData,
|
||||
ctypes.uint8_t.array(len).ptr).contents;
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
encryptedData.push(encrypted[i]);
|
||||
}
|
||||
|
||||
wintypes.BYTE.array(len).ptr).contents;
|
||||
encryptedData = this.arrayToString(encrypted);
|
||||
this._functions.get("LocalFree")(outData.pbData);
|
||||
return encryptedData;
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user