browserify-sign
Advanced tools
Comparing version 2.3.0 to 2.4.0
10
algos.js
@@ -21,1 +21,11 @@ exports['RSA-SHA224'] = exports.sha224WithRSAEncryption = { | ||
}; | ||
exports['RSA-SHA1'] = { | ||
sign: 'rsa', | ||
hash: 'sha1', | ||
id: new Buffer('3021300906052b0e03021a05000414', 'hex') | ||
} | ||
exports['ecdsa-with-SHA1'] = { | ||
sign: 'ecdsa', | ||
hash: 'sha1', | ||
id: new Buffer(/*'3021300906052b0e03021a05000414'*/'', 'hex') | ||
} |
71
asn1.js
@@ -32,2 +32,23 @@ // from https://github.com/indutny/self-signed/blob/gh-pages/lib/asn1.js | ||
exports.PublicKey = PublicKey; | ||
var ECPublicKey = asn1.define('ECPublicKey', function() { | ||
this.seq().obj( | ||
this.key('algorithm').seq().obj( | ||
this.key('id').objid(), | ||
this.key('curve').objid() | ||
), | ||
this.key('subjectPrivateKey').bitstr() | ||
); | ||
}); | ||
exports.ECPublicKey = ECPublicKey; | ||
var ECPrivateWrap = asn1.define('ECPrivateWrap', function() { | ||
this.seq().obj( | ||
this.key('version').int(), | ||
this.key('algorithm').seq().obj( | ||
this.key('id').objid(), | ||
this.key('curve').objid() | ||
), | ||
this.key('subjectPrivateKey').octstr() | ||
); | ||
}); | ||
exports.ECPrivateWrap = ECPrivateWrap; | ||
var PrivateKeyInfo = asn1.define('PrivateKeyInfo', function() { | ||
@@ -63,37 +84,29 @@ this.seq().obj( | ||
exports.EncryptedPrivateKey = EncryptedPrivateKeyInfo; | ||
var GeneralName = asn1.define('GeneralName', function() { | ||
var ECPrivateKey = asn1.define('ECPrivateKey', function() { | ||
this.seq().obj( | ||
this.key('version').int(), | ||
this.key('privateKey').octstr(), | ||
this.key('parameters').optional().explicit(0).use(ECParameters), | ||
this.key('publicKey').optional().explicit(1).bitstr() | ||
); | ||
}); | ||
exports.ECPrivateKey = ECPrivateKey; | ||
var ECParameters = asn1.define('ECParameters', function() { | ||
this.choice({ | ||
dNSName: this.implicit(2).ia5str() | ||
namedCurve: this.objid() | ||
}); | ||
}); | ||
exports.GeneralName = GeneralName; | ||
var GeneralNames = asn1.define('GeneralNames', function() { | ||
this.seqof(GeneralName); | ||
}); | ||
exports.GeneralNames = GeneralNames; | ||
var Signature = asn1.define('Signature', function() { | ||
var ECPrivateKey2 = asn1.define('ECPrivateKey2', function() { | ||
this.seq().obj( | ||
this.key('algorithm').seq().obj( | ||
this.key('algorithm').objid(), | ||
this.null_() | ||
), | ||
this.key('digest').octstr() | ||
this.key('version').int(), | ||
this.key('privateKey').octstr(), | ||
this.key('publicKey').seq().obj( | ||
this.key('key').bitstr() | ||
) | ||
); | ||
}); | ||
exports.Signature = Signature; | ||
var IA5Str = asn1.define('IA5Str', function() { | ||
this.ia5str(); | ||
}); | ||
exports.IA5Str = IA5Str; | ||
exports.SHA256 = [ 2, 16, 840, 1, 101, 3, 4, 2, 1 ]; | ||
exports.SHA256RSA = [ 1, 2, 840, 113549, 1, 1, 11 ]; | ||
exports.RSA = [ 1, 2, 840, 113549, 1, 1, 1 ]; | ||
exports.COMMONNAME = [ 2, 5, 4, 3 ]; | ||
exports.ALTNAME = [ 2, 5, 29, 17 ]; | ||
exports.TBSCertificate = rfc3280.TBSCertificate; | ||
exports.Certificate = rfc3280.Certificate; | ||
exports.ECPrivateKey2 = ECPrivateKey2; |
@@ -22,2 +22,5 @@ var sign = require('./sign'); | ||
var data = algos[algorithm]; | ||
if (!data) { | ||
throw new Error('Unknown message digest'); | ||
} | ||
this._hash = crypto.createHash(data.hash); | ||
@@ -50,2 +53,5 @@ this._tag = data.id; | ||
var data = algos[algorithm]; | ||
if (!data) { | ||
throw new Error('Unknown message digest'); | ||
} | ||
this._hash = crypto.createHash(data.hash); | ||
@@ -52,0 +58,0 @@ this._tag = data.id; |
{ | ||
"name": "browserify-sign", | ||
"version": "2.3.0", | ||
"version": "2.4.0", | ||
"description": "", | ||
@@ -16,7 +16,8 @@ "main": "index.js", | ||
"dependencies": { | ||
"pemstrip": "0.0.1", | ||
"asn1.js": "^0.6.4", | ||
"asn1.js-rfc3280": "^0.5.1", | ||
"bn.js": "^0.15.2", | ||
"elliptic": "^0.15.14", | ||
"inherits": "^2.0.1", | ||
"bn.js": "^0.15.2", | ||
"asn1.js": "^0.6.4", | ||
"pemstrip": "0.0.1", | ||
"readable-stream": "^1.0.33" | ||
@@ -23,0 +24,0 @@ }, |
@@ -15,10 +15,15 @@ var pemstrip = require('pemstrip'); | ||
var data = new Buffer(stripped.base64, 'base64'); | ||
var subtype | ||
var subtype,ndata; | ||
switch (type) { | ||
case 'PUBLIC KEY': | ||
data = asn1.PublicKey.decode(data, 'der'); | ||
subtype = data.algorithm.algorithm.join('.'); | ||
ndata = asn1.PublicKey.decode(data, 'der'); | ||
subtype = ndata.algorithm.algorithm.join('.'); | ||
switch(subtype) { | ||
case '1.2.840.113549.1.1.1': | ||
return asn1.RSAPublicKey.decode(data.subjectPublicKey.data, 'der'); | ||
return asn1.RSAPublicKey.decode(ndata.subjectPublicKey.data, 'der'); | ||
case '1.2.840.10045.2.1': | ||
return { | ||
type: 'ec', | ||
data: asn1.ECPublicKey.decode(data, 'der') | ||
}; | ||
default: throw new Error('unknown key id ' + subtype); | ||
@@ -32,7 +37,13 @@ } | ||
case 'PRIVATE KEY': | ||
data = asn1.PrivateKey.decode(data, 'der'); | ||
subtype = data.algorithm.algorithm.join('.'); | ||
ndata = asn1.PrivateKey.decode(data, 'der'); | ||
subtype = ndata.algorithm.algorithm.join('.'); | ||
switch(subtype) { | ||
case '1.2.840.113549.1.1.1': | ||
return asn1.RSAPrivateKey.decode(data.subjectPrivateKey, 'der'); | ||
return asn1.RSAPrivateKey.decode(ndata.subjectPrivateKey, 'der'); | ||
case '1.2.840.10045.2.1': | ||
ndata = asn1.ECPrivateWrap.decode(data, 'der'); | ||
return { | ||
curve: ndata.algorithm.curve, | ||
privateKey: asn1.ECPrivateKey.decode(ndata.subjectPrivateKey, 'der').privateKey | ||
}; | ||
default: throw new Error('unknown key id ' + subtype); | ||
@@ -45,2 +56,8 @@ } | ||
return asn1.RSAPrivateKey.decode(data, 'der'); | ||
case 'EC PRIVATE KEY': | ||
data = asn1.ECPrivateKey.decode(data, 'der'); | ||
return { | ||
curve: data.parameters.value, | ||
privateKey: data.privateKey | ||
} | ||
default: throw new Error('unknown key type ' + type); | ||
@@ -47,0 +64,0 @@ } |
@@ -15,5 +15,5 @@ browserify-sign [![Build Status](https://travis-ci.org/calvinmetcalf/browserify-sign.svg)](https://travis-ci.org/calvinmetcalf/browserify-sign) | ||
- eliptical curve signing | ||
- publicEncrypt and privateDecrypt? | ||
- ~~publicEncrypt and privateDecrypt?~~ (out of scope) | ||
- ~~other key encodings (non rss format public keys)~~ | ||
- dsa keys? | ||
- ~~keys with passwords~~ |
15
sign.js
// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js | ||
var parseKeys = require('./parseKeys'); | ||
var bn = require('bn.js'); | ||
var elliptic = require('elliptic'); | ||
module.exports = sign; | ||
function sign(hash, key, crypto) { | ||
var priv = parseKeys(key, crypto); | ||
if (priv.curve) { | ||
return ecSign(hash, priv, crypto); | ||
} | ||
var len = priv.modulus.byteLength(); | ||
@@ -40,2 +44,13 @@ var pad = [ 0, 1 ]; | ||
return new Buffer(m2.toArray()); | ||
} | ||
function ecSign(hash, priv, crypto) { | ||
elliptic.rand = crypto.randomBytes; | ||
var curve; | ||
if (priv.curve.join('.') === '1.3.132.0.10') { | ||
curve = new elliptic.ec('secp256k1'); | ||
} | ||
var key = curve.genKeyPair(); | ||
key._importPrivate(priv.privateKey); | ||
var out = key.sign(hash); | ||
return new Buffer(out.toDER()); | ||
} |
@@ -23,2 +23,13 @@ var test = require('tape'); | ||
} | ||
var ec = { | ||
private: fs.readFileSync(__dirname + '/ec.priv'), | ||
public: fs.readFileSync(__dirname + '/ec.pub') | ||
} | ||
var ecpass = { | ||
private: { | ||
key: fs.readFileSync(__dirname + '/ec.pass.priv'), | ||
passphrase: 'bard' | ||
}, | ||
public: fs.readFileSync(__dirname + '/ec.pub') | ||
} | ||
function isNode10() { | ||
@@ -46,3 +57,24 @@ return process.version && process.version.split('.').length === 3 && parseInt(process.version.split('.')[1], 10) <= 10; | ||
} | ||
function ectestIt(keys, message, scheme) { | ||
var pub = keys.public; | ||
var priv = keys.private; | ||
test(message.toString(), function (t) { | ||
t.plan(3); | ||
var nodeSign = nodeCrypto.createSign(scheme); | ||
var mySign = myCrypto.createSign(scheme); | ||
var mySig = mySign.update(message).sign(priv); | ||
var nodeSig = nodeSign.update(message).sign(priv); | ||
t.notEqual(mySig.toString('hex'), nodeSig.toString('hex'), 'not equal sigs'); | ||
var myVer = myCrypto.createVerify(scheme); | ||
var nodeVer = nodeCrypto.createVerify(scheme); | ||
t.ok(nodeVer.update(message).verify(pub, mySig), 'node validate my sig'); | ||
t.ok(myVer.update(message).verify(pub, nodeSig), 'me validate node sig'); | ||
}); | ||
} | ||
ectestIt(ec, new Buffer('ecdsa with sha1'), 'ecdsa-with-SHA1'); | ||
testIt(rsa1024, new Buffer('sha1 with 1024 keys'), 'RSA-SHA1'); | ||
testIt(rsa2028, new Buffer('sha1 with 2028 keys'), 'RSA-SHA1'); | ||
testIt(nonrsa1024, new Buffer('sha1 with 1024 keys non-rsa key'), 'RSA-SHA1'); | ||
testIt(rsa1024, new Buffer('sha224 with 1024 keys'), 'RSA-SHA224'); | ||
@@ -61,2 +93,4 @@ testIt(nonrsa1024, new Buffer('sha224 with 1024 keys non-rsa key'), 'RSA-SHA224'); | ||
if (!isNode10()) { | ||
ectestIt(ecpass, new Buffer('ecdsa with password'), 'ecdsa-with-SHA1'); | ||
testIt(pass1024, new Buffer('sha1 with 1024 keys and password'), 'RSA-SHA1'); | ||
testIt(pass1024, new Buffer('sha224 with 1024 keys and password'), 'RSA-SHA224'); | ||
@@ -63,0 +97,0 @@ testIt(pass1024, new Buffer('sha256 with 1024 keys and password'), 'RSA-SHA256'); |
// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js | ||
var parseKeys = require('./parseKeys'); | ||
var elliptic = require('elliptic'); | ||
var bn = require('bn.js'); | ||
@@ -8,3 +8,5 @@ module.exports = verify; | ||
var pub = parseKeys(key); | ||
if (pub.type === 'ec') { | ||
return ecVerify(sig, hash, pub); | ||
} | ||
var red = bn.mont(pub.modulus); | ||
@@ -24,2 +26,10 @@ sig = new bn(sig).toRed(red); | ||
return !out; | ||
} | ||
} | ||
function ecVerify(sig, hash, pub) { | ||
var curve; | ||
if (pub.data.algorithm.curve.join('.') === '1.3.132.0.10') { | ||
curve = new elliptic.ec('secp256k1'); | ||
} | ||
var pubkey = pub.data.subjectPrivateKey.data; | ||
return curve.verify(hash.toString('hex'), sig.toString('hex'), pubkey.toString('hex')); | ||
} |
23554
24
463
7
+ Addedelliptic@^0.15.14
+ Addedbn.js@0.16.1(transitive)
+ Addedbrorand@1.1.0(transitive)
+ Addedelliptic@0.15.17(transitive)
+ Addedhash.js@0.2.1(transitive)