| var asn1 = require('./asn1') |
| var aesid = require('./aesid.json') |
| var fixProc = require('./fixProc') |
| var ciphers = require('browserify-aes') |
| var compat = require('pbkdf2') |
| var Buffer = require('safe-buffer').Buffer |
| module.exports = parseKeys |
| |
| function parseKeys (buffer) { |
| var password |
| if (typeof buffer === 'object' && !Buffer.isBuffer(buffer)) { |
| password = buffer.passphrase |
| buffer = buffer.key |
| } |
| if (typeof buffer === 'string') { |
| buffer = Buffer.from(buffer) |
| } |
| |
| var stripped = fixProc(buffer, password) |
| |
| var type = stripped.tag |
| var data = stripped.data |
| var subtype, ndata |
| switch (type) { |
| case 'CERTIFICATE': |
| ndata = asn1.certificate.decode(data, 'der').tbsCertificate.subjectPublicKeyInfo |
| // falls through |
| case 'PUBLIC KEY': |
| if (!ndata) { |
| 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(ndata.subjectPublicKey.data, 'der') |
| case '1.2.840.10045.2.1': |
| ndata.subjectPrivateKey = ndata.subjectPublicKey |
| return { |
| type: 'ec', |
| data: ndata |
| } |
| case '1.2.840.10040.4.1': |
| ndata.algorithm.params.pub_key = asn1.DSAparam.decode(ndata.subjectPublicKey.data, 'der') |
| return { |
| type: 'dsa', |
| data: ndata.algorithm.params |
| } |
| default: throw new Error('unknown key id ' + subtype) |
| } |
| throw new Error('unknown key type ' + type) |
| case 'ENCRYPTED PRIVATE KEY': |
| data = asn1.EncryptedPrivateKey.decode(data, 'der') |
| data = decrypt(data, password) |
| // falls through |
| case 'PRIVATE KEY': |
| 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(ndata.subjectPrivateKey, 'der') |
| case '1.2.840.10045.2.1': |
| return { |
| curve: ndata.algorithm.curve, |
| privateKey: asn1.ECPrivateKey.decode(ndata.subjectPrivateKey, 'der').privateKey |
| } |
| case '1.2.840.10040.4.1': |
| ndata.algorithm.params.priv_key = asn1.DSAparam.decode(ndata.subjectPrivateKey, 'der') |
| return { |
| type: 'dsa', |
| params: ndata.algorithm.params |
| } |
| default: throw new Error('unknown key id ' + subtype) |
| } |
| throw new Error('unknown key type ' + type) |
| case 'RSA PUBLIC KEY': |
| return asn1.RSAPublicKey.decode(data, 'der') |
| case 'RSA PRIVATE KEY': |
| return asn1.RSAPrivateKey.decode(data, 'der') |
| case 'DSA PRIVATE KEY': |
| return { |
| type: 'dsa', |
| params: asn1.DSAPrivateKey.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) |
| } |
| } |
| parseKeys.signature = asn1.signature |
| function decrypt (data, password) { |
| var salt = data.algorithm.decrypt.kde.kdeparams.salt |
| var iters = parseInt(data.algorithm.decrypt.kde.kdeparams.iters.toString(), 10) |
| var algo = aesid[data.algorithm.decrypt.cipher.algo.join('.')] |
| var iv = data.algorithm.decrypt.cipher.iv |
| var cipherText = data.subjectPrivateKey |
| var keylen = parseInt(algo.split('-')[1], 10) / 8 |
| var key = compat.pbkdf2Sync(password, salt, iters, keylen, 'sha1') |
| var cipher = ciphers.createDecipheriv(algo, key, iv) |
| var out = [] |
| out.push(cipher.update(cipherText)) |
| out.push(cipher.final()) |
| return Buffer.concat(out) |
| } |