fcoin/lib/crypto/pk.js
2017-02-03 22:47:26 -08:00

169 lines
3.4 KiB
JavaScript

/*!
* 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 new Buffer(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;