JavaScript RSA using bn.js, without asmcrypto.js
This commit is contained in:
parent
9943379cb7
commit
7a3a75a7df
|
@ -53,7 +53,6 @@ export default {
|
|||
let r;
|
||||
let s;
|
||||
let t;
|
||||
// TODO benchmark BN.mont vs BN.red
|
||||
const redp = new BN.red(p);
|
||||
const redq = new BN.red(q);
|
||||
const gred = g.toRed(redp);
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
/** @see module:crypto/public_key/rsa */
|
||||
import rsa from './rsa';
|
||||
import prime from './prime';
|
||||
/** @see module:crypto/public_key/elgamal */
|
||||
import elgamal from './elgamal';
|
||||
/** @see module:crypto/public_key/elliptic */
|
||||
|
@ -18,7 +17,6 @@ import dsa from './dsa';
|
|||
|
||||
export default {
|
||||
rsa: rsa,
|
||||
prime: prime,
|
||||
elgamal: elgamal,
|
||||
elliptic: elliptic,
|
||||
dsa: dsa
|
||||
|
|
|
@ -29,14 +29,12 @@
|
|||
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { RSA_RAW } from 'asmcrypto.js/src/rsa/exports-raw';
|
||||
import prime from './prime';
|
||||
import random from '../random';
|
||||
import config from '../../config';
|
||||
import util from '../../util';
|
||||
|
||||
const two = new BN(2);
|
||||
const zero = new BN(0);
|
||||
|
||||
// TODO use this is ../../encoding/base64.js and ./elliptic/{key,curve}.js
|
||||
function b64toBN(base64url) {
|
||||
|
@ -54,11 +52,11 @@ export default {
|
|||
* @return BN
|
||||
*/
|
||||
sign: function(m, n, e, d) {
|
||||
m = m.toArrayLike(Uint8Array);
|
||||
n = n.toArrayLike(Uint8Array);
|
||||
e = e.toArrayLike(Uint8Array);
|
||||
d = d.toArrayLike(Uint8Array);
|
||||
return RSA_RAW.sign(m, [n, e, d]);
|
||||
if (n.cmp(m) <= 0) {
|
||||
throw new Error('Data too large.');
|
||||
}
|
||||
const nred = new BN.red(n);
|
||||
return m.toRed(nred).redPow(d).toArrayLike(Uint8Array, 'be', n.byteLength());
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -69,10 +67,11 @@ export default {
|
|||
* @return BN
|
||||
*/
|
||||
verify: function(s, n, e) {
|
||||
s = s.toArrayLike(Uint8Array);
|
||||
n = n.toArrayLike(Uint8Array);
|
||||
e = e.toArrayLike(Uint8Array);
|
||||
return RSA_RAW.verify(s, [n, e]);
|
||||
if (n.cmp(s) <= 0) {
|
||||
throw new Error('Data too large.');
|
||||
}
|
||||
const nred = new BN.red(n);
|
||||
return s.toRed(nred).redPow(e).toArrayLike(Uint8Array, 'be', n.byteLength());
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -83,10 +82,11 @@ export default {
|
|||
* @return BN
|
||||
*/
|
||||
encrypt: function(m, n, e) {
|
||||
m = m.toArrayLike(Uint8Array);
|
||||
n = n.toArrayLike(Uint8Array);
|
||||
e = e.toArrayLike(Uint8Array);
|
||||
return RSA_RAW.encrypt(m, [n, e]);
|
||||
if (n.cmp(m) <= 0) {
|
||||
throw new Error('Data too large.');
|
||||
}
|
||||
const nred = new BN.red(n);
|
||||
return m.toRed(nred).redPow(e).toArrayLike(Uint8Array, 'be', n.byteLength());
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -101,37 +101,35 @@ export default {
|
|||
* @return {BN} The decrypted value of the message
|
||||
*/
|
||||
decrypt: function(m, n, e, d, p, q, u) {
|
||||
let blinder = zero;
|
||||
let unblinder = zero;
|
||||
if (n.cmp(m) <= 0) {
|
||||
throw new Error('Data too large.');
|
||||
}
|
||||
const dq = d.mod(q.subn(1)); // d mod (q-1)
|
||||
const dp = d.mod(p.subn(1)); // d mod (p-1)
|
||||
const pred = new BN.red(p);
|
||||
const qred = new BN.red(q);
|
||||
const nred = new BN.red(n);
|
||||
|
||||
config.rsa_blinding = false; // FIXME
|
||||
let blinder;
|
||||
let unblinder;
|
||||
if (config.rsa_blinding) {
|
||||
if (unblinder.bitLength() === n.bitLength()) {
|
||||
unblinder = unblinder.sqr().mod(n);
|
||||
} else {
|
||||
unblinder = random.getRandomBN(two, n);
|
||||
}
|
||||
blinder = unblinder.toRed(nred).redInvm().redPow(e).fromRed();
|
||||
m = m.mul(blinder).mod(n);
|
||||
unblinder = random.getRandomBN(two, n).toRed(nred);
|
||||
blinder = unblinder.redInvm().redPow(e);
|
||||
m = m.toRed(nred).redMul(blinder).fromRed();
|
||||
}
|
||||
|
||||
const dq = d.mod(q.subn(1)).toArrayLike(Uint8Array); // d mod (q-1)
|
||||
const dp = d.mod(p.subn(1)).toArrayLike(Uint8Array); // d mod (p-1)
|
||||
const nn = n.toArrayLike(Uint8Array);
|
||||
m = m.toArrayLike(Uint8Array);
|
||||
e = e.toArrayLike(Uint8Array);
|
||||
d = d.toArrayLike(Uint8Array);
|
||||
q = q.toArrayLike(Uint8Array);
|
||||
p = p.toArrayLike(Uint8Array);
|
||||
u = u.toArrayLike(Uint8Array);
|
||||
let result = new BN(RSA_RAW.decrypt(m, [nn, e, d, q, p, dq, dp, u]).slice(1)); // FIXME remove slice
|
||||
const mp = m.toRed(pred).redPow(dp);
|
||||
const mq = m.toRed(qred).redPow(dq);
|
||||
const t = mq.redSub(mp.fromRed().toRed(qred));
|
||||
const h = u.toRed(qred).redMul(t).fromRed();
|
||||
|
||||
let result = h.mul(p).add(mp).toRed(nred);
|
||||
|
||||
if (config.rsa_blinding) {
|
||||
result = result.mul(unblinder).mod(n);
|
||||
result = result.redMul(unblinder);
|
||||
}
|
||||
|
||||
return result;
|
||||
return result.toArrayLike(Uint8Array, 'be', n.byteLength());
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue
Block a user