Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/sshpk/lib/formats/pem.js')
-rw-r--r--node_modules/sshpk/lib/formats/pem.js116
1 files changed, 107 insertions, 9 deletions
diff --git a/node_modules/sshpk/lib/formats/pem.js b/node_modules/sshpk/lib/formats/pem.js
index 859cfa13f..bbe78fcb5 100644
--- a/node_modules/sshpk/lib/formats/pem.js
+++ b/node_modules/sshpk/lib/formats/pem.js
@@ -1,4 +1,4 @@
-// Copyright 2015 Joyent, Inc.
+// Copyright 2018 Joyent, Inc.
module.exports = {
read: read,
@@ -21,6 +21,29 @@ var rfc4253 = require('./rfc4253');
var errors = require('../errors');
+var OID_PBES2 = '1.2.840.113549.1.5.13';
+var OID_PBKDF2 = '1.2.840.113549.1.5.12';
+
+var OID_TO_CIPHER = {
+ '1.2.840.113549.3.7': '3des-cbc',
+ '2.16.840.1.101.3.4.1.2': 'aes128-cbc',
+ '2.16.840.1.101.3.4.1.42': 'aes256-cbc'
+};
+var CIPHER_TO_OID = {};
+Object.keys(OID_TO_CIPHER).forEach(function (k) {
+ CIPHER_TO_OID[OID_TO_CIPHER[k]] = k;
+});
+
+var OID_TO_HASH = {
+ '1.2.840.113549.2.7': 'sha1',
+ '1.2.840.113549.2.9': 'sha256',
+ '1.2.840.113549.2.11': 'sha512'
+};
+var HASH_TO_OID = {};
+Object.keys(OID_TO_HASH).forEach(function (k) {
+ HASH_TO_OID[OID_TO_HASH[k]] = k;
+});
+
/*
* For reading we support both PKCS#1 and PKCS#8. If we find a private key,
* we just take the public component of it and use that.
@@ -32,14 +55,22 @@ function read(buf, options, forceType) {
buf = buf.toString('ascii');
}
- var lines = buf.trim().split('\n');
+ var lines = buf.trim().split(/[\r\n]+/g);
- var m = lines[0].match(/*JSSTYLED*/
- /[-]+[ ]*BEGIN ([A-Z0-9][A-Za-z0-9]+ )?(PUBLIC|PRIVATE) KEY[ ]*[-]+/);
+ var m;
+ var si = -1;
+ while (!m && si < lines.length) {
+ m = lines[++si].match(/*JSSTYLED*/
+ /[-]+[ ]*BEGIN ([A-Z0-9][A-Za-z0-9]+ )?(PUBLIC|PRIVATE) KEY[ ]*[-]+/);
+ }
assert.ok(m, 'invalid PEM header');
- var m2 = lines[lines.length - 1].match(/*JSSTYLED*/
- /[-]+[ ]*END ([A-Z0-9][A-Za-z0-9]+ )?(PUBLIC|PRIVATE) KEY[ ]*[-]+/);
+ var m2;
+ var ei = lines.length;
+ while (!m2 && ei > 0) {
+ m2 = lines[--ei].match(/*JSSTYLED*/
+ /[-]+[ ]*END ([A-Z0-9][A-Za-z0-9]+ )?(PUBLIC|PRIVATE) KEY[ ]*[-]+/);
+ }
assert.ok(m2, 'invalid PEM footer');
/* Begin and end banners must match key type */
@@ -53,6 +84,8 @@ function read(buf, options, forceType) {
alg = m[1].trim();
}
+ lines = lines.slice(si, ei + 1);
+
var headers = {};
while (true) {
lines = lines.slice(1);
@@ -63,6 +96,10 @@ function read(buf, options, forceType) {
headers[m[1].toLowerCase()] = m[2];
}
+ /* Chop off the first and last lines */
+ lines = lines.slice(0, -1).join('');
+ buf = Buffer.from(lines, 'base64');
+
var cipher, key, iv;
if (headers['proc-type']) {
var parts = headers['proc-type'].split(',');
@@ -85,9 +122,70 @@ function read(buf, options, forceType) {
}
}
- /* Chop off the first and last lines */
- lines = lines.slice(0, -1).join('');
- buf = Buffer.from(lines, 'base64');
+ if (alg && alg.toLowerCase() === 'encrypted') {
+ var eder = new asn1.BerReader(buf);
+ var pbesEnd;
+ eder.readSequence();
+
+ eder.readSequence();
+ pbesEnd = eder.offset + eder.length;
+
+ var method = eder.readOID();
+ if (method !== OID_PBES2) {
+ throw (new Error('Unsupported PEM/PKCS8 encryption ' +
+ 'scheme: ' + method));
+ }
+
+ eder.readSequence(); /* PBES2-params */
+
+ eder.readSequence(); /* keyDerivationFunc */
+ var kdfEnd = eder.offset + eder.length;
+ var kdfOid = eder.readOID();
+ if (kdfOid !== OID_PBKDF2)
+ throw (new Error('Unsupported PBES2 KDF: ' + kdfOid));
+ eder.readSequence();
+ var salt = eder.readString(asn1.Ber.OctetString, true);
+ var iterations = eder.readInt();
+ var hashAlg = 'sha1';
+ if (eder.offset < kdfEnd) {
+ eder.readSequence();
+ var hashAlgOid = eder.readOID();
+ hashAlg = OID_TO_HASH[hashAlgOid];
+ if (hashAlg === undefined) {
+ throw (new Error('Unsupported PBKDF2 hash: ' +
+ hashAlgOid));
+ }
+ }
+ eder._offset = kdfEnd;
+
+ eder.readSequence(); /* encryptionScheme */
+ var cipherOid = eder.readOID();
+ cipher = OID_TO_CIPHER[cipherOid];
+ if (cipher === undefined) {
+ throw (new Error('Unsupported PBES2 cipher: ' +
+ cipherOid));
+ }
+ iv = eder.readString(asn1.Ber.OctetString, true);
+
+ eder._offset = pbesEnd;
+ buf = eder.readString(asn1.Ber.OctetString, true);
+
+ if (typeof (options.passphrase) === 'string') {
+ options.passphrase = Buffer.from(
+ options.passphrase, 'utf-8');
+ }
+ if (!Buffer.isBuffer(options.passphrase)) {
+ throw (new errors.KeyEncryptedError(
+ options.filename, 'PEM'));
+ }
+
+ var cinfo = utils.opensshCipherInfo(cipher);
+
+ cipher = cinfo.opensslName;
+ key = utils.pbkdf2(hashAlg, salt, iterations, cinfo.keySize,
+ options.passphrase);
+ alg = undefined;
+ }
if (cipher && key && iv) {
var cipherStream = crypto.createDecipheriv(cipher, key, iv);