| 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) | 
| } |