Cleanup RSA and util code

This commit is contained in:
Tankred Hase 2016-02-03 13:52:18 +07:00
parent 55bd9757e7
commit 4d325ca65c
3 changed files with 78 additions and 36 deletions

View File

@ -29,6 +29,9 @@
"before": true,
"beforeEach": true,
"after": true,
"afterEach": true
"afterEach": true,
"escape": true,
"unescape": true,
"asmCrypto": true
}
}

View File

@ -24,6 +24,8 @@
* @module crypto/public_key/rsa
*/
'use strict';
var BigInteger = require('./jsbn.js'),
util = require('../../util.js'),
random = require('../random.js'),
@ -119,7 +121,7 @@ function RSA() {
// "empty" RSA key constructor
function keyObject() {
function KeyObject() {
this.n = null;
this.e = 0;
this.ee = null;
@ -167,8 +169,8 @@ function RSA() {
};
keys = webCrypto.generateKey(keyGenOpt, true, ['sign', 'verify']);
if (!(typeof keys.then === 'function')) { // IE11 KeyOperation
keys = convertKeyOperation(keys, 'Error generating RSA key pair.');
if (typeof keys.then !== 'function') { // IE11 KeyOperation
keys = util.promisifyIE11Op(keys, 'Error generating RSA key pair.');
}
}
@ -185,15 +187,15 @@ function RSA() {
// export the generated keys as JsonWebKey (JWK)
// https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33
var key = webCrypto.exportKey('jwk', keypair.privateKey);
if (!(typeof key.then === 'function')) { // IE11 KeyOperation
key = convertKeyOperation(key, 'Error exporting RSA key pair.');
if (typeof key.then !== 'function') { // IE11 KeyOperation
key = util.promisifyIE11Op(key, 'Error exporting RSA key pair.');
}
return key;
}
function decodeKey(jwk) {
// map JWK parameters to local BigInteger type system
var key = new keyObject();
var key = new KeyObject();
key.n = toBigInteger(jwk.n);
key.ee = new BigInteger(E, 16);
key.d = toBigInteger(jwk.d);
@ -210,23 +212,12 @@ function RSA() {
return key;
}
function convertKeyOperation(keyop, errmsg) {
return new Promise(function(resolve, reject) {
keyop.onerror = function (err) {
reject(new Error(errmsg));
};
keyop.oncomplete = function (e) {
resolve(e.target.result);
};
});
}
//
// JS code
//
return new Promise(function(resolve) {
var key = new keyObject();
var key = new KeyObject();
var rng = new SecureRandom();
var qs = B >> 1;
key.e = parseInt(E, 16);
@ -235,13 +226,15 @@ function RSA() {
for (;;) {
for (;;) {
key.p = new BigInteger(B - qs, 1, rng);
if (key.p.subtract(BigInteger.ONE).gcd(key.ee).compareTo(BigInteger.ONE) === 0 && key.p.isProbablePrime(10))
if (key.p.subtract(BigInteger.ONE).gcd(key.ee).compareTo(BigInteger.ONE) === 0 && key.p.isProbablePrime(10)) {
break;
}
}
for (;;) {
key.q = new BigInteger(qs, 1, rng);
if (key.q.subtract(BigInteger.ONE).gcd(key.ee).compareTo(BigInteger.ONE) === 0 && key.q.isProbablePrime(10))
if (key.q.subtract(BigInteger.ONE).gcd(key.ee).compareTo(BigInteger.ONE) === 0 && key.q.isProbablePrime(10)) {
break;
}
}
if (key.p.compareTo(key.q) <= 0) {
var t = key.p;
@ -270,7 +263,7 @@ function RSA() {
this.verify = verify;
this.sign = sign;
this.generate = generate;
this.keyObject = keyObject;
this.keyObject = KeyObject;
}
module.exports = RSA;

View File

@ -69,11 +69,14 @@ module.exports = {
var i = 0;
while (c < e) {
h = str.charCodeAt(c++).toString(16);
while (h.length < 2) h = "0" + h;
while (h.length < 2) {
h = "0" + h;
}
r.push(" " + h);
i++;
if (i % 32 === 0)
if (i % 32 === 0) {
r.push("\n ");
}
}
return r.join('');
},
@ -84,15 +87,18 @@ module.exports = {
* @return {String} String containing the hexadecimal values
*/
hexstrdump: function (str) {
if (str === null)
if (str === null) {
return "";
}
var r = [];
var e = str.length;
var c = 0;
var h;
while (c < e) {
h = str.charCodeAt(c++).toString(16);
while (h.length < 2) h = "0" + h;
while (h.length < 2) {
h = "0" + h;
}
r.push("" + h);
}
return r.join('');
@ -105,8 +111,9 @@ module.exports = {
*/
hex2bin: function (hex) {
var str = '';
for (var i = 0; i < hex.length; i += 2)
for (var i = 0; i < hex.length; i += 2) {
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
}
return str;
},
@ -122,7 +129,9 @@ module.exports = {
var h;
while (c < e) {
h = str[c++].toString(16);
while (h.length < 2) h = "0" + h;
while (h.length < 2) {
h = "0" + h;
}
r.push("" + h);
}
return r.join('');
@ -189,7 +198,7 @@ module.exports = {
str2Uint8Array: function (str) {
// Uncomment for debugging
if(!(typeof str === 'string') && !String.prototype.isPrototypeOf(str)) {
if(typeof str !== 'string' && !String.prototype.isPrototypeOf(str)) {
throw new Error('str2Uint8Array: Data must be in the form of a string');
}
@ -227,7 +236,7 @@ module.exports = {
* @param {Array<Uint8array>} Array of Uint8Arrays to concatenate
* @return {Uint8array} Concatenated array
*/
concatUint8Array: function (arrays) {
concatUint8Array: function (arrays) {
var totalLength = 0;
arrays.forEach(function (element) {
@ -248,7 +257,7 @@ module.exports = {
});
return result;
},
},
/**
* Deep copy Uint8Array
@ -342,8 +351,9 @@ module.exports = {
getLeftNBits: function (string, bitcount) {
var rest = bitcount % 8;
if (rest === 0)
if (rest === 0) {
return string.substring(0, bitcount / 8);
}
var bytes = (bitcount - rest) / 8 + 1;
var result = string.substring(0, bytes);
return this.shiftRight(result, 8 - rest); // +String.fromCharCode(string.charCodeAt(bytes -1) << (8-rest) & 0xFF);
@ -357,17 +367,18 @@ module.exports = {
* @return {String} Resulting string.
*/
shiftRight: function (value, bitcount) {
var temp = util.str2bin(value);
var temp = this.str2bin(value);
if (bitcount % 8 !== 0) {
for (var i = temp.length - 1; i >= 0; i--) {
temp[i] >>= bitcount % 8;
if (i > 0)
if (i > 0) {
temp[i] |= (temp[i - 1] << (8 - (bitcount % 8))) & 0xFF;
}
}
} else {
return value;
}
return util.bin2str(temp);
return this.bin2str(temp);
},
/**
@ -413,5 +424,40 @@ module.exports = {
return window.msCrypto.subtle;
}
}
},
/**
* Wraps a generic synchronous function in an ES6 Promise.
* @param {Function} fn The function to be wrapped
* @return {Function} The function wrapped in a Promise
*/
promisify: function(fn) {
return function() {
var args = arguments;
return new Promise(function(resolve) {
var result = fn.apply(null, args);
resolve(result);
});
};
},
/**
* Converts an IE11 web crypro api result to a promise.
* This is required since IE11 implements an old version of the
* Web Crypto specification that does not use promises.
* @param {Object} cryptoOp The return value of an IE11 web cryptro api call
* @param {String} errmsg An error message for a specific operation
* @return {Promise} The resulting Promise
*/
promisifyIE11Op: function(cryptoOp, errmsg) {
return new Promise(function(resolve, reject) {
cryptoOp.onerror = function () {
reject(new Error(errmsg));
};
cryptoOp.oncomplete = function (e) {
resolve(e.target.result);
};
});
}
};