fcoin/lib/crypto/pk.js
2016-11-21 17:50:05 -08:00

153 lines
2.9 KiB
JavaScript

/*!
* pk.js - public key algorithms for bcoin
* Copyright (c) 2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var assert = require('assert');
var PEM = require('../utils/pem');
var elliptic = require('elliptic');
var util = require('../utils/util');
var backend = require('./backend');
var nodeCrypto = require('crypto');
var dsa, rsa, ecdsa;
/*
* DSA
*/
dsa = {};
dsa.verify = function _verify(alg, msg, sig, key, params) {
var pem = toPEM('dsa', key, params, 'public key');
return verify('dsa', alg, msg, sig, pem);
};
dsa.sign = function _sign(alg, msg, key, params) {
var pem = toPEM('dsa', key, params, 'private key');
return sign('dsa', alg, msg, pem);
};
dsa.verifyAsync = util.promisify(dsa.verify);
dsa.signAsync = util.promisify(dsa.sign);
/*
* RSA
*/
rsa = {};
rsa.verify = function _verify(alg, msg, sig, key) {
var pem = toPEM('rsa', key, null, 'public key');
return verify('rsa', alg, msg, sig, pem);
};
rsa.sign = function _sign(alg, msg, key) {
var pem = toPEM('rsa', key, null, 'private key');
return sign('rsa', alg, msg, pem);
};
rsa.verifyAsync = util.promisify(rsa.verify);
rsa.signAsync = util.promisify(rsa.sign);
/*
* ECDSA
*/
ecdsa = {};
ecdsa.verify = function verify(curve, msg, alg, key, sig) {
var ec, hash;
assert(curve, 'No curve selected.');
ec = elliptic.ec(curve);
hash = backend.hash(alg, msg);
return ec.verify(hash, sig, key);
};
ecdsa.sign = function sign(curve, msg, alg, 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));
};
ecdsa.verifyAsync = util.promisify(ecdsa.verify);
ecdsa.signAsync = util.promisify(ecdsa.sign);
/*
* 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 'dsa':
tag = 'DSA';
break;
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.dsa = dsa;
exports.rsa = rsa;
exports.ecdsa = ecdsa;