js-encrypt
Version:
A Javascript library to perform OpenSSL RSA Encryption, Decryption, and Key Generation.
166 lines (159 loc) • 5.34 kB
JavaScript
var _rng = require("./rng");
var _jsbn = require("./jsbn");
var _rsa = require("./rsa");
// Generate a new random private key B bits long, using public expt E
_rsa.RSAKey.prototype.generateAsync = function (B, E, callback) {
//var rng = new SeededRandom();
var rng = new _rng.SecureRandom();
var qs = B >> 1;
this.e = parseInt(E, 16);
var ee = new _jsbn.BigInteger(E, 16);
var rsa = this;
// These functions have non-descript names because they were originally for(;;) loops.
// I don't know about cryptography to give them better names than loop1-4.
var loop1 = function loop1() {
var loop4 = function loop4() {
if (rsa.p.compareTo(rsa.q) <= 0) {
var t = rsa.p;
rsa.p = rsa.q;
rsa.q = t;
}
var p1 = rsa.p.subtract(_jsbn.BigInteger.ONE);
var q1 = rsa.q.subtract(_jsbn.BigInteger.ONE);
var phi = p1.multiply(q1);
if (phi.gcd(ee).compareTo(_jsbn.BigInteger.ONE) == 0) {
rsa.n = rsa.p.multiply(rsa.q);
rsa.d = ee.modInverse(phi);
rsa.dmp1 = rsa.d.mod(p1);
rsa.dmq1 = rsa.d.mod(q1);
rsa.coeff = rsa.q.modInverse(rsa.p);
setTimeout(function () {
callback();
}, 0); // escape
} else {
setTimeout(loop1, 0);
}
};
var loop3 = function loop3() {
rsa.q = nbi();
rsa.q.fromNumberAsync(qs, 1, rng, function () {
rsa.q.subtract(_jsbn.BigInteger.ONE).gcda(ee, function (r) {
if (r.compareTo(_jsbn.BigInteger.ONE) == 0 && rsa.q.isProbablePrime(10)) {
setTimeout(loop4, 0);
} else {
setTimeout(loop3, 0);
}
});
});
};
var loop2 = function loop2() {
rsa.p = nbi();
rsa.p.fromNumberAsync(B - qs, 1, rng, function () {
rsa.p.subtract(_jsbn.BigInteger.ONE).gcda(ee, function (r) {
if (r.compareTo(_jsbn.BigInteger.ONE) == 0 && rsa.p.isProbablePrime(10)) {
setTimeout(loop3, 0);
} else {
setTimeout(loop2, 0);
}
});
});
};
setTimeout(loop2, 0);
};
setTimeout(loop1, 0);
};
// Public API method
// Copyright (c) 2011 Kevin M Burns Jr.
// All Rights Reserved.
// See "LICENSE" for details.
//
// Extension to jsbn which adds facilities for asynchronous RSA key generation
// Primarily created to avoid execution timeout on mobile devices
//
// http://www-cs-students.stanford.edu/~tjw/jsbn/
//
// ---
var bnGCDAsync = function bnGCDAsync(a, callback) {
var x = this.s < 0 ? this.negate() : this.clone();
var y = a.s < 0 ? a.negate() : a.clone();
if (x.compareTo(y) < 0) {
var t = x;
x = y;
y = t;
}
var i = x.getLowestSetBit(),
g = y.getLowestSetBit();
if (g < 0) {
callback(x);
return;
}
if (i < g) g = i;
if (g > 0) {
x.rShiftTo(g, x);
y.rShiftTo(g, y);
}
// Workhorse of the algorithm, gets called 200 - 800 times per 512 bit keygen.
var gcda1 = function gcda1() {
if ((i = x.getLowestSetBit()) > 0) {
x.rShiftTo(i, x);
}
if ((i = y.getLowestSetBit()) > 0) {
y.rShiftTo(i, y);
}
if (x.compareTo(y) >= 0) {
x.subTo(y, x);
x.rShiftTo(1, x);
} else {
y.subTo(x, y);
y.rShiftTo(1, y);
}
if (!(x.signum() > 0)) {
if (g > 0) y.lShiftTo(g, y);
setTimeout(function () {
callback(y);
}, 0); // escape
} else {
setTimeout(gcda1, 0);
}
};
setTimeout(gcda1, 10);
};
_jsbn.BigInteger.prototype.gcda = bnGCDAsync;
// (protected) alternate constructor
var bnpFromNumberAsync = function bnpFromNumberAsync(a, b, c, callback) {
if ("number" == typeof b) {
if (a < 2) {
this.fromInt(1);
} else {
this.fromNumber(a, c);
if (!this.testBit(a - 1)) {
this.bitwiseTo(_jsbn.BigInteger.ONE.shiftLeft(a - 1), op_or, this);
}
if (this.isEven()) {
this.dAddOffset(1, 0);
}
var bnp = this;
var bnpfn1 = function bnpfn1() {
bnp.dAddOffset(2, 0);
if (bnp.bitLength() > a) bnp.subTo(_jsbn.BigInteger.ONE.shiftLeft(a - 1), bnp);
if (bnp.isProbablePrime(b)) {
setTimeout(function () {
callback();
}, 0); // escape
} else {
setTimeout(bnpfn1, 0);
}
};
setTimeout(bnpfn1, 0);
}
} else {
var x = [],
t = a & 7;
x.length = (a >> 3) + 1;
b.nextBytes(x);
if (t > 0) x[0] &= (1 << t) - 1;else x[0] = 0;
this.fromString(x, 256);
}
};
_jsbn.BigInteger.prototype.fromNumberAsync = bnpFromNumberAsync;
;