Added Native RSA Key Generation

This commit is contained in:
Mahrud Sayrafi 2018-02-24 22:00:20 -05:00
parent 168a6b0bb8
commit 9943379cb7
No known key found for this signature in database
GPG Key ID: C24071B956C3245F
3 changed files with 60 additions and 40 deletions

View File

@ -7,16 +7,18 @@
*/ */
/** @see module:crypto/public_key/rsa */ /** @see module:crypto/public_key/rsa */
import rsa from './rsa.js'; import rsa from './rsa';
import prime from './prime';
/** @see module:crypto/public_key/elgamal */ /** @see module:crypto/public_key/elgamal */
import elgamal from './elgamal.js'; import elgamal from './elgamal';
/** @see module:crypto/public_key/elliptic */ /** @see module:crypto/public_key/elliptic */
import elliptic from './elliptic'; import elliptic from './elliptic';
/** @see module:crypto/public_key/dsa */ /** @see module:crypto/public_key/dsa */
import dsa from './dsa.js'; import dsa from './dsa';
export default { export default {
rsa: rsa, rsa: rsa,
prime: prime,
elgamal: elgamal, elgamal: elgamal,
elliptic: elliptic, elliptic: elliptic,
dsa: dsa dsa: dsa

View File

@ -15,7 +15,7 @@
// License along with this library; if not, write to the Free Software // License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
// Algorithms for probabilistic primality testing // Algorithms for probabilistic prime generation
/** /**
* @requires bn.js * @requires bn.js
@ -26,21 +26,32 @@
import BN from 'bn.js'; import BN from 'bn.js';
import random from '../random'; import random from '../random';
function randomProbablePrime(b) { export default {
let n; randomProbablePrime, isProbablePrime, fermat, millerRabin
const min = new BN(1).shln(b-1); };
do {
n = random.getRandomBN(min, min.shln(1)); function randomProbablePrime(bits, e) {
const min = new BN(1).shln(bits - 1);
let n = random.getRandomBN(min, min.shln(1));
if (n.isEven()) { if (n.isEven()) {
n.iaddn(1); // force odd n.iaddn(1); // force odd
} }
} while (!isProbablePrime(n));
// this.dAddOffset(2, 0); while (!isProbablePrime(n, e)) {
// if (this.bitLength() > b) n.iaddn(2);
// this.subTo(BigInteger.ONE.shiftLeft(b - 1), this); // If reached the maximum, go back to the minimum.
if (n.bitLength() > bits) {
n = n.mod(min.shln(1)).iadd(min);
}
}
return n;
} }
function isProbablePrime(n) { function isProbablePrime(n, e) {
if (e && !n.subn(1).gcd(e).eqn(1)) {
return false;
}
if (!fermat(n)) { if (!fermat(n)) {
return false; return false;
} }
@ -54,9 +65,9 @@ function isProbablePrime(n) {
* Tests whether n is probably prime or not using Fermat's test with b = 2. * Tests whether n is probably prime or not using Fermat's test with b = 2.
* Fails if b^(n-1) mod n === 1. * Fails if b^(n-1) mod n === 1.
*/ */
export function fermat(n, b) { function fermat(n, b) {
b = b || new BN(2); b = b || new BN(2);
return b.toRed(BN.mont(n)).redPow(n.subn(1)).cmpn(1) === 0; return b.toRed(BN.mont(n)).redPow(n.subn(1)).fromRed().cmpn(1) === 0;
} }
@ -93,7 +104,7 @@ export function fermat(n, b) {
* Tests whether n is probably prime or not using the Miller-Rabin test. * Tests whether n is probably prime or not using the Miller-Rabin test.
* See HAC Remark 4.28. * See HAC Remark 4.28.
*/ */
export function millerRabin(n, k, cb) { function millerRabin(n, k, cb) {
var len = n.bitLength(); var len = n.bitLength();
var red = BN.mont(n); var red = BN.mont(n);
var rone = new BN(1).toRed(red); var rone = new BN(1).toRed(red);

View File

@ -29,9 +29,7 @@
import BN from 'bn.js'; import BN from 'bn.js';
import { RSA } from 'asmcrypto.js/src/rsa/exports-keygen';
import { RSA_RAW } from 'asmcrypto.js/src/rsa/exports-raw'; import { RSA_RAW } from 'asmcrypto.js/src/rsa/exports-raw';
import { random as asmcrypto_random } from 'asmcrypto.js/src/random/exports';
import prime from './prime'; import prime from './prime';
import random from '../random'; import random from '../random';
import config from '../../config'; import config from '../../config';
@ -40,6 +38,13 @@ import util from '../../util';
const two = new BN(2); const two = new BN(2);
const zero = new BN(0); const zero = new BN(0);
// TODO use this is ../../encoding/base64.js and ./elliptic/{key,curve}.js
function b64toBN(base64url) {
const base64 = base64url.replace(/\-/g, '+').replace(/_/g, '/');
const hex = util.hexstrdump(atob(base64));
return new BN(hex, 16);
}
export default { export default {
/** Create signature /** Create signature
* @param m message as BN * @param m message as BN
@ -189,25 +194,27 @@ export default {
return key; return key;
} }
// TODO use this is ../../encoding/base64.js and ./elliptic/{key,curve}.js while (true) {
function b64toBN(base64url) { let p = prime.randomProbablePrime(B - (B >> 1), E);
const base64 = base64url.replace(/\-/g, '+').replace(/_/g, '/'); let q = prime.randomProbablePrime(B >> 1, E);
const hex = util.hexstrdump(atob(base64));
return new BN(hex, 16); if (p.cmp(q) < 0) {
const t = p;
p = q;
q = t;
} }
// asmcrypto fallback const phi = p.subn(1).mul(q.subn(1));
await asmcrypto_random.seed(await random.getRandomBytes(1024)); // FIXME how much randomness?
key = await RSA.generateKey(B, E.toArrayLike(Uint8Array));
return { return {
n: new BN(key[0]), n: p.mul(q),
e: new BN(key[1]), e: E,
d: new BN(key[2]), d: E.invm(phi),
q: new BN(key[3]), q: q,
p: new BN(key[4]), p: p,
// dq: new BN(key[5]), // dq: d.mod(q.subn(1)),
// dp: new BN(key[6]), // dp: d.mod(p.subn(1)),
u: new BN(key[7]) u: p.invm(q)
}; };
} }
}
}; };