Skip to content

Commit 6cfeecb

Browse files
committed
first
0 parents  commit 6cfeecb

File tree

5 files changed

+223
-0
lines changed

5 files changed

+223
-0
lines changed

aesid.json

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{"2.16.840.1.101.3.4.1.1": "aes-128-ecb",
2+
"2.16.840.1.101.3.4.1.2": "aes-128-cbc",
3+
"2.16.840.1.101.3.4.1.3": "aes-128-ofb",
4+
"2.16.840.1.101.3.4.1.4": "aes-128-cfb",
5+
"2.16.840.1.101.3.4.1.21": "aes-192-ecb",
6+
"2.16.840.1.101.3.4.1.22": "aes-192-cbc",
7+
"2.16.840.1.101.3.4.1.23": "aes-192-ofb",
8+
"2.16.840.1.101.3.4.1.24": "aes-192-cfb",
9+
"2.16.840.1.101.3.4.1.41": "aes-256-ecb",
10+
"2.16.840.1.101.3.4.1.42": "aes-256-cbc",
11+
"2.16.840.1.101.3.4.1.43": "aes-256-ofb",
12+
"2.16.840.1.101.3.4.1.44": "aes-256-cfb"
13+
}

asn1.js

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// from https://github.com/indutny/self-signed/blob/gh-pages/lib/asn1.js
2+
// Fedor, you are amazing.
3+
4+
var asn1 = require('asn1.js');
5+
var rfc3280 = require('asn1.js-rfc3280');
6+
7+
var RSAPrivateKey = asn1.define('RSAPrivateKey', function() {
8+
this.seq().obj(
9+
this.key('version').int(),
10+
this.key('modulus').int(),
11+
this.key('publicExponent').int(),
12+
this.key('privateExponent').int(),
13+
this.key('prime1').int(),
14+
this.key('prime2').int(),
15+
this.key('exponent1').int(),
16+
this.key('exponent2').int(),
17+
this.key('coefficient').int()
18+
);
19+
});
20+
exports.RSAPrivateKey = RSAPrivateKey;
21+
22+
var RSAPublicKey = asn1.define('RSAPublicKey', function() {
23+
this.seq().obj(
24+
this.key('modulus').int(),
25+
this.key('publicExponent').int()
26+
);
27+
});
28+
exports.RSAPublicKey = RSAPublicKey;
29+
30+
var PublicKey = rfc3280.SubjectPublicKeyInfo;
31+
exports.PublicKey = PublicKey;
32+
var ECPublicKey = asn1.define('ECPublicKey', function() {
33+
this.seq().obj(
34+
this.key('algorithm').seq().obj(
35+
this.key('id').objid(),
36+
this.key('curve').objid()
37+
),
38+
this.key('subjectPrivateKey').bitstr()
39+
);
40+
});
41+
exports.ECPublicKey = ECPublicKey;
42+
var ECPrivateWrap = asn1.define('ECPrivateWrap', function() {
43+
this.seq().obj(
44+
this.key('version').int(),
45+
this.key('algorithm').seq().obj(
46+
this.key('id').objid(),
47+
this.key('curve').objid()
48+
),
49+
this.key('subjectPrivateKey').octstr()
50+
);
51+
});
52+
exports.ECPrivateWrap = ECPrivateWrap;
53+
var PrivateKeyInfo = asn1.define('PrivateKeyInfo', function() {
54+
this.seq().obj(
55+
this.key('version').int(),
56+
this.key('algorithm').use(rfc3280.AlgorithmIdentifier),
57+
this.key('subjectPrivateKey').octstr()
58+
);
59+
});
60+
exports.PrivateKey = PrivateKeyInfo;
61+
var EncryptedPrivateKeyInfo = asn1.define('EncryptedPrivateKeyInfo', function() {
62+
this.seq().obj(
63+
this.key('algorithm').seq().obj(
64+
this.key('id').objid(),
65+
this.key('decrypt').seq().obj(
66+
this.key('kde').seq().obj(
67+
this.key('id').objid(),
68+
this.key('kdeparams').seq().obj(
69+
this.key('salt').octstr(),
70+
this.key('iters').int()
71+
)
72+
),
73+
this.key('cipher').seq().obj(
74+
this.key('algo').objid(),
75+
this.key('iv').octstr()
76+
)
77+
)
78+
),
79+
this.key('subjectPrivateKey').octstr()
80+
);
81+
});
82+
exports.EncryptedPrivateKey = EncryptedPrivateKeyInfo;
83+
84+
85+
86+
var ECPrivateKey = asn1.define('ECPrivateKey', function() {
87+
this.seq().obj(
88+
this.key('version').int(),
89+
this.key('privateKey').octstr(),
90+
this.key('parameters').optional().explicit(0).use(ECParameters),
91+
this.key('publicKey').optional().explicit(1).bitstr()
92+
);
93+
});
94+
exports.ECPrivateKey = ECPrivateKey;
95+
var ECParameters = asn1.define('ECParameters', function() {
96+
this.choice({
97+
namedCurve: this.objid()
98+
});
99+
});
100+
101+
var ECPrivateKey2 = asn1.define('ECPrivateKey2', function() {
102+
this.seq().obj(
103+
this.key('version').int(),
104+
this.key('privateKey').octstr(),
105+
this.key('publicKey').seq().obj(
106+
this.key('key').bitstr()
107+
)
108+
);
109+
});
110+
exports.ECPrivateKey2 = ECPrivateKey2;

