diff --git a/lib/bcoin-browser.js b/lib/bcoin-browser.js index 75c29458..775c75c7 100644 --- a/lib/bcoin-browser.js +++ b/lib/bcoin-browser.js @@ -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 diff --git a/lib/bcoin.js b/lib/bcoin.js index 52c6eae8..b186f149 100644 --- a/lib/bcoin.js +++ b/lib/bcoin.js @@ -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 diff --git a/lib/bip70/pk.js b/lib/bip70/pk.js index e49588da..96dc4b7b 100644 --- a/lib/bip70/pk.js +++ b/lib/bip70/pk.js @@ -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.'); } diff --git a/lib/crypto/ecdsa.js b/lib/crypto/ecdsa.js new file mode 100644 index 00000000..ebc67027 --- /dev/null +++ b/lib/crypto/ecdsa.js @@ -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()); +}; diff --git a/lib/crypto/index.js b/lib/crypto/index.js index 7cef358c..3818d165 100644 --- a/lib/crypto/index.js +++ b/lib/crypto/index.js @@ -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 diff --git a/lib/crypto/pk.js b/lib/crypto/pk.js deleted file mode 100644 index 2bb20eb8..00000000 --- a/lib/crypto/pk.js +++ /dev/null @@ -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; diff --git a/lib/crypto/pk-browser.js b/lib/crypto/rsa-browser.js similarity index 69% rename from lib/crypto/pk-browser.js rename to lib/crypto/rsa-browser.js index 32ea206d..855b213f 100644 --- a/lib/crypto/pk-browser.js +++ b/lib/crypto/rsa-browser.js @@ -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; diff --git a/lib/crypto/rsa.js b/lib/crypto/rsa.js new file mode 100644 index 00000000..e237270d --- /dev/null +++ b/lib/crypto/rsa.js @@ -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(); +} diff --git a/package.json b/package.json index b641ef63..1024c5a7 100644 --- a/package.json +++ b/package.json @@ -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",