169 lines
3.4 KiB
JavaScript
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;
|