index.js

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
var pemstrip = require('pemstrip');
2+
var asn1 = require('./asn1');
3+
var aesid = require('./aesid.json');
4+
module.exports = parseKeys;
5+
6+
function parseKeys(buffer, crypto) {
7+
var password;
8+
if (typeof buffer === 'object' && !Buffer.isBuffer(buffer)) {
9+
password = buffer.passphrase;
10+
buffer = buffer.key;
11+
}
12+
var stripped = pemstrip.strip(buffer);
13+
var type = stripped.tag;
14+
var data = new Buffer(stripped.base64, 'base64');
15+
var subtype,ndata;
16+
switch (type) {
17+
case 'PUBLIC KEY':
18+
ndata = asn1.PublicKey.decode(data, 'der');
19+
subtype = ndata.algorithm.algorithm.join('.');
20+
switch(subtype) {
21+
case '1.2.840.113549.1.1.1':
22+
return asn1.RSAPublicKey.decode(ndata.subjectPublicKey.data, 'der');
23+
case '1.2.840.10045.2.1':
24+
return {
25+
type: 'ec',
26+
data: asn1.ECPublicKey.decode(data, 'der')
27+
};
28+
default: throw new Error('unknown key id ' + subtype);
29+
}
30+
throw new Error('unknown key type ' + type);
31+
case 'ENCRYPTED PRIVATE KEY':
32+
data = asn1.EncryptedPrivateKey.decode(data, 'der');
33+
data = decrypt(crypto, data, password);
34+
//falling through
35+
case 'PRIVATE KEY':
36+
ndata = asn1.PrivateKey.decode(data, 'der');
37+
subtype = ndata.algorithm.algorithm.join('.');
38+
switch(subtype) {
39+
case '1.2.840.113549.1.1.1':
40+
return asn1.RSAPrivateKey.decode(ndata.subjectPrivateKey, 'der');
41+
case '1.2.840.10045.2.1':
42+
ndata = asn1.ECPrivateWrap.decode(data, 'der');
43+
return {
44+
curve: ndata.algorithm.curve,
45+
privateKey: asn1.ECPrivateKey.decode(ndata.subjectPrivateKey, 'der').privateKey
46+
};
47+
default: throw new Error('unknown key id ' + subtype);
48+
}
49+
throw new Error('unknown key type ' + type);
50+
case 'RSA PUBLIC KEY':
51+
return asn1.RSAPublicKey.decode(data, 'der');
52+
case 'RSA PRIVATE KEY':
53+
return asn1.RSAPrivateKey.decode(data, 'der');
54+
case 'EC PRIVATE KEY':
55+
data = asn1.ECPrivateKey.decode(data, 'der');
56+
return {
57+
curve: data.parameters.value,
58+
privateKey: data.privateKey
59+
};
60+
default: throw new Error('unknown key type ' + type);
61+
}
62+
}
63+
function decrypt(crypto, data, password) {
64+
var salt = data.algorithm.decrypt.kde.kdeparams.salt;
65+
var iters = data.algorithm.decrypt.kde.kdeparams.iters;
66+
var algo = aesid[data.algorithm.decrypt.cipher.algo.join('.')];
67+
var iv = data.algorithm.decrypt.cipher.iv;
68+
var cipherText = data.subjectPrivateKey;
69+
var keylen = parseInt(algo.split('-')[1], 10)/8;
70+
var key = crypto.pbkdf2Sync(password, salt, iters, keylen);
71+
var cipher = crypto.createDecipheriv(algo, key, iv);
72+
var out = [];
73+
out.push(cipher.update(cipherText));
74+
out.push(cipher.final());
75+
return Buffer.concat(out);
76+
}

package.json

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "parse-asn1",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "git://github.com/calvinmetcalf/parse-asn1.git"
12+
},
13+
"author": "",
14+
"license": "ISC",
15+
"dependencies": {
16+
"asn1.js": "^0.6.5",
17+
"asn1.js-rfc3280": "^0.5.1",
18+
"pemstrip": "0.0.1"
19+
}
20+
}

readme.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
parse-asn1
2+
===
3+
4+
utility library for parsing asn1 files for use with browserify-sign.

0 commit comments

Comments
 (0)