From 9c00a0f81e4b288d02e850632fed7cfa25e0dce0 Mon Sep 17 00:00:00 2001 From: Mark Vayngrib Date: Sun, 11 Sep 2016 16:45:12 -0400 Subject: [PATCH 1/3] separate out curves --- lib/curves.js | 37 +++++++++++++++++++++++++++++++++++++ lib/key-encoder.js | 13 ++----------- 2 files changed, 39 insertions(+), 11 deletions(-) create mode 100644 lib/curves.js diff --git a/lib/curves.js b/lib/curves.js new file mode 100644 index 0000000..fea40ed --- /dev/null +++ b/lib/curves.js @@ -0,0 +1,37 @@ + +var EC = require('elliptic').ec + +var alt = { + p192: 'prime192v1', + p224: 'secp224r1', + p256: 'prime256v1', + p384: 'secp384r1', + p521: 'secp521r1' +} + +var parameters = { + secp256k1: [1, 3, 132, 0, 10], + p192: [1, 2, 840, 10045, 3, 1, 1], + p224: [1, 3, 132, 0, 33], + p256: [1, 2, 840, 10045, 3, 1, 7], + p384: [1, 3, 132, 0, 34], + p521: [1, 3, 132, 0, 35] +} + +function toCurves (parameters) { + var curves = {} + for (var curve in parameters) { + curves[curve] = { + curveParameters: parameters[curve], + privatePEMOptions: {label: 'EC PRIVATE KEY'}, + publicPEMOptions: {label: 'PUBLIC KEY'}, + curve: new EC(curve) + } + + if (alt[curve]) curves[alt[curve]] = curves[curve] + } + + return curves +} + +module.exports = toCurves(parameters) diff --git a/lib/key-encoder.js b/lib/key-encoder.js index 286e522..9e2834e 100644 --- a/lib/key-encoder.js +++ b/lib/key-encoder.js @@ -2,7 +2,7 @@ var asn1 = require('asn1.js'), BN = require('bn.js'), - EC = require('elliptic').ec + curves = require('./curves') var ECPrivateKeyASN = asn1.define('ECPrivateKey', function() { this.seq().obj( @@ -23,15 +23,6 @@ var SubjectPublicKeyInfoASN = asn1.define('SubjectPublicKeyInfo', function() { ) }) -var curves = { - secp256k1: { - curveParameters: [1, 3, 132, 0, 10], - privatePEMOptions: {label: 'EC PRIVATE KEY'}, - publicPEMOptions: {label: 'PUBLIC KEY'}, - curve: new EC('secp256k1') - } -} - function assert(val, msg) { if (!val) { throw new Error(msg || 'Assertion failed') @@ -160,4 +151,4 @@ KeyEncoder.prototype.encodePublic = function(publicKey, originalFormat, destinat } } -module.exports = KeyEncoder \ No newline at end of file +module.exports = KeyEncoder From 9811b1d85ded6f6d8eb6b48389d80ed17df550ff Mon Sep 17 00:00:00 2001 From: Mark Vayngrib Date: Thu, 15 Sep 2016 15:14:33 -0400 Subject: [PATCH 2/3] lazy load curves --- lib/aliases.js | 8 ++++++++ lib/curves.js | 44 ++++++++++++++++++++++++++------------------ 2 files changed, 34 insertions(+), 18 deletions(-) create mode 100644 lib/aliases.js diff --git a/lib/aliases.js b/lib/aliases.js new file mode 100644 index 0000000..3b21ad7 --- /dev/null +++ b/lib/aliases.js @@ -0,0 +1,8 @@ +module.exports = { + p192: 'prime192v1', + p224: 'secp224r1', + p256: 'prime256v1', + p384: 'secp384r1', + p521: 'secp521r1' +} + diff --git a/lib/curves.js b/lib/curves.js index fea40ed..5ccb872 100644 --- a/lib/curves.js +++ b/lib/curves.js @@ -1,14 +1,6 @@ var EC = require('elliptic').ec - -var alt = { - p192: 'prime192v1', - p224: 'secp224r1', - p256: 'prime256v1', - p384: 'secp384r1', - p521: 'secp521r1' -} - +var aliases = require('./aliases') var parameters = { secp256k1: [1, 3, 132, 0, 10], p192: [1, 2, 840, 10045, 3, 1, 1], @@ -20,16 +12,32 @@ var parameters = { function toCurves (parameters) { var curves = {} - for (var curve in parameters) { - curves[curve] = { - curveParameters: parameters[curve], - privatePEMOptions: {label: 'EC PRIVATE KEY'}, - publicPEMOptions: {label: 'PUBLIC KEY'}, - curve: new EC(curve) - } + Object.keys(parameters).forEach(function (curve) { + var cParams + // be lazy + Object.defineProperty(curves, curve, { + get: function () { + if (!cParams) { + cParams = { + curveParameters: parameters[curve], + privatePEMOptions: {label: 'EC PRIVATE KEY'}, + publicPEMOptions: {label: 'PUBLIC KEY'}, + curve: new EC(curve) + } + } + + return cParams + } + }) - if (alt[curve]) curves[alt[curve]] = curves[curve] - } + if (aliases[curve]) { + Object.defineProperty(curves, aliases[curve], { + get: function () { + return curves[curve] + } + }) + } + }) return curves } From a75b1d7f40d44c6e80051d5c869293acb3db4f47 Mon Sep 17 00:00:00 2001 From: Ryan Shea Date: Fri, 16 Sep 2016 10:02:45 -0400 Subject: [PATCH 3/3] incorporate in and expand on mvayngrib's tests --- lib/key-encoder.js | 5 +++- test.js | 63 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/lib/key-encoder.js b/lib/key-encoder.js index 9e2834e..2b4aa38 100644 --- a/lib/key-encoder.js +++ b/lib/key-encoder.js @@ -2,7 +2,8 @@ var asn1 = require('asn1.js'), BN = require('bn.js'), - curves = require('./curves') + curves = require('./curves'), + aliases = require('./aliases') var ECPrivateKeyASN = asn1.define('ECPrivateKey', function() { this.seq().obj( @@ -38,6 +39,8 @@ function KeyEncoder(options) { this.algorithmID = [1, 2, 840, 10045, 2, 1] } +KeyEncoder.aliases = aliases +KeyEncoder.curves = curves KeyEncoder.ECPrivateKeyASN = ECPrivateKeyASN KeyEncoder.SubjectPublicKeyInfoASN = SubjectPublicKeyInfoASN diff --git a/test.js b/test.js index 492df4c..3d32c2c 100644 --- a/test.js +++ b/test.js @@ -2,7 +2,8 @@ var test = require('tape'), KeyEncoder = require('./index'), ECPrivateKeyASN = KeyEncoder.ECPrivateKeyASN, SubjectPublicKeyInfoASN = KeyEncoder.SubjectPublicKeyInfoASN, - BN = require('bn.js') + BN = require('bn.js'), + crypto = require('crypto') var keys = { rawPrivate: '844055cca13efd78ce79a4c3a4c5aba5db0ebeb7ae9d56906c03d333c5668d5b', @@ -128,3 +129,63 @@ test('encodePEMPublicKey', function(t) { var publicKeyDER = keyEncoder.encodePublic(keys.pemPublic, 'pem', 'der') t.equal(publicKeyDER, keys.derPublic, 'encoded DER public key should match the OpenSSL reference') }) + +var aliases = KeyEncoder.aliases +var curves = KeyEncoder.curves + +test('elliptic sign => native verify compact', function (t) { + var testData = 'some data', + hashingAlgorithm = 'sha256', + testDataHash = crypto.createHash(hashingAlgorithm).update(testData).digest() + + for (var curveName in aliases) { + var curve = curves[curveName].curve, + keyEncoder = new KeyEncoder(curveName) + t.ok(keyEncoder, 'curve ' + curveName + ': created a key encoder') + + var keypair = curve.genKeyPair(), + publixKeyHex = keypair.getPublic('hex'), + publicKeyPEM = keyEncoder.encodePublic(publixKeyHex, 'raw', 'pem') + + var signatureOfTestData = keypair.sign(testDataHash).toDER('hex') + t.ok(signatureOfTestData, 'curve ' + curveName + ': signed test data') + + var verified = crypto + .createVerify(hashingAlgorithm) + .update(testData) + .verify(publicKeyPEM, signatureOfTestData, 'hex') + t.ok(verified, 'curve ' + curveName + ': verified signature') + } + + t.end() +}) + +test('native sign => elliptic verify compact', function (t) { + var testData = 'some data', + hashingAlgorithm = 'sha256', + testDataHash = crypto.createHash(hashingAlgorithm).update(testData).digest() + + for (var curveName in aliases) { + var curve = curves[curveName].curve, + keyEncoder = new KeyEncoder(curveName) + t.ok(keyEncoder, 'curve ' + curveName + ': created a key encoder') + + var ecdh = crypto.createECDH(aliases[curveName]) + ecdh.generateKeys() + var privateKey = ecdh.getPrivateKey(), + privateKeyPEM = keyEncoder.encodePrivate(privateKey, 'raw', 'pem') + + var signatureOfTestData = crypto + .createSign(hashingAlgorithm) + .update(testData) + .sign(privateKeyPEM, 'hex') + t.ok(signatureOfTestData, 'curve ' + curveName + ': signed test data') + + var verified = curve + .keyFromPrivate(privateKey) + .verify(testDataHash, signatureOfTestData) + t.ok(verified, 'curve ' + curveName + ': verified signature') + } + + t.end() +})