crypto: refactor pk.js.

This commit is contained in:
Christopher Jeffrey 2017-06-27 02:34:17 -07:00
parent f6fb3ba3b5
commit 5d6e089c92
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
9 changed files with 173 additions and 286 deletions

View File

@ -35,7 +35,6 @@
*
* @property {Object} crypto
* @property {Object} ec
* @property {Object} pk
* @property {Object} schnorr
*
* @property {Object} db
@ -169,7 +168,6 @@ bcoin.coinview = require('./coins/coinview');
bcoin.crypto = require('./crypto');
bcoin.bn = require('./crypto/bn');
bcoin.ec = require('./crypto/ec');
bcoin.pk = require('./crypto/pk');
bcoin.schnorr = require('./crypto/schnorr');
// DB

View File

@ -35,7 +35,6 @@
*
* @property {Object} crypto
* @property {Object} ec
* @property {Object} pk
* @property {Object} schnorr
*
* @property {Object} db
@ -189,7 +188,6 @@ bcoin.define('coinview', './coins/coinview');
bcoin.define('crypto', './crypto');
bcoin.define('bn', './crypto/bn');
bcoin.define('ec', './crypto/ec');
bcoin.define('pk', './crypto/pk');
bcoin.define('schnorr', './crypto/schnorr');
// DB

View File

@ -10,28 +10,8 @@
* @module bip70/pk
*/
var pk = require('../crypto/pk');
/**
* Verify signature with public key.
* @private
* @param {String} hash - Hash algorithm.
* @param {Buffer} msg
* @param {Buffer} sig
* @param {Object} key
* @returns {Boolean}
*/
exports._verify = function verify(hash, msg, sig, key) {
switch (key.alg) {
case 'rsa':
return pk.rsa.verify(hash, msg, sig, key.data);
case 'ecdsa':
return pk.ecdsa.verify(key.curve, hash, msg, sig, key.data);
default:
throw new Error('Unsupported algorithm.');
}
};
var rsa = require('../crypto/rsa');
var ecdsa = require('../crypto/ecdsa');
/**
* Verify signature with public key.
@ -43,10 +23,13 @@ exports._verify = function verify(hash, msg, sig, key) {
*/
exports.verify = function verify(hash, msg, sig, key) {
try {
return exports._verify(hash, msg, sig, key);
} catch (e) {
return false;
switch (key.alg) {
case 'rsa':
return rsa.verify(hash, msg, sig, key.data);
case 'ecdsa':
return ecdsa.verify(key.curve, hash, msg, sig, key.data);
default:
throw new Error('Unsupported algorithm.');
}
};
@ -61,9 +44,9 @@ exports.verify = function verify(hash, msg, sig, key) {
exports.sign = function sign(hash, msg, key) {
switch (key.alg) {
case 'rsa':
return pk.rsa.sign(hash, msg, key.data);
return rsa.sign(hash, msg, key.data);
case 'ecdsa':
return pk.ecdsa.sign(key.curve, hash, msg, key.data);
return ecdsa.sign(key.curve, hash, msg, key.data);
default:
throw new Error('Unsupported algorithm.');
}

70
lib/crypto/ecdsa.js Normal file
View File

@ -0,0 +1,70 @@
/*!
* ecdsa.js - ecdsa for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto/ecdsa
*/
var assert = require('assert');
var elliptic = require('elliptic');
var backend = require('./backend');
/**
* Verify ECDSA signature.
* @param {String} curve - Curve name.
* @param {String} alg - Hash algorithm.
* @param {Buffer} msg - Signed message.
* @param {Buffer} sig - Signature.
* @param {Buffer} key - ASN1 serialized ECDSA key.
* @returns {Boolean}
*/
exports.verify = function verify(curve, alg, msg, sig, key) {
var ec, hash;
assert(typeof curve === 'string', 'No curve selected.');
assert(typeof alg === 'string', 'No algorithm selected.');
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(sig));
assert(Buffer.isBuffer(key));
ec = elliptic.ec(curve);
hash = backend.hash(alg, msg);
try {
return ec.verify(hash, sig, key);
} catch (e) {
return false;
}
};
/**
* Sign message with ECDSA key.
* @memberof module:crypto/pk.ecdsa
* @param {String} curve - Curve name.
* @param {String} alg - Hash algorithm.
* @param {Buffer} msg - Signed message.
* @param {Buffer} key - ASN1 serialized ECDSA key.
* @returns {Buffer} Signature (DER)
*/
exports.sign = function sign(curve, alg, msg, key) {
var ec, hash, sig;
assert(typeof curve === 'string', 'No curve selected.');
assert(typeof alg === 'string', 'No algorithm selected.');
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(key));
ec = elliptic.ec(curve);
hash = backend.hash(alg, msg);
sig = ec.sign(hash, key, { canonical: true });
return Buffer.from(sig.toDER());
};

View File

@ -306,26 +306,19 @@ exports.AEAD = exports.chachapoly.AEAD;
exports.BN = require('./bn');
/**
* pk module
* @see module:crypto/pk
*/
exports.pk = require('./pk');
/**
* RSA
* @see module:crypto/pk.rsa
* @see module:crypto/rsa
*/
exports.rsa = exports.pk.rsa;
exports.rsa = require('./rsa');
/**
* ECDSA
* @see module:crypto/pk.ecdsa
* @see module:crypto/ecdsa
*/
exports.ecdsa = exports.pk.ecdsa;
exports.ecdsa = require('./ecdsa');
/**
* ec module

View File

@ -1,168 +0,0 @@
/*!
* pk.js - public key algorithms for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto/pk
*/
var assert = require('assert');
var nodeCrypto = require('crypto');
var elliptic = require('elliptic');
var PEM = require('../utils/pem');
var backend = require('./backend');
var rsa, ecdsa;
/**
* RSA
* @namespace module:crypto/pk.rsa
*/
rsa = {};
/**
* Verify RSA signature.
* @memberof module:crypto/pk.rsa
* @param {String} alg - Hash algorithm.
* @param {Buffer} msg - Signed message.
* @param {Buffer} sig - Signature.
* @param {Buffer} key - ASN1 serialized RSA key.
* @returns {Boolean}
*/
rsa.verify = function _verify(alg, msg, sig, key) {
var pem = toPEM('rsa', key, null, 'public key');
return verify('rsa', alg, msg, sig, pem);
};
/**
* Sign message with RSA key.
* @memberof module:crypto/pk.rsa
* @param {String} alg - Hash algorithm.
* @param {Buffer} msg - Signed message.
* @param {Buffer} key - ASN1 serialized RSA key.
* @returns {Buffer} Signature (DER)
*/
rsa.sign = function _sign(alg, msg, key) {
var pem = toPEM('rsa', key, null, 'private key');
return sign('rsa', alg, msg, pem);
};
/**
* ECDSA
* @namespace module:crypto/pk.ecdsa
*/
ecdsa = {};
/**
* Verify ECDSA signature.
* @memberof module:crypto/pk.ecdsa
* @param {String} curve - Curve name.
* @param {String} alg - Hash algorithm.
* @param {Buffer} msg - Signed message.
* @param {Buffer} sig - Signature.
* @param {Buffer} key - ASN1 serialized ECDSA key.
* @returns {Boolean}
*/
ecdsa.verify = function verify(curve, alg, msg, sig, key) {
var ec, hash;
assert(curve, 'No curve selected.');
ec = elliptic.ec(curve);
hash = backend.hash(alg, msg);
return ec.verify(hash, sig, key);
};
/**
* Sign message with ECDSA key.
* @memberof module:crypto/pk.ecdsa
* @param {String} curve - Curve name.
* @param {String} alg - Hash algorithm.
* @param {Buffer} msg - Signed message.
* @param {Buffer} key - ASN1 serialized ECDSA key.
* @returns {Buffer} Signature (DER)
*/
ecdsa.sign = function sign(curve, alg, msg, key) {
var ec, hash;
assert(curve, 'No curve selected.');
ec = elliptic.ec(curve);
hash = backend.hash(alg, msg);
return Buffer.from(ec.sign(hash, key));
};
/*
* Helpers
*/
function verify(alg, hash, msg, sig, key) {
var algo = normalizeAlg(alg, hash);
var verifier = nodeCrypto.createVerify(algo);
verifier.update(msg);
return verifier.verify(key, sig);
}
function sign(alg, hash, msg, key) {
var algo = normalizeAlg(alg, hash);
var sig = nodeCrypto.createSign(algo);
sig.update(msg);
return sig.sign(key);
}
function toPEM(alg, key, params, type) {
var tag, pem;
switch (alg) {
case 'rsa':
tag = 'RSA';
break;
case 'ecdsa':
tag = 'EC';
break;
default:
throw new Error('Unsupported algorithm.');
}
pem = PEM.encode(key, tag, type);
// Key parameters, usually present
// if selecting an EC curve.
if (params)
pem += PEM.encode(params, tag, 'parameters');
return pem;
}
function normalizeAlg(alg, hash) {
var name = alg.toUpperCase() + '-' + hash.toUpperCase();
switch (name) {
case 'ECDSA-SHA1':
name = 'ecdsa-with-SHA1';
break;
case 'ECDSA-SHA256':
name = 'ecdsa-with-SHA256';
break;
}
return name;
}
/*
* Expose
*/
exports.rsa = rsa;
exports.ecdsa = ecdsa;

View File

@ -1,35 +1,26 @@
/*!
* pk-browser.js - public key algorithms for bcoin
* rsa-browser.js - rsa for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto/pk-browser
* @ignore
*/
var assert = require('assert');
var elliptic = require('elliptic');
var BN = require('./bn');
var ASN1 = require('../utils/asn1');
var backend = require('./backend');
var rsa, ecdsa;
/**
* RSA
* @namespace module:crypto/pk-browser.rsa
* @exports crypto/rsa
* @ignore
*/
rsa = {};
var rsa = exports;
/**
* PKCS signature prefixes.
* @type {Object}
* @memberof module:crypto/pk-browser.rsa
*/
rsa.prefixes = {
@ -44,7 +35,6 @@ rsa.prefixes = {
/**
* Verify RSA signature.
* @memberof module:crypto/pk-browser.rsa
* @param {String} alg - Hash algorithm.
* @param {Buffer} msg - Signed message.
* @param {Buffer} sig - Signature.
@ -57,6 +47,11 @@ rsa.verify = function verify(alg, msg, sig, key) {
var hash, len, pub;
var N, e, k, m, em, ok, i;
assert(typeof alg === 'string', 'No algorithm selected.');
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(sig));
assert(Buffer.isBuffer(key));
if (!prefix)
throw new Error('Unknown PKCS prefix.');
@ -88,7 +83,6 @@ rsa.verify = function verify(alg, msg, sig, key) {
/**
* Sign message with RSA key.
* @memberof module:crypto/pk-browser.rsa
* @param {String} alg - Hash algorithm.
* @param {Buffer} msg - Signed message.
* @param {Buffer} key - ASN1 serialized RSA key.
@ -100,6 +94,10 @@ rsa.sign = function sign(alg, msg, key) {
var hash, len, priv;
var N, D, k, i, em;
assert(typeof alg === 'string', 'No algorithm selected.');
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(key));
if (!prefix)
throw new Error('Unknown PKCS prefix.');
@ -129,7 +127,6 @@ rsa.sign = function sign(alg, msg, key) {
/**
* Decrypt with modulus and exponent.
* @memberof module:crypto/pk-browser.rsa
* @param {BN} N
* @param {BN} D
* @param {Buffer} m
@ -151,7 +148,6 @@ rsa.decrypt = function decrypt(N, D, m) {
/**
* Encrypt with modulus and exponent.
* @memberof module:crypto/pk-browser.rsa
* @param {BN} N
* @param {BN} e
* @param {Buffer} m
@ -166,57 +162,6 @@ rsa.encrypt = function encrypt(N, e, m) {
.toArrayLike(Buffer, 'be');
};
/**
* ECDSA
* @namespace module:crypto/pk.ecdsa
* @ignore
*/
ecdsa = {};
/**
* Verify ECDSA signature.
* @memberof module:crypto/pk-browser.ecdsa
* @param {String} curve - Curve name.
* @param {String} alg - Hash algorithm.
* @param {Buffer} msg - Signed message.
* @param {Buffer} sig - Signature.
* @param {Buffer} key - ASN1 serialized ECDSA key.
* @returns {Boolean}
*/
ecdsa.verify = function verify(curve, alg, msg, sig, key) {
var ec, hash;
assert(curve, 'No curve selected.');
ec = elliptic.ec(curve);
hash = backend.hash(alg, msg);
return ec.verify(hash, sig, key);
};
/**
* Sign message with ECDSA key.
* @memberof module:crypto/pk-browser.ecdsa
* @param {String} curve - Curve name.
* @param {String} alg - Hash algorithm.
* @param {Buffer} msg - Signed message.
* @param {Buffer} key - ASN1 serialized ECDSA key.
* @returns {Buffer} Signature (DER)
*/
ecdsa.sign = function sign(curve, alg, msg, key) {
var ec, hash;
assert(curve, 'No curve selected.');
ec = elliptic.ec(curve);
hash = backend.hash(alg, msg);
return Buffer.from(ec.sign(hash, key));
};
/*
* Helpers
*/
@ -243,10 +188,3 @@ function ceq(a, b) {
r &= r >>> 1;
return r === 1;
}
/*
* Expose
*/
exports.rsa = rsa;
exports.ecdsa = ecdsa;

75
lib/crypto/rsa.js Normal file
View File

@ -0,0 +1,75 @@
/*!
* rsa.js - RSA for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* @module crypto/rsa
*/
var assert = require('assert');
var crypto = require('crypto');
var PEM = require('../utils/pem');
/**
* Verify RSA signature.
* @param {String} alg - Hash algorithm.
* @param {Buffer} msg - Signed message.
* @param {Buffer} sig - Signature.
* @param {Buffer} key - ASN1 serialized RSA key.
* @returns {Boolean}
*/
exports.verify = function verify(alg, msg, sig, key) {
var pem, name, ctx;
assert(typeof alg === 'string', 'No algorithm selected.');
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(sig));
assert(Buffer.isBuffer(key));
pem = PEM.encode(key, 'rsa', 'public key');
name = normalizeAlg('rsa', alg);
ctx = crypto.createVerify(name);
try {
ctx.update(msg);
return ctx.verify(key, sig);
} catch (e) {
return false;
}
};
/**
* Sign message with RSA key.
* @param {String} alg - Hash algorithm.
* @param {Buffer} msg - Signed message.
* @param {Buffer} key - ASN1 serialized RSA key.
* @returns {Buffer} Signature (DER)
*/
exports.sign = function sign(alg, msg, key) {
var pem, name, ctx;
assert(typeof alg === 'string', 'No algorithm selected.');
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(key));
pem = PEM.encode(key, 'rsa', 'private key');
name = normalizeAlg('rsa', alg);
ctx = crypto.createSign(name);
ctx.update(msg);
return ctx.sign(key);
};
/*
* Helpers
*/
function normalizeAlg(alg, hash) {
return alg.toUpperCase() + '-' + hash.toUpperCase();
}

View File

@ -80,7 +80,7 @@
"./lib/blockchain/layout.js": "./lib/blockchain/layout-browser.js",
"./lib/crypto/backend.js": "./lib/crypto/backend-browser.js",
"./lib/crypto/ec.js": "./lib/crypto/ec-elliptic.js",
"./lib/crypto/pk.js": "./lib/crypto/pk-browser.js",
"./lib/crypto/rsa.js": "./lib/crypto/rsa-browser.js",
"./lib/db/backends.js": "./lib/db/backends-browser.js",
"./lib/hd/wordlist": "./lib/hd/wordlist-browser.js",
"./lib/http/base": "./browser/empty.js",