108 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			108 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 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)
 | |
| }
 |