aboutsummaryrefslogtreecommitdiffstats
path: root/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats
diff options
context:
space:
mode:
Diffstat (limited to 'vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats')
-rw-r--r--vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/auto.js73
-rw-r--r--vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/openssh-cert.js289
-rw-r--r--vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/pem.js186
-rw-r--r--vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/pkcs1.js320
-rw-r--r--vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/pkcs8.js505
-rw-r--r--vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/rfc4253.js146
-rw-r--r--vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/ssh-private.js261
-rw-r--r--vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/ssh.js114
-rw-r--r--vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/x509-pem.js77
-rw-r--r--vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/x509.js699
10 files changed, 2670 insertions, 0 deletions
diff --git a/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/auto.js b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/auto.js
new file mode 100644
index 00000000..973c0324
--- /dev/null
+++ b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/auto.js
@@ -0,0 +1,73 @@
+// Copyright 2015 Joyent, Inc.
+
+module.exports = {
+ read: read,
+ write: write
+};
+
+var assert = require('assert-plus');
+var utils = require('../utils');
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+
+var pem = require('./pem');
+var ssh = require('./ssh');
+var rfc4253 = require('./rfc4253');
+
+function read(buf, options) {
+ if (typeof (buf) === 'string') {
+ if (buf.trim().match(/^[-]+[ ]*BEGIN/))
+ return (pem.read(buf, options));
+ if (buf.match(/^\s*ssh-[a-z]/))
+ return (ssh.read(buf, options));
+ if (buf.match(/^\s*ecdsa-/))
+ return (ssh.read(buf, options));
+ buf = new Buffer(buf, 'binary');
+ } else {
+ assert.buffer(buf);
+ if (findPEMHeader(buf))
+ return (pem.read(buf, options));
+ if (findSSHHeader(buf))
+ return (ssh.read(buf, options));
+ }
+ if (buf.readUInt32BE(0) < buf.length)
+ return (rfc4253.read(buf, options));
+ throw (new Error('Failed to auto-detect format of key'));
+}
+
+function findSSHHeader(buf) {
+ var offset = 0;
+ while (offset < buf.length &&
+ (buf[offset] === 32 || buf[offset] === 10 || buf[offset] === 9))
+ ++offset;
+ if (offset + 4 <= buf.length &&
+ buf.slice(offset, offset + 4).toString('ascii') === 'ssh-')
+ return (true);
+ if (offset + 6 <= buf.length &&
+ buf.slice(offset, offset + 6).toString('ascii') === 'ecdsa-')
+ return (true);
+ return (false);
+}
+
+function findPEMHeader(buf) {
+ var offset = 0;
+ while (offset < buf.length &&
+ (buf[offset] === 32 || buf[offset] === 10))
+ ++offset;
+ if (buf[offset] !== 45)
+ return (false);
+ while (offset < buf.length &&
+ (buf[offset] === 45))
+ ++offset;
+ while (offset < buf.length &&
+ (buf[offset] === 32))
+ ++offset;
+ if (offset + 5 > buf.length ||
+ buf.slice(offset, offset + 5).toString('ascii') !== 'BEGIN')
+ return (false);
+ return (true);
+}
+
+function write(key, options) {
+ throw (new Error('"auto" format cannot be used for writing'));
+}
diff --git a/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/openssh-cert.js b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/openssh-cert.js
new file mode 100644
index 00000000..8ce7350f
--- /dev/null
+++ b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/openssh-cert.js
@@ -0,0 +1,289 @@
+// Copyright 2016 Joyent, Inc.
+
+module.exports = {
+ read: read,
+ verify: verify,
+ sign: sign,
+ write: write,
+
+ /* Internal private API */
+ fromBuffer: fromBuffer,
+ toBuffer: toBuffer
+};
+
+var assert = require('assert-plus');
+var SSHBuffer = require('../ssh-buffer');
+var crypto = require('crypto');
+var algs = require('../algs');
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+var Identity = require('../identity');
+var rfc4253 = require('./rfc4253');
+var Signature = require('../signature');
+var utils = require('../utils');
+var Certificate = require('../certificate');
+
+function verify(cert, key) {
+ /*
+ * We always give an issuerKey, so if our verify() is being called then
+ * there was no signature. Return false.
+ */
+ return (false);
+}
+
+var TYPES = {
+ 'user': 1,
+ 'host': 2
+};
+Object.keys(TYPES).forEach(function (k) { TYPES[TYPES[k]] = k; });
+
+var ECDSA_ALGO = /^ecdsa-sha2-([^@-]+)-cert-v01@openssh.com$/;
+
+function read(buf, options) {
+ if (Buffer.isBuffer(buf))
+ buf = buf.toString('ascii');
+ var parts = buf.trim().split(/[ \t\n]+/g);
+ if (parts.length < 2 || parts.length > 3)
+ throw (new Error('Not a valid SSH certificate line'));
+
+ var algo = parts[0];
+ var data = parts[1];
+
+ data = new Buffer(data, 'base64');
+ return (fromBuffer(data, algo));
+}
+
+function fromBuffer(data, algo, partial) {
+ var sshbuf = new SSHBuffer({ buffer: data });
+ var innerAlgo = sshbuf.readString();
+ if (algo !== undefined && innerAlgo !== algo)
+ throw (new Error('SSH certificate algorithm mismatch'));
+ if (algo === undefined)
+ algo = innerAlgo;
+
+ var cert = {};
+ cert.signatures = {};
+ cert.signatures.openssh = {};
+
+ cert.signatures.openssh.nonce = sshbuf.readBuffer();
+
+ var key = {};
+ var parts = (key.parts = []);
+ key.type = getAlg(algo);
+
+ var partCount = algs.info[key.type].parts.length;
+ while (parts.length < partCount)
+ parts.push(sshbuf.readPart());
+ assert.ok(parts.length >= 1, 'key must have at least one part');
+
+ var algInfo = algs.info[key.type];
+ if (key.type === 'ecdsa') {
+ var res = ECDSA_ALGO.exec(algo);
+ assert.ok(res !== null);
+ assert.strictEqual(res[1], parts[0].data.toString());
+ }
+
+ for (var i = 0; i < algInfo.parts.length; ++i) {
+ parts[i].name = algInfo.parts[i];
+ if (parts[i].name !== 'curve' &&
+ algInfo.normalize !== false) {
+ var p = parts[i];
+ p.data = utils.mpNormalize(p.data);
+ }
+ }
+
+ cert.subjectKey = new Key(key);
+
+ cert.serial = sshbuf.readInt64();
+
+ var type = TYPES[sshbuf.readInt()];
+ assert.string(type, 'valid cert type');
+
+ cert.signatures.openssh.keyId = sshbuf.readString();
+
+ var principals = [];
+ var pbuf = sshbuf.readBuffer();
+ var psshbuf = new SSHBuffer({ buffer: pbuf });
+ while (!psshbuf.atEnd())
+ principals.push(psshbuf.readString());
+ if (principals.length === 0)
+ principals = ['*'];
+
+ cert.subjects = principals.map(function (pr) {
+ if (type === 'user')
+ return (Identity.forUser(pr));
+ else if (type === 'host')
+ return (Identity.forHost(pr));
+ throw (new Error('Unknown identity type ' + type));
+ });
+
+ cert.validFrom = int64ToDate(sshbuf.readInt64());
+ cert.validUntil = int64ToDate(sshbuf.readInt64());
+
+ cert.signatures.openssh.critical = sshbuf.readBuffer();
+ cert.signatures.openssh.exts = sshbuf.readBuffer();
+
+ /* reserved */
+ sshbuf.readBuffer();
+
+ var signingKeyBuf = sshbuf.readBuffer();
+ cert.issuerKey = rfc4253.read(signingKeyBuf);
+
+ /*
+ * OpenSSH certs don't give the identity of the issuer, just their
+ * public key. So, we use an Identity that matches anything. The
+ * isSignedBy() function will later tell you if the key matches.
+ */
+ cert.issuer = Identity.forHost('**');
+
+ var sigBuf = sshbuf.readBuffer();
+ cert.signatures.openssh.signature =
+ Signature.parse(sigBuf, cert.issuerKey.type, 'ssh');
+
+ if (partial !== undefined) {
+ partial.remainder = sshbuf.remainder();
+ partial.consumed = sshbuf._offset;
+ }
+
+ return (new Certificate(cert));
+}
+
+function int64ToDate(buf) {
+ var i = buf.readUInt32BE(0) * 4294967296;
+ i += buf.readUInt32BE(4);
+ var d = new Date();
+ d.setTime(i * 1000);
+ d.sourceInt64 = buf;
+ return (d);
+}
+
+function dateToInt64(date) {
+ if (date.sourceInt64 !== undefined)
+ return (date.sourceInt64);
+ var i = Math.round(date.getTime() / 1000);
+ var upper = Math.floor(i / 4294967296);
+ var lower = Math.floor(i % 4294967296);
+ var buf = new Buffer(8);
+ buf.writeUInt32BE(upper, 0);
+ buf.writeUInt32BE(lower, 4);
+ return (buf);
+}
+
+function sign(cert, key) {
+ if (cert.signatures.openssh === undefined)
+ cert.signatures.openssh = {};
+ try {
+ var blob = toBuffer(cert, true);
+ } catch (e) {
+ delete (cert.signatures.openssh);
+ return (false);
+ }
+ var sig = cert.signatures.openssh;
+ var hashAlgo = undefined;
+ if (key.type === 'rsa' || key.type === 'dsa')
+ hashAlgo = 'sha1';
+ var signer = key.createSign(hashAlgo);
+ signer.write(blob);
+ sig.signature = signer.sign();
+ return (true);
+}
+
+function write(cert, options) {
+ if (options === undefined)
+ options = {};
+
+ var blob = toBuffer(cert);
+ var out = getCertType(cert.subjectKey) + ' ' + blob.toString('base64');
+ if (options.comment)
+ out = out + ' ' + options.comment;
+ return (out);
+}
+
+
+function toBuffer(cert, noSig) {
+ assert.object(cert.signatures.openssh, 'signature for openssh format');
+ var sig = cert.signatures.openssh;
+
+ if (sig.nonce === undefined)
+ sig.nonce = crypto.randomBytes(16);
+ var buf = new SSHBuffer({});
+ buf.writeString(getCertType(cert.subjectKey));
+ buf.writeBuffer(sig.nonce);
+
+ var key = cert.subjectKey;
+ var algInfo = algs.info[key.type];
+ algInfo.parts.forEach(function (part) {
+ buf.writePart(key.part[part]);
+ });
+
+ buf.writeInt64(cert.serial);
+
+ var type = cert.subjects[0].type;
+ assert.notStrictEqual(type, 'unknown');
+ cert.subjects.forEach(function (id) {
+ assert.strictEqual(id.type, type);
+ });
+ type = TYPES[type];
+ buf.writeInt(type);
+
+ if (sig.keyId === undefined) {
+ sig.keyId = cert.subjects[0].type + '_' +
+ (cert.subjects[0].uid || cert.subjects[0].hostname);
+ }
+ buf.writeString(sig.keyId);
+
+ var sub = new SSHBuffer({});
+ cert.subjects.forEach(function (id) {
+ if (type === TYPES.host)
+ sub.writeString(id.hostname);
+ else if (type === TYPES.user)
+ sub.writeString(id.uid);
+ });
+ buf.writeBuffer(sub.toBuffer());
+
+ buf.writeInt64(dateToInt64(cert.validFrom));
+ buf.writeInt64(dateToInt64(cert.validUntil));
+
+ if (sig.critical === undefined)
+ sig.critical = new Buffer(0);
+ buf.writeBuffer(sig.critical);
+
+ if (sig.exts === undefined)
+ sig.exts = new Buffer(0);
+ buf.writeBuffer(sig.exts);
+
+ /* reserved */
+ buf.writeBuffer(new Buffer(0));
+
+ sub = rfc4253.write(cert.issuerKey);
+ buf.writeBuffer(sub);
+
+ if (!noSig)
+ buf.writeBuffer(sig.signature.toBuffer('ssh'));
+
+ return (buf.toBuffer());
+}
+
+function getAlg(certType) {
+ if (certType === 'ssh-rsa-cert-v01@openssh.com')
+ return ('rsa');
+ if (certType === 'ssh-dss-cert-v01@openssh.com')
+ return ('dsa');
+ if (certType.match(ECDSA_ALGO))
+ return ('ecdsa');
+ if (certType === 'ssh-ed25519-cert-v01@openssh.com')
+ return ('ed25519');
+ throw (new Error('Unsupported cert type ' + certType));
+}
+
+function getCertType(key) {
+ if (key.type === 'rsa')
+ return ('ssh-rsa-cert-v01@openssh.com');
+ if (key.type === 'dsa')
+ return ('ssh-dss-cert-v01@openssh.com');
+ if (key.type === 'ecdsa')
+ return ('ecdsa-sha2-' + key.curve + '-cert-v01@openssh.com');
+ if (key.type === 'ed25519')
+ return ('ssh-ed25519-cert-v01@openssh.com');
+ throw (new Error('Unsupported key type ' + key.type));
+}
diff --git a/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/pem.js b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/pem.js
new file mode 100644
index 00000000..c254e4e8
--- /dev/null
+++ b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/pem.js
@@ -0,0 +1,186 @@
+// Copyright 2015 Joyent, Inc.
+
+module.exports = {
+ read: read,
+ write: write
+};
+
+var assert = require('assert-plus');
+var asn1 = require('asn1');
+var crypto = require('crypto');
+var algs = require('../algs');
+var utils = require('../utils');
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+
+var pkcs1 = require('./pkcs1');
+var pkcs8 = require('./pkcs8');
+var sshpriv = require('./ssh-private');
+var rfc4253 = require('./rfc4253');
+
+var errors = require('../errors');
+
+/*
+ * 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.
+ */
+function read(buf, options, forceType) {
+ var input = buf;
+ if (typeof (buf) !== 'string') {
+ assert.buffer(buf, 'buf');
+ buf = buf.toString('ascii');
+ }
+
+ var lines = buf.trim().split('\n');
+
+ var m = lines[0].match(/*JSSTYLED*/
+ /[-]+[ ]*BEGIN ([A-Z0-9]+ )?(PUBLIC|PRIVATE) KEY[ ]*[-]+/);
+ assert.ok(m, 'invalid PEM header');
+
+ var m2 = lines[lines.length - 1].match(/*JSSTYLED*/
+ /[-]+[ ]*END ([A-Z0-9]+ )?(PUBLIC|PRIVATE) KEY[ ]*[-]+/);
+ assert.ok(m2, 'invalid PEM footer');
+
+ /* Begin and end banners must match key type */
+ assert.equal(m[2], m2[2]);
+ var type = m[2].toLowerCase();
+
+ var alg;
+ if (m[1]) {
+ /* They also must match algorithms, if given */
+ assert.equal(m[1], m2[1], 'PEM header and footer mismatch');
+ alg = m[1].trim();
+ }
+
+ var headers = {};
+ while (true) {
+ lines = lines.slice(1);
+ m = lines[0].match(/*JSSTYLED*/
+ /^([A-Za-z0-9-]+): (.+)$/);
+ if (!m)
+ break;
+ headers[m[1].toLowerCase()] = m[2];
+ }
+
+ var cipher, key, iv;
+ if (headers['proc-type']) {
+ var parts = headers['proc-type'].split(',');
+ if (parts[0] === '4' && parts[1] === 'ENCRYPTED') {
+ if (typeof (options.passphrase) === 'string') {
+ options.passphrase = new Buffer(
+ options.passphrase, 'utf-8');
+ }
+ if (!Buffer.isBuffer(options.passphrase)) {
+ throw (new errors.KeyEncryptedError(
+ options.filename, 'PEM'));
+ } else {
+ parts = headers['dek-info'].split(',');
+ assert.ok(parts.length === 2);
+ cipher = parts[0].toLowerCase();
+ iv = new Buffer(parts[1], 'hex');
+ key = utils.opensslKeyDeriv(cipher, iv,
+ options.passphrase, 1).key;
+ }
+ }
+ }
+
+ /* Chop off the first and last lines */
+ lines = lines.slice(0, -1).join('');
+ buf = new Buffer(lines, 'base64');
+
+ if (cipher && key && iv) {
+ var cipherStream = crypto.createDecipheriv(cipher, key, iv);
+ var chunk, chunks = [];
+ cipherStream.once('error', function (e) {
+ if (e.toString().indexOf('bad decrypt') !== -1) {
+ throw (new Error('Incorrect passphrase ' +
+ 'supplied, could not decrypt key'));
+ }
+ throw (e);
+ });
+ cipherStream.write(buf);
+ cipherStream.end();
+ while ((chunk = cipherStream.read()) !== null)
+ chunks.push(chunk);
+ buf = Buffer.concat(chunks);
+ }
+
+ /* The new OpenSSH internal format abuses PEM headers */
+ if (alg && alg.toLowerCase() === 'openssh')
+ return (sshpriv.readSSHPrivate(type, buf, options));
+ if (alg && alg.toLowerCase() === 'ssh2')
+ return (rfc4253.readType(type, buf, options));
+
+ var der = new asn1.BerReader(buf);
+ der.originalInput = input;
+
+ /*
+ * All of the PEM file types start with a sequence tag, so chop it
+ * off here
+ */
+ der.readSequence();
+
+ /* PKCS#1 type keys name an algorithm in the banner explicitly */
+ if (alg) {
+ if (forceType)
+ assert.strictEqual(forceType, 'pkcs1');
+ return (pkcs1.readPkcs1(alg, type, der));
+ } else {
+ if (forceType)
+ assert.strictEqual(forceType, 'pkcs8');
+ return (pkcs8.readPkcs8(alg, type, der));
+ }
+}
+
+function write(key, options, type) {
+ assert.object(key);
+
+ var alg = {'ecdsa': 'EC', 'rsa': 'RSA', 'dsa': 'DSA'}[key.type];
+ var header;
+
+ var der = new asn1.BerWriter();
+
+ if (PrivateKey.isPrivateKey(key)) {
+ if (type && type === 'pkcs8') {
+ header = 'PRIVATE KEY';
+ pkcs8.writePkcs8(der, key);
+ } else {
+ if (type)
+ assert.strictEqual(type, 'pkcs1');
+ header = alg + ' PRIVATE KEY';
+ pkcs1.writePkcs1(der, key);
+ }
+
+ } else if (Key.isKey(key)) {
+ if (type && type === 'pkcs1') {
+ header = alg + ' PUBLIC KEY';
+ pkcs1.writePkcs1(der, key);
+ } else {
+ if (type)
+ assert.strictEqual(type, 'pkcs8');
+ header = 'PUBLIC KEY';
+ pkcs8.writePkcs8(der, key);
+ }
+
+ } else {
+ throw (new Error('key is not a Key or PrivateKey'));
+ }
+
+ var tmp = der.buffer.toString('base64');
+ var len = tmp.length + (tmp.length / 64) +
+ 18 + 16 + header.length*2 + 10;
+ var buf = new Buffer(len);
+ var o = 0;
+ o += buf.write('-----BEGIN ' + header + '-----\n', o);
+ for (var i = 0; i < tmp.length; ) {
+ var limit = i + 64;
+ if (limit > tmp.length)
+ limit = tmp.length;
+ o += buf.write(tmp.slice(i, limit), o);
+ buf[o++] = 10;
+ i = limit;
+ }
+ o += buf.write('-----END ' + header + '-----\n', o);
+
+ return (buf.slice(0, o));
+}
diff --git a/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/pkcs1.js b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/pkcs1.js
new file mode 100644
index 00000000..a5676af6
--- /dev/null
+++ b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/pkcs1.js
@@ -0,0 +1,320 @@
+// Copyright 2015 Joyent, Inc.
+
+module.exports = {
+ read: read,
+ readPkcs1: readPkcs1,
+ write: write,
+ writePkcs1: writePkcs1
+};
+
+var assert = require('assert-plus');
+var asn1 = require('asn1');
+var algs = require('../algs');
+var utils = require('../utils');
+
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+var pem = require('./pem');
+
+var pkcs8 = require('./pkcs8');
+var readECDSACurve = pkcs8.readECDSACurve;
+
+function read(buf, options) {
+ return (pem.read(buf, options, 'pkcs1'));
+}
+
+function write(key, options) {
+ return (pem.write(key, options, 'pkcs1'));
+}
+
+/* Helper to read in a single mpint */
+function readMPInt(der, nm) {
+ assert.strictEqual(der.peek(), asn1.Ber.Integer,
+ nm + ' is not an Integer');
+ return (utils.mpNormalize(der.readString(asn1.Ber.Integer, true)));
+}
+
+function readPkcs1(alg, type, der) {
+ switch (alg) {
+ case 'RSA':
+ if (type === 'public')
+ return (readPkcs1RSAPublic(der));
+ else if (type === 'private')
+ return (readPkcs1RSAPrivate(der));
+ throw (new Error('Unknown key type: ' + type));
+ case 'DSA':
+ if (type === 'public')
+ return (readPkcs1DSAPublic(der));
+ else if (type === 'private')
+ return (readPkcs1DSAPrivate(der));
+ throw (new Error('Unknown key type: ' + type));
+ case 'EC':
+ case 'ECDSA':
+ if (type === 'private')
+ return (readPkcs1ECDSAPrivate(der));
+ else if (type === 'public')
+ return (readPkcs1ECDSAPublic(der));
+ throw (new Error('Unknown key type: ' + type));
+ default:
+ throw (new Error('Unknown key algo: ' + alg));
+ }
+}
+
+function readPkcs1RSAPublic(der) {
+ // modulus and exponent
+ var n = readMPInt(der, 'modulus');
+ var e = readMPInt(der, 'exponent');
+
+ // now, make the key
+ var key = {
+ type: 'rsa',
+ parts: [
+ { name: 'e', data: e },
+ { name: 'n', data: n }
+ ]
+ };
+
+ return (new Key(key));
+}
+
+function readPkcs1RSAPrivate(der) {
+ var version = readMPInt(der, 'version');
+ assert.strictEqual(version[0], 0);
+
+ // modulus then public exponent
+ var n = readMPInt(der, 'modulus');
+ var e = readMPInt(der, 'public exponent');
+ var d = readMPInt(der, 'private exponent');
+ var p = readMPInt(der, 'prime1');
+ var q = readMPInt(der, 'prime2');
+ var dmodp = readMPInt(der, 'exponent1');
+ var dmodq = readMPInt(der, 'exponent2');
+ var iqmp = readMPInt(der, 'iqmp');
+
+ // now, make the key
+ var key = {
+ type: 'rsa',
+ parts: [
+ { name: 'n', data: n },
+ { name: 'e', data: e },
+ { name: 'd', data: d },
+ { name: 'iqmp', data: iqmp },
+ { name: 'p', data: p },
+ { name: 'q', data: q },
+ { name: 'dmodp', data: dmodp },
+ { name: 'dmodq', data: dmodq }
+ ]
+ };
+
+ return (new PrivateKey(key));
+}
+
+function readPkcs1DSAPrivate(der) {
+ var version = readMPInt(der, 'version');
+ assert.strictEqual(version.readUInt8(0), 0);
+
+ var p = readMPInt(der, 'p');
+ var q = readMPInt(der, 'q');
+ var g = readMPInt(der, 'g');
+ var y = readMPInt(der, 'y');
+ var x = readMPInt(der, 'x');
+
+ // now, make the key
+ var key = {
+ type: 'dsa',
+ parts: [
+ { name: 'p', data: p },
+ { name: 'q', data: q },
+ { name: 'g', data: g },
+ { name: 'y', data: y },
+ { name: 'x', data: x }
+ ]
+ };
+
+ return (new PrivateKey(key));
+}
+
+function readPkcs1DSAPublic(der) {
+ var y = readMPInt(der, 'y');
+ var p = readMPInt(der, 'p');
+ var q = readMPInt(der, 'q');
+ var g = readMPInt(der, 'g');
+
+ var key = {
+ type: 'dsa',
+ parts: [
+ { name: 'y', data: y },
+ { name: 'p', data: p },
+ { name: 'q', data: q },
+ { name: 'g', data: g }
+ ]
+ };
+
+ return (new Key(key));
+}
+
+function readPkcs1ECDSAPublic(der) {
+ der.readSequence();
+
+ var oid = der.readOID();
+ assert.strictEqual(oid, '1.2.840.10045.2.1', 'must be ecPublicKey');
+
+ var curveOid = der.readOID();
+
+ var curve;
+ var curves = Object.keys(algs.curves);
+ for (var j = 0; j < curves.length; ++j) {
+ var c = curves[j];
+ var cd = algs.curves[c];
+ if (cd.pkcs8oid === curveOid) {
+ curve = c;
+ break;
+ }
+ }
+ assert.string(curve, 'a known ECDSA named curve');
+
+ var Q = der.readString(asn1.Ber.BitString, true);
+ Q = utils.ecNormalize(Q);
+
+ var key = {
+ type: 'ecdsa',
+ parts: [
+ { name: 'curve', data: new Buffer(curve) },
+ { name: 'Q', data: Q }
+ ]
+ };
+
+ return (new Key(key));
+}
+
+function readPkcs1ECDSAPrivate(der) {
+ var version = readMPInt(der, 'version');
+ assert.strictEqual(version.readUInt8(0), 1);
+
+ // private key
+ var d = der.readString(asn1.Ber.OctetString, true);
+
+ der.readSequence(0xa0);
+ var curve = readECDSACurve(der);
+ assert.string(curve, 'a known elliptic curve');
+
+ der.readSequence(0xa1);
+ var Q = der.readString(asn1.Ber.BitString, true);
+ Q = utils.ecNormalize(Q);
+
+ var key = {
+ type: 'ecdsa',
+ parts: [
+ { name: 'curve', data: new Buffer(curve) },
+ { name: 'Q', data: Q },
+ { name: 'd', data: d }
+ ]
+ };
+
+ return (new PrivateKey(key));
+}
+
+function writePkcs1(der, key) {
+ der.startSequence();
+
+ switch (key.type) {
+ case 'rsa':
+ if (PrivateKey.isPrivateKey(key))
+ writePkcs1RSAPrivate(der, key);
+ else
+ writePkcs1RSAPublic(der, key);
+ break;
+ case 'dsa':
+ if (PrivateKey.isPrivateKey(key))
+ writePkcs1DSAPrivate(der, key);
+ else
+ writePkcs1DSAPublic(der, key);
+ break;
+ case 'ecdsa':
+ if (PrivateKey.isPrivateKey(key))
+ writePkcs1ECDSAPrivate(der, key);
+ else
+ writePkcs1ECDSAPublic(der, key);
+ break;
+ default:
+ throw (new Error('Unknown key algo: ' + key.type));
+ }
+
+ der.endSequence();
+}
+
+function writePkcs1RSAPublic(der, key) {
+ der.writeBuffer(key.part.n.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.e.data, asn1.Ber.Integer);
+}
+
+function writePkcs1RSAPrivate(der, key) {
+ var ver = new Buffer(1);
+ ver[0] = 0;
+ der.writeBuffer(ver, asn1.Ber.Integer);
+
+ der.writeBuffer(key.part.n.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.e.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.d.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.q.data, asn1.Ber.Integer);
+ if (!key.part.dmodp || !key.part.dmodq)
+ utils.addRSAMissing(key);
+ der.writeBuffer(key.part.dmodp.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.dmodq.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.iqmp.data, asn1.Ber.Integer);
+}
+
+function writePkcs1DSAPrivate(der, key) {
+ var ver = new Buffer(1);
+ ver[0] = 0;
+ der.writeBuffer(ver, asn1.Ber.Integer);
+
+ der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.q.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.g.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.y.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.x.data, asn1.Ber.Integer);
+}
+
+function writePkcs1DSAPublic(der, key) {
+ der.writeBuffer(key.part.y.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.q.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.g.data, asn1.Ber.Integer);
+}
+
+function writePkcs1ECDSAPublic(der, key) {
+ der.startSequence();
+
+ der.writeOID('1.2.840.10045.2.1'); /* ecPublicKey */
+ var curve = key.part.curve.data.toString();
+ var curveOid = algs.curves[curve].pkcs8oid;
+ assert.string(curveOid, 'a known ECDSA named curve');
+ der.writeOID(curveOid);
+
+ der.endSequence();
+
+ var Q = utils.ecNormalize(key.part.Q.data, true);
+ der.writeBuffer(Q, asn1.Ber.BitString);
+}
+
+function writePkcs1ECDSAPrivate(der, key) {
+ var ver = new Buffer(1);
+ ver[0] = 1;
+ der.writeBuffer(ver, asn1.Ber.Integer);
+
+ der.writeBuffer(key.part.d.data, asn1.Ber.OctetString);
+
+ der.startSequence(0xa0);
+ var curve = key.part.curve.data.toString();
+ var curveOid = algs.curves[curve].pkcs8oid;
+ assert.string(curveOid, 'a known ECDSA named curve');
+ der.writeOID(curveOid);
+ der.endSequence();
+
+ der.startSequence(0xa1);
+ var Q = utils.ecNormalize(key.part.Q.data, true);
+ der.writeBuffer(Q, asn1.Ber.BitString);
+ der.endSequence();
+}
diff --git a/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/pkcs8.js b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/pkcs8.js
new file mode 100644
index 00000000..4ccbefcb
--- /dev/null
+++ b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/pkcs8.js
@@ -0,0 +1,505 @@
+// Copyright 2015 Joyent, Inc.
+
+module.exports = {
+ read: read,
+ readPkcs8: readPkcs8,
+ write: write,
+ writePkcs8: writePkcs8,
+
+ readECDSACurve: readECDSACurve,
+ writeECDSACurve: writeECDSACurve
+};
+
+var assert = require('assert-plus');
+var asn1 = require('asn1');
+var algs = require('../algs');
+var utils = require('../utils');
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+var pem = require('./pem');
+
+function read(buf, options) {
+ return (pem.read(buf, options, 'pkcs8'));
+}
+
+function write(key, options) {
+ return (pem.write(key, options, 'pkcs8'));
+}
+
+/* Helper to read in a single mpint */
+function readMPInt(der, nm) {
+ assert.strictEqual(der.peek(), asn1.Ber.Integer,
+ nm + ' is not an Integer');
+ return (utils.mpNormalize(der.readString(asn1.Ber.Integer, true)));
+}
+
+function readPkcs8(alg, type, der) {
+ /* Private keys in pkcs#8 format have a weird extra int */
+ if (der.peek() === asn1.Ber.Integer) {
+ assert.strictEqual(type, 'private',
+ 'unexpected Integer at start of public key');
+ der.readString(asn1.Ber.Integer, true);
+ }
+
+ der.readSequence();
+ var next = der.offset + der.length;
+
+ var oid = der.readOID();
+ switch (oid) {
+ case '1.2.840.113549.1.1.1':
+ der._offset = next;
+ if (type === 'public')
+ return (readPkcs8RSAPublic(der));
+ else
+ return (readPkcs8RSAPrivate(der));
+ case '1.2.840.10040.4.1':
+ if (type === 'public')
+ return (readPkcs8DSAPublic(der));
+ else
+ return (readPkcs8DSAPrivate(der));
+ case '1.2.840.10045.2.1':
+ if (type === 'public')
+ return (readPkcs8ECDSAPublic(der));
+ else
+ return (readPkcs8ECDSAPrivate(der));
+ default:
+ throw (new Error('Unknown key type OID ' + oid));
+ }
+}
+
+function readPkcs8RSAPublic(der) {
+ // bit string sequence
+ der.readSequence(asn1.Ber.BitString);
+ der.readByte();
+ der.readSequence();
+
+ // modulus
+ var n = readMPInt(der, 'modulus');
+ var e = readMPInt(der, 'exponent');
+
+ // now, make the key
+ var key = {
+ type: 'rsa',
+ source: der.originalInput,
+ parts: [
+ { name: 'e', data: e },
+ { name: 'n', data: n }
+ ]
+ };
+
+ return (new Key(key));
+}
+
+function readPkcs8RSAPrivate(der) {
+ der.readSequence(asn1.Ber.OctetString);
+ der.readSequence();
+
+ var ver = readMPInt(der, 'version');
+ assert.equal(ver[0], 0x0, 'unknown RSA private key version');
+
+ // modulus then public exponent
+ var n = readMPInt(der, 'modulus');
+ var e = readMPInt(der, 'public exponent');
+ var d = readMPInt(der, 'private exponent');
+ var p = readMPInt(der, 'prime1');
+ var q = readMPInt(der, 'prime2');
+ var dmodp = readMPInt(der, 'exponent1');
+ var dmodq = readMPInt(der, 'exponent2');
+ var iqmp = readMPInt(der, 'iqmp');
+
+ // now, make the key
+ var key = {
+ type: 'rsa',
+ parts: [
+ { name: 'n', data: n },
+ { name: 'e', data: e },
+ { name: 'd', data: d },
+ { name: 'iqmp', data: iqmp },
+ { name: 'p', data: p },
+ { name: 'q', data: q },
+ { name: 'dmodp', data: dmodp },
+ { name: 'dmodq', data: dmodq }
+ ]
+ };
+
+ return (new PrivateKey(key));
+}
+
+function readPkcs8DSAPublic(der) {
+ der.readSequence();
+
+ var p = readMPInt(der, 'p');
+ var q = readMPInt(der, 'q');
+ var g = readMPInt(der, 'g');
+
+ // bit string sequence
+ der.readSequence(asn1.Ber.BitString);
+ der.readByte();
+
+ var y = readMPInt(der, 'y');
+
+ // now, make the key
+ var key = {
+ type: 'dsa',
+ parts: [
+ { name: 'p', data: p },
+ { name: 'q', data: q },
+ { name: 'g', data: g },
+ { name: 'y', data: y }
+ ]
+ };
+
+ return (new Key(key));
+}
+
+function readPkcs8DSAPrivate(der) {
+ der.readSequence();
+
+ var p = readMPInt(der, 'p');
+ var q = readMPInt(der, 'q');
+ var g = readMPInt(der, 'g');
+
+ der.readSequence(asn1.Ber.OctetString);
+ var x = readMPInt(der, 'x');
+
+ /* The pkcs#8 format does not include the public key */
+ var y = utils.calculateDSAPublic(g, p, x);
+
+ var key = {
+ type: 'dsa',
+ parts: [
+ { name: 'p', data: p },
+ { name: 'q', data: q },
+ { name: 'g', data: g },
+ { name: 'y', data: y },
+ { name: 'x', data: x }
+ ]
+ };
+
+ return (new PrivateKey(key));
+}
+
+function readECDSACurve(der) {
+ var curveName, curveNames;
+ var j, c, cd;
+
+ if (der.peek() === asn1.Ber.OID) {
+ var oid = der.readOID();
+
+ curveNames = Object.keys(algs.curves);
+ for (j = 0; j < curveNames.length; ++j) {
+ c = curveNames[j];
+ cd = algs.curves[c];
+ if (cd.pkcs8oid === oid) {
+ curveName = c;
+ break;
+ }
+ }
+
+ } else {
+ // ECParameters sequence
+ der.readSequence();
+ var version = der.readString(asn1.Ber.Integer, true);
+ assert.strictEqual(version[0], 1, 'ECDSA key not version 1');
+
+ var curve = {};
+
+ // FieldID sequence
+ der.readSequence();
+ var fieldTypeOid = der.readOID();
+ assert.strictEqual(fieldTypeOid, '1.2.840.10045.1.1',
+ 'ECDSA key is not from a prime-field');
+ var p = curve.p = utils.mpNormalize(
+ der.readString(asn1.Ber.Integer, true));
+ /*
+ * p always starts with a 1 bit, so count the zeros to get its
+ * real size.
+ */
+ curve.size = p.length * 8 - utils.countZeros(p);
+
+ // Curve sequence
+ der.readSequence();
+ curve.a = utils.mpNormalize(
+ der.readString(asn1.Ber.OctetString, true));
+ curve.b = utils.mpNormalize(
+ der.readString(asn1.Ber.OctetString, true));
+ if (der.peek() === asn1.Ber.BitString)
+ curve.s = der.readString(asn1.Ber.BitString, true);
+
+ // Combined Gx and Gy
+ curve.G = der.readString(asn1.Ber.OctetString, true);
+ assert.strictEqual(curve.G[0], 0x4,
+ 'uncompressed G is required');
+
+ curve.n = utils.mpNormalize(
+ der.readString(asn1.Ber.Integer, true));
+ curve.h = utils.mpNormalize(
+ der.readString(asn1.Ber.Integer, true));
+ assert.strictEqual(curve.h[0], 0x1, 'a cofactor=1 curve is ' +
+ 'required');
+
+ curveNames = Object.keys(algs.curves);
+ var ks = Object.keys(curve);
+ for (j = 0; j < curveNames.length; ++j) {
+ c = curveNames[j];
+ cd = algs.curves[c];
+ var equal = true;
+ for (var i = 0; i < ks.length; ++i) {
+ var k = ks[i];
+ if (cd[k] === undefined)
+ continue;
+ if (typeof (cd[k]) === 'object' &&
+ cd[k].equals !== undefined) {
+ if (!cd[k].equals(curve[k])) {
+ equal = false;
+ break;
+ }
+ } else if (Buffer.isBuffer(cd[k])) {
+ if (cd[k].toString('binary')
+ !== curve[k].toString('binary')) {
+ equal = false;
+ break;
+ }
+ } else {
+ if (cd[k] !== curve[k]) {
+ equal = false;
+ break;
+ }
+ }
+ }
+ if (equal) {
+ curveName = c;
+ break;
+ }
+ }
+ }
+ return (curveName);
+}
+
+function readPkcs8ECDSAPrivate(der) {
+ var curveName = readECDSACurve(der);
+ assert.string(curveName, 'a known elliptic curve');
+
+ der.readSequence(asn1.Ber.OctetString);
+ der.readSequence();
+
+ var version = readMPInt(der, 'version');
+ assert.equal(version[0], 1, 'unknown version of ECDSA key');
+
+ var d = der.readString(asn1.Ber.OctetString, true);
+ der.readSequence(0xa1);
+
+ var Q = der.readString(asn1.Ber.BitString, true);
+ Q = utils.ecNormalize(Q);
+
+ var key = {
+ type: 'ecdsa',
+ parts: [
+ { name: 'curve', data: new Buffer(curveName) },
+ { name: 'Q', data: Q },
+ { name: 'd', data: d }
+ ]
+ };
+
+ return (new PrivateKey(key));
+}
+
+function readPkcs8ECDSAPublic(der) {
+ var curveName = readECDSACurve(der);
+ assert.string(curveName, 'a known elliptic curve');
+
+ var Q = der.readString(asn1.Ber.BitString, true);
+ Q = utils.ecNormalize(Q);
+
+ var key = {
+ type: 'ecdsa',
+ parts: [
+ { name: 'curve', data: new Buffer(curveName) },
+ { name: 'Q', data: Q }
+ ]
+ };
+
+ return (new Key(key));
+}
+
+function writePkcs8(der, key) {
+ der.startSequence();
+
+ if (PrivateKey.isPrivateKey(key)) {
+ var sillyInt = new Buffer(1);
+ sillyInt[0] = 0x0;
+ der.writeBuffer(sillyInt, asn1.Ber.Integer);
+ }
+
+ der.startSequence();
+ switch (key.type) {
+ case 'rsa':
+ der.writeOID('1.2.840.113549.1.1.1');
+ if (PrivateKey.isPrivateKey(key))
+ writePkcs8RSAPrivate(key, der);
+ else
+ writePkcs8RSAPublic(key, der);
+ break;
+ case 'dsa':
+ der.writeOID('1.2.840.10040.4.1');
+ if (PrivateKey.isPrivateKey(key))
+ writePkcs8DSAPrivate(key, der);
+ else
+ writePkcs8DSAPublic(key, der);
+ break;
+ case 'ecdsa':
+ der.writeOID('1.2.840.10045.2.1');
+ if (PrivateKey.isPrivateKey(key))
+ writePkcs8ECDSAPrivate(key, der);
+ else
+ writePkcs8ECDSAPublic(key, der);
+ break;
+ default:
+ throw (new Error('Unsupported key type: ' + key.type));
+ }
+
+ der.endSequence();
+}
+
+function writePkcs8RSAPrivate(key, der) {
+ der.writeNull();
+ der.endSequence();
+
+ der.startSequence(asn1.Ber.OctetString);
+ der.startSequence();
+
+ var version = new Buffer(1);
+ version[0] = 0;
+ der.writeBuffer(version, asn1.Ber.Integer);
+
+ der.writeBuffer(key.part.n.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.e.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.d.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.q.data, asn1.Ber.Integer);
+ if (!key.part.dmodp || !key.part.dmodq)
+ utils.addRSAMissing(key);
+ der.writeBuffer(key.part.dmodp.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.dmodq.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.iqmp.data, asn1.Ber.Integer);
+
+ der.endSequence();
+ der.endSequence();
+}
+
+function writePkcs8RSAPublic(key, der) {
+ der.writeNull();
+ der.endSequence();
+
+ der.startSequence(asn1.Ber.BitString);
+ der.writeByte(0x00);
+
+ der.startSequence();
+ der.writeBuffer(key.part.n.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.e.data, asn1.Ber.Integer);
+ der.endSequence();
+
+ der.endSequence();
+}
+
+function writePkcs8DSAPrivate(key, der) {
+ der.startSequence();
+ der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.q.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.g.data, asn1.Ber.Integer);
+ der.endSequence();
+
+ der.endSequence();
+
+ der.startSequence(asn1.Ber.OctetString);
+ der.writeBuffer(key.part.x.data, asn1.Ber.Integer);
+ der.endSequence();
+}
+
+function writePkcs8DSAPublic(key, der) {
+ der.startSequence();
+ der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.q.data, asn1.Ber.Integer);
+ der.writeBuffer(key.part.g.data, asn1.Ber.Integer);
+ der.endSequence();
+ der.endSequence();
+
+ der.startSequence(asn1.Ber.BitString);
+ der.writeByte(0x00);
+ der.writeBuffer(key.part.y.data, asn1.Ber.Integer);
+ der.endSequence();
+}
+
+function writeECDSACurve(key, der) {
+ var curve = algs.curves[key.curve];
+ if (curve.pkcs8oid) {
+ /* This one has a name in pkcs#8, so just write the oid */
+ der.writeOID(curve.pkcs8oid);
+
+ } else {
+ // ECParameters sequence
+ der.startSequence();
+
+ var version = new Buffer(1);
+ version.writeUInt8(1, 0);
+ der.writeBuffer(version, asn1.Ber.Integer);
+
+ // FieldID sequence
+ der.startSequence();
+ der.writeOID('1.2.840.10045.1.1'); // prime-field
+ der.writeBuffer(curve.p, asn1.Ber.Integer);
+ der.endSequence();
+
+ // Curve sequence
+ der.startSequence();
+ var a = curve.p;
+ if (a[0] === 0x0)
+ a = a.slice(1);
+ der.writeBuffer(a, asn1.Ber.OctetString);
+ der.writeBuffer(curve.b, asn1.Ber.OctetString);
+ der.writeBuffer(curve.s, asn1.Ber.BitString);
+ der.endSequence();
+
+ der.writeBuffer(curve.G, asn1.Ber.OctetString);
+ der.writeBuffer(curve.n, asn1.Ber.Integer);
+ var h = curve.h;
+ if (!h) {
+ h = new Buffer(1);
+ h[0] = 1;
+ }
+ der.writeBuffer(h, asn1.Ber.Integer);
+
+ // ECParameters
+ der.endSequence();
+ }
+}
+
+function writePkcs8ECDSAPublic(key, der) {
+ writeECDSACurve(key, der);
+ der.endSequence();
+
+ var Q = utils.ecNormalize(key.part.Q.data, true);
+ der.writeBuffer(Q, asn1.Ber.BitString);
+}
+
+function writePkcs8ECDSAPrivate(key, der) {
+ writeECDSACurve(key, der);
+ der.endSequence();
+
+ der.startSequence(asn1.Ber.OctetString);
+ der.startSequence();
+
+ var version = new Buffer(1);
+ version[0] = 1;
+ der.writeBuffer(version, asn1.Ber.Integer);
+
+ der.writeBuffer(key.part.d.data, asn1.Ber.OctetString);
+
+ der.startSequence(0xa1);
+ var Q = utils.ecNormalize(key.part.Q.data, true);
+ der.writeBuffer(Q, asn1.Ber.BitString);
+ der.endSequence();
+
+ der.endSequence();
+ der.endSequence();
+}
diff --git a/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/rfc4253.js b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/rfc4253.js
new file mode 100644
index 00000000..9d436dd9
--- /dev/null
+++ b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/rfc4253.js
@@ -0,0 +1,146 @@
+// Copyright 2015 Joyent, Inc.
+
+module.exports = {
+ read: read.bind(undefined, false, undefined),
+ readType: read.bind(undefined, false),
+ write: write,
+ /* semi-private api, used by sshpk-agent */
+ readPartial: read.bind(undefined, true),
+
+ /* shared with ssh format */
+ readInternal: read,
+ keyTypeToAlg: keyTypeToAlg,
+ algToKeyType: algToKeyType
+};
+
+var assert = require('assert-plus');
+var algs = require('../algs');
+var utils = require('../utils');
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+var SSHBuffer = require('../ssh-buffer');
+
+function algToKeyType(alg) {
+ assert.string(alg);
+ if (alg === 'ssh-dss')
+ return ('dsa');
+ else if (alg === 'ssh-rsa')
+ return ('rsa');
+ else if (alg === 'ssh-ed25519')
+ return ('ed25519');
+ else if (alg === 'ssh-curve25519')
+ return ('curve25519');
+ else if (alg.match(/^ecdsa-sha2-/))
+ return ('ecdsa');
+ else
+ throw (new Error('Unknown algorithm ' + alg));
+}
+
+function keyTypeToAlg(key) {
+ assert.object(key);
+ if (key.type === 'dsa')
+ return ('ssh-dss');
+ else if (key.type === 'rsa')
+ return ('ssh-rsa');
+ else if (key.type === 'ed25519')
+ return ('ssh-ed25519');
+ else if (key.type === 'curve25519')
+ return ('ssh-curve25519');
+ else if (key.type === 'ecdsa')
+ return ('ecdsa-sha2-' + key.part.curve.data.toString());
+ else
+ throw (new Error('Unknown key type ' + key.type));
+}
+
+function read(partial, type, buf, options) {
+ if (typeof (buf) === 'string')
+ buf = new Buffer(buf);
+ assert.buffer(buf, 'buf');
+
+ var key = {};
+
+ var parts = key.parts = [];
+ var sshbuf = new SSHBuffer({buffer: buf});
+
+ var alg = sshbuf.readString();
+ assert.ok(!sshbuf.atEnd(), 'key must have at least one part');
+
+ key.type = algToKeyType(alg);
+
+ var partCount = algs.info[key.type].parts.length;
+ if (type && type === 'private')
+ partCount = algs.privInfo[key.type].parts.length;
+
+ while (!sshbuf.atEnd() && parts.length < partCount)
+ parts.push(sshbuf.readPart());
+ while (!partial && !sshbuf.atEnd())
+ parts.push(sshbuf.readPart());
+
+ assert.ok(parts.length >= 1,
+ 'key must have at least one part');
+ assert.ok(partial || sshbuf.atEnd(),
+ 'leftover bytes at end of key');
+
+ var Constructor = Key;
+ var algInfo = algs.info[key.type];
+ if (type === 'private' || algInfo.parts.length !== parts.length) {
+ algInfo = algs.privInfo[key.type];
+ Constructor = PrivateKey;
+ }
+ assert.strictEqual(algInfo.parts.length, parts.length);
+
+ if (key.type === 'ecdsa') {
+ var res = /^ecdsa-sha2-(.+)$/.exec(alg);
+ assert.ok(res !== null);
+ assert.strictEqual(res[1], parts[0].data.toString());
+ }
+
+ var normalized = true;
+ for (var i = 0; i < algInfo.parts.length; ++i) {
+ parts[i].name = algInfo.parts[i];
+ if (parts[i].name !== 'curve' &&
+ algInfo.normalize !== false) {
+ var p = parts[i];
+ var nd = utils.mpNormalize(p.data);
+ if (nd !== p.data) {
+ p.data = nd;
+ normalized = false;
+ }
+ }
+ }
+
+ if (normalized)
+ key._rfc4253Cache = sshbuf.toBuffer();
+
+ if (partial && typeof (partial) === 'object') {
+ partial.remainder = sshbuf.remainder();
+ partial.consumed = sshbuf._offset;
+ }
+
+ return (new Constructor(key));
+}
+
+function write(key, options) {
+ assert.object(key);
+
+ var alg = keyTypeToAlg(key);
+ var i;
+
+ var algInfo = algs.info[key.type];
+ if (PrivateKey.isPrivateKey(key))
+ algInfo = algs.privInfo[key.type];
+ var parts = algInfo.parts;
+
+ var buf = new SSHBuffer({});
+
+ buf.writeString(alg);
+
+ for (i = 0; i < parts.length; ++i) {
+ var data = key.part[parts[i]].data;
+ if (algInfo.normalize !== false)
+ data = utils.mpNormalize(data);
+ buf.writeBuffer(data);
+ }
+
+ return (buf.toBuffer());
+}
diff --git a/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/ssh-private.js b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/ssh-private.js
new file mode 100644
index 00000000..2fcf7199
--- /dev/null
+++ b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/ssh-private.js
@@ -0,0 +1,261 @@
+// Copyright 2015 Joyent, Inc.
+
+module.exports = {
+ read: read,
+ readSSHPrivate: readSSHPrivate,
+ write: write
+};
+
+var assert = require('assert-plus');
+var asn1 = require('asn1');
+var algs = require('../algs');
+var utils = require('../utils');
+var crypto = require('crypto');
+
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+var pem = require('./pem');
+var rfc4253 = require('./rfc4253');
+var SSHBuffer = require('../ssh-buffer');
+var errors = require('../errors');
+
+var bcrypt;
+
+function read(buf, options) {
+ return (pem.read(buf, options));
+}
+
+var MAGIC = 'openssh-key-v1';
+
+function readSSHPrivate(type, buf, options) {
+ buf = new SSHBuffer({buffer: buf});
+
+ var magic = buf.readCString();
+ assert.strictEqual(magic, MAGIC, 'bad magic string');
+
+ var cipher = buf.readString();
+ var kdf = buf.readString();
+ var kdfOpts = buf.readBuffer();
+
+ var nkeys = buf.readInt();
+ if (nkeys !== 1) {
+ throw (new Error('OpenSSH-format key file contains ' +
+ 'multiple keys: this is unsupported.'));
+ }
+
+ var pubKey = buf.readBuffer();
+
+ if (type === 'public') {
+ assert.ok(buf.atEnd(), 'excess bytes left after key');
+ return (rfc4253.read(pubKey));
+ }
+
+ var privKeyBlob = buf.readBuffer();
+ assert.ok(buf.atEnd(), 'excess bytes left after key');
+
+ var kdfOptsBuf = new SSHBuffer({ buffer: kdfOpts });
+ switch (kdf) {
+ case 'none':
+ if (cipher !== 'none') {
+ throw (new Error('OpenSSH-format key uses KDF "none" ' +
+ 'but specifies a cipher other than "none"'));
+ }
+ break;
+ case 'bcrypt':
+ var salt = kdfOptsBuf.readBuffer();
+ var rounds = kdfOptsBuf.readInt();
+ var cinf = utils.opensshCipherInfo(cipher);
+ if (bcrypt === undefined) {
+ bcrypt = require('bcrypt-pbkdf');
+ }
+
+ if (typeof (options.passphrase) === 'string') {
+ options.passphrase = new Buffer(options.passphrase,
+ 'utf-8');
+ }
+ if (!Buffer.isBuffer(options.passphrase)) {
+ throw (new errors.KeyEncryptedError(
+ options.filename, 'OpenSSH'));
+ }
+
+ var pass = new Uint8Array(options.passphrase);
+ var salti = new Uint8Array(salt);
+ /* Use the pbkdf to derive both the key and the IV. */
+ var out = new Uint8Array(cinf.keySize + cinf.blockSize);
+ var res = bcrypt.pbkdf(pass, pass.length, salti, salti.length,
+ out, out.length, rounds);
+ if (res !== 0) {
+ throw (new Error('bcrypt_pbkdf function returned ' +
+ 'failure, parameters invalid'));
+ }
+ out = new Buffer(out);
+ var ckey = out.slice(0, cinf.keySize);
+ var iv = out.slice(cinf.keySize, cinf.keySize + cinf.blockSize);
+ var cipherStream = crypto.createDecipheriv(cinf.opensslName,
+ ckey, iv);
+ cipherStream.setAutoPadding(false);
+ var chunk, chunks = [];
+ cipherStream.once('error', function (e) {
+ if (e.toString().indexOf('bad decrypt') !== -1) {
+ throw (new Error('Incorrect passphrase ' +
+ 'supplied, could not decrypt key'));
+ }
+ throw (e);
+ });
+ cipherStream.write(privKeyBlob);
+ cipherStream.end();
+ while ((chunk = cipherStream.read()) !== null)
+ chunks.push(chunk);
+ privKeyBlob = Buffer.concat(chunks);
+ break;
+ default:
+ throw (new Error(
+ 'OpenSSH-format key uses unknown KDF "' + kdf + '"'));
+ }
+
+ buf = new SSHBuffer({buffer: privKeyBlob});
+
+ var checkInt1 = buf.readInt();
+ var checkInt2 = buf.readInt();
+ if (checkInt1 !== checkInt2) {
+ throw (new Error('Incorrect passphrase supplied, could not ' +
+ 'decrypt key'));
+ }
+
+ var ret = {};
+ var key = rfc4253.readInternal(ret, 'private', buf.remainder());
+
+ buf.skip(ret.consumed);
+
+ var comment = buf.readString();
+ key.comment = comment;
+
+ return (key);
+}
+
+function write(key, options) {
+ var pubKey;
+ if (PrivateKey.isPrivateKey(key))
+ pubKey = key.toPublic();
+ else
+ pubKey = key;
+
+ var cipher = 'none';
+ var kdf = 'none';
+ var kdfopts = new Buffer(0);
+ var cinf = { blockSize: 8 };
+ var passphrase;
+ if (options !== undefined) {
+ passphrase = options.passphrase;
+ if (typeof (passphrase) === 'string')
+ passphrase = new Buffer(passphrase, 'utf-8');
+ if (passphrase !== undefined) {
+ assert.buffer(passphrase, 'options.passphrase');
+ assert.optionalString(options.cipher, 'options.cipher');
+ cipher = options.cipher;
+ if (cipher === undefined)
+ cipher = 'aes128-ctr';
+ cinf = utils.opensshCipherInfo(cipher);
+ kdf = 'bcrypt';
+ }
+ }
+
+ var privBuf;
+ if (PrivateKey.isPrivateKey(key)) {
+ privBuf = new SSHBuffer({});
+ var checkInt = crypto.randomBytes(4).readUInt32BE(0);
+ privBuf.writeInt(checkInt);
+ privBuf.writeInt(checkInt);
+ privBuf.write(key.toBuffer('rfc4253'));
+ privBuf.writeString(key.comment || '');
+
+ var n = 1;
+ while (privBuf._offset % cinf.blockSize !== 0)
+ privBuf.writeChar(n++);
+ privBuf = privBuf.toBuffer();
+ }
+
+ switch (kdf) {
+ case 'none':
+ break;
+ case 'bcrypt':
+ var salt = crypto.randomBytes(16);
+ var rounds = 16;
+ var kdfssh = new SSHBuffer({});
+ kdfssh.writeBuffer(salt);
+ kdfssh.writeInt(rounds);
+ kdfopts = kdfssh.toBuffer();
+
+ if (bcrypt === undefined) {
+ bcrypt = require('bcrypt-pbkdf');
+ }
+ var pass = new Uint8Array(passphrase);
+ var salti = new Uint8Array(salt);
+ /* Use the pbkdf to derive both the key and the IV. */
+ var out = new Uint8Array(cinf.keySize + cinf.blockSize);
+ var res = bcrypt.pbkdf(pass, pass.length, salti, salti.length,
+ out, out.length, rounds);
+ if (res !== 0) {
+ throw (new Error('bcrypt_pbkdf function returned ' +
+ 'failure, parameters invalid'));
+ }
+ out = new Buffer(out);
+ var ckey = out.slice(0, cinf.keySize);
+ var iv = out.slice(cinf.keySize, cinf.keySize + cinf.blockSize);
+
+ var cipherStream = crypto.createCipheriv(cinf.opensslName,
+ ckey, iv);
+ cipherStream.setAutoPadding(false);
+ var chunk, chunks = [];
+ cipherStream.once('error', function (e) {
+ throw (e);
+ });
+ cipherStream.write(privBuf);
+ cipherStream.end();
+ while ((chunk = cipherStream.read()) !== null)
+ chunks.push(chunk);
+ privBuf = Buffer.concat(chunks);
+ break;
+ default:
+ throw (new Error('Unsupported kdf ' + kdf));
+ }
+
+ var buf = new SSHBuffer({});
+
+ buf.writeCString(MAGIC);
+ buf.writeString(cipher); /* cipher */
+ buf.writeString(kdf); /* kdf */
+ buf.writeBuffer(kdfopts); /* kdfoptions */
+
+ buf.writeInt(1); /* nkeys */
+ buf.writeBuffer(pubKey.toBuffer('rfc4253'));
+
+ if (privBuf)
+ buf.writeBuffer(privBuf);
+
+ buf = buf.toBuffer();
+
+ var header;
+ if (PrivateKey.isPrivateKey(key))
+ header = 'OPENSSH PRIVATE KEY';
+ else
+ header = 'OPENSSH PUBLIC KEY';
+
+ var tmp = buf.toString('base64');
+ var len = tmp.length + (tmp.length / 70) +
+ 18 + 16 + header.length*2 + 10;
+ buf = new Buffer(len);
+ var o = 0;
+ o += buf.write('-----BEGIN ' + header + '-----\n', o);
+ for (var i = 0; i < tmp.length; ) {
+ var limit = i + 70;
+ if (limit > tmp.length)
+ limit = tmp.length;
+ o += buf.write(tmp.slice(i, limit), o);
+ buf[o++] = 10;
+ i = limit;
+ }
+ o += buf.write('-----END ' + header + '-----\n', o);
+
+ return (buf.slice(0, o));
+}
diff --git a/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/ssh.js b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/ssh.js
new file mode 100644
index 00000000..655c9eaf
--- /dev/null
+++ b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/ssh.js
@@ -0,0 +1,114 @@
+// Copyright 2015 Joyent, Inc.
+
+module.exports = {
+ read: read,
+ write: write
+};
+
+var assert = require('assert-plus');
+var rfc4253 = require('./rfc4253');
+var utils = require('../utils');
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+
+var sshpriv = require('./ssh-private');
+
+/*JSSTYLED*/
+var SSHKEY_RE = /^([a-z0-9-]+)[ \t]+([a-zA-Z0-9+\/]+[=]*)([\n \t]+([^\n]+))?$/;
+/*JSSTYLED*/
+var SSHKEY_RE2 = /^([a-z0-9-]+)[ \t]+([a-zA-Z0-9+\/ \t\n]+[=]*)(.*)$/;
+
+function read(buf, options) {
+ if (typeof (buf) !== 'string') {
+ assert.buffer(buf, 'buf');
+ buf = buf.toString('ascii');
+ }
+
+ var trimmed = buf.trim().replace(/[\\\r]/g, '');
+ var m = trimmed.match(SSHKEY_RE);
+ if (!m)
+ m = trimmed.match(SSHKEY_RE2);
+ assert.ok(m, 'key must match regex');
+
+ var type = rfc4253.algToKeyType(m[1]);
+ var kbuf = new Buffer(m[2], 'base64');
+
+ /*
+ * This is a bit tricky. If we managed to parse the key and locate the
+ * key comment with the regex, then do a non-partial read and assert
+ * that we have consumed all bytes. If we couldn't locate the key
+ * comment, though, there may be whitespace shenanigans going on that
+ * have conjoined the comment to the rest of the key. We do a partial
+ * read in this case to try to make the best out of a sorry situation.
+ */
+ var key;
+ var ret = {};
+ if (m[4]) {
+ try {
+ key = rfc4253.read(kbuf);
+
+ } catch (e) {
+ m = trimmed.match(SSHKEY_RE2);
+ assert.ok(m, 'key must match regex');
+ kbuf = new Buffer(m[2], 'base64');
+ key = rfc4253.readInternal(ret, 'public', kbuf);
+ }
+ } else {
+ key = rfc4253.readInternal(ret, 'public', kbuf);
+ }
+
+ assert.strictEqual(type, key.type);
+
+ if (m[4] && m[4].length > 0) {
+ key.comment = m[4];
+
+ } else if (ret.consumed) {
+ /*
+ * Now the magic: trying to recover the key comment when it's
+ * gotten conjoined to the key or otherwise shenanigan'd.
+ *
+ * Work out how much base64 we used, then drop all non-base64
+ * chars from the beginning up to this point in the the string.
+ * Then offset in this and try to make up for missing = chars.
+ */
+ var data = m[2] + m[3];
+ var realOffset = Math.ceil(ret.consumed / 3) * 4;
+ data = data.slice(0, realOffset - 2). /*JSSTYLED*/
+ replace(/[^a-zA-Z0-9+\/=]/g, '') +
+ data.slice(realOffset - 2);
+
+ var padding = ret.consumed % 3;
+ if (padding > 0 &&
+ data.slice(realOffset - 1, realOffset) !== '=')
+ realOffset--;
+ while (data.slice(realOffset, realOffset + 1) === '=')
+ realOffset++;
+
+ /* Finally, grab what we think is the comment & clean it up. */
+ var trailer = data.slice(realOffset);
+ trailer = trailer.replace(/[\r\n]/g, ' ').
+ replace(/^\s+/, '');
+ if (trailer.match(/^[a-zA-Z0-9]/))
+ key.comment = trailer;
+ }
+
+ return (key);
+}
+
+function write(key, options) {
+ assert.object(key);
+ if (!Key.isKey(key))
+ throw (new Error('Must be a public key'));
+
+ var parts = [];
+ var alg = rfc4253.keyTypeToAlg(key);
+ parts.push(alg);
+
+ var buf = rfc4253.write(key);
+ parts.push(buf.toString('base64'));
+
+ if (key.comment)
+ parts.push(key.comment);
+
+ return (new Buffer(parts.join(' ')));
+}
diff --git a/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/x509-pem.js b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/x509-pem.js
new file mode 100644
index 00000000..c59c7d5f
--- /dev/null
+++ b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/x509-pem.js
@@ -0,0 +1,77 @@
+// Copyright 2016 Joyent, Inc.
+
+var x509 = require('./x509');
+
+module.exports = {
+ read: read,
+ verify: x509.verify,
+ sign: x509.sign,
+ write: write
+};
+
+var assert = require('assert-plus');
+var asn1 = require('asn1');
+var algs = require('../algs');
+var utils = require('../utils');
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+var pem = require('./pem');
+var Identity = require('../identity');
+var Signature = require('../signature');
+var Certificate = require('../certificate');
+
+function read(buf, options) {
+ if (typeof (buf) !== 'string') {
+ assert.buffer(buf, 'buf');
+ buf = buf.toString('ascii');
+ }
+
+ var lines = buf.trim().split(/[\r\n]+/g);
+
+ var m = lines[0].match(/*JSSTYLED*/
+ /[-]+[ ]*BEGIN CERTIFICATE[ ]*[-]+/);
+ assert.ok(m, 'invalid PEM header');
+
+ var m2 = lines[lines.length - 1].match(/*JSSTYLED*/
+ /[-]+[ ]*END CERTIFICATE[ ]*[-]+/);
+ assert.ok(m2, 'invalid PEM footer');
+
+ var headers = {};
+ while (true) {
+ lines = lines.slice(1);
+ m = lines[0].match(/*JSSTYLED*/
+ /^([A-Za-z0-9-]+): (.+)$/);
+ if (!m)
+ break;
+ headers[m[1].toLowerCase()] = m[2];
+ }
+
+ /* Chop off the first and last lines */
+ lines = lines.slice(0, -1).join('');
+ buf = new Buffer(lines, 'base64');
+
+ return (x509.read(buf, options));
+}
+
+function write(cert, options) {
+ var dbuf = x509.write(cert, options);
+
+ var header = 'CERTIFICATE';
+ var tmp = dbuf.toString('base64');
+ var len = tmp.length + (tmp.length / 64) +
+ 18 + 16 + header.length*2 + 10;
+ var buf = new Buffer(len);
+ var o = 0;
+ o += buf.write('-----BEGIN ' + header + '-----\n', o);
+ for (var i = 0; i < tmp.length; ) {
+ var limit = i + 64;
+ if (limit > tmp.length)
+ limit = tmp.length;
+ o += buf.write(tmp.slice(i, limit), o);
+ buf[o++] = 10;
+ i = limit;
+ }
+ o += buf.write('-----END ' + header + '-----\n', o);
+
+ return (buf.slice(0, o));
+}
diff --git a/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/x509.js b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/x509.js
new file mode 100644
index 00000000..c630ce10
--- /dev/null
+++ b/vnfmarket/src/main/webapp/vnfmarket/node_modules/sshpk/lib/formats/x509.js
@@ -0,0 +1,699 @@
+// Copyright 2016 Joyent, Inc.
+
+module.exports = {
+ read: read,
+ verify: verify,
+ sign: sign,
+ write: write
+};
+
+var assert = require('assert-plus');
+var asn1 = require('asn1');
+var algs = require('../algs');
+var utils = require('../utils');
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+var pem = require('./pem');
+var Identity = require('../identity');
+var Signature = require('../signature');
+var Certificate = require('../certificate');
+var pkcs8 = require('./pkcs8');
+
+/*
+ * This file is based on RFC5280 (X.509).
+ */
+
+/* Helper to read in a single mpint */
+function readMPInt(der, nm) {
+ assert.strictEqual(der.peek(), asn1.Ber.Integer,
+ nm + ' is not an Integer');
+ return (utils.mpNormalize(der.readString(asn1.Ber.Integer, true)));
+}
+
+function verify(cert, key) {
+ var sig = cert.signatures.x509;
+ assert.object(sig, 'x509 signature');
+
+ var algParts = sig.algo.split('-');
+ if (algParts[0] !== key.type)
+ return (false);
+
+ var blob = sig.cache;
+ if (blob === undefined) {
+ var der = new asn1.BerWriter();
+ writeTBSCert(cert, der);
+ blob = der.buffer;
+ }
+
+ var verifier = key.createVerify(algParts[1]);
+ verifier.write(blob);
+ return (verifier.verify(sig.signature));
+}
+
+function Local(i) {
+ return (asn1.Ber.Context | asn1.Ber.Constructor | i);
+}
+
+function Context(i) {
+ return (asn1.Ber.Context | i);
+}
+
+var SIGN_ALGS = {
+ 'rsa-md5': '1.2.840.113549.1.1.4',
+ 'rsa-sha1': '1.2.840.113549.1.1.5',
+ 'rsa-sha256': '1.2.840.113549.1.1.11',
+ 'rsa-sha384': '1.2.840.113549.1.1.12',
+ 'rsa-sha512': '1.2.840.113549.1.1.13',
+ 'dsa-sha1': '1.2.840.10040.4.3',
+ 'dsa-sha256': '2.16.840.1.101.3.4.3.2',
+ 'ecdsa-sha1': '1.2.840.10045.4.1',
+ 'ecdsa-sha256': '1.2.840.10045.4.3.2',
+ 'ecdsa-sha384': '1.2.840.10045.4.3.3',
+ 'ecdsa-sha512': '1.2.840.10045.4.3.4'
+};
+Object.keys(SIGN_ALGS).forEach(function (k) {
+ SIGN_ALGS[SIGN_ALGS[k]] = k;
+});
+SIGN_ALGS['1.3.14.3.2.3'] = 'rsa-md5';
+SIGN_ALGS['1.3.14.3.2.29'] = 'rsa-sha1';
+
+var EXTS = {
+ 'issuerKeyId': '2.5.29.35',
+ 'altName': '2.5.29.17',
+ 'basicConstraints': '2.5.29.19',
+ 'keyUsage': '2.5.29.15',
+ 'extKeyUsage': '2.5.29.37'
+};
+
+function read(buf, options) {
+ if (typeof (buf) === 'string') {
+ buf = new Buffer(buf, 'binary');
+ }
+ assert.buffer(buf, 'buf');
+
+ var der = new asn1.BerReader(buf);
+
+ der.readSequence();
+ if (Math.abs(der.length - der.remain) > 1) {
+ throw (new Error('DER sequence does not contain whole byte ' +
+ 'stream'));
+ }
+
+ var tbsStart = der.offset;
+ der.readSequence();
+ var sigOffset = der.offset + der.length;
+ var tbsEnd = sigOffset;
+
+ if (der.peek() === Local(0)) {
+ der.readSequence(Local(0));
+ var version = der.readInt();
+ assert.ok(version <= 3,
+ 'only x.509 versions up to v3 supported');
+ }
+
+ var cert = {};
+ cert.signatures = {};
+ var sig = (cert.signatures.x509 = {});
+ sig.extras = {};
+
+ cert.serial = readMPInt(der, 'serial');
+
+ der.readSequence();
+ var after = der.offset + der.length;
+ var certAlgOid = der.readOID();
+ var certAlg = SIGN_ALGS[certAlgOid];
+ if (certAlg === undefined)
+ throw (new Error('unknown signature algorithm ' + certAlgOid));
+
+ der._offset = after;
+ cert.issuer = Identity.parseAsn1(der);
+
+ der.readSequence();
+ cert.validFrom = readDate(der);
+ cert.validUntil = readDate(der);
+
+ cert.subjects = [Identity.parseAsn1(der)];
+
+ der.readSequence();
+ after = der.offset + der.length;
+ cert.subjectKey = pkcs8.readPkcs8(undefined, 'public', der);
+ der._offset = after;
+
+ /* issuerUniqueID */
+ if (der.peek() === Local(1)) {
+ der.readSequence(Local(1));
+ sig.extras.issuerUniqueID =
+ buf.slice(der.offset, der.offset + der.length);
+ der._offset += der.length;
+ }
+
+ /* subjectUniqueID */
+ if (der.peek() === Local(2)) {
+ der.readSequence(Local(2));
+ sig.extras.subjectUniqueID =
+ buf.slice(der.offset, der.offset + der.length);
+ der._offset += der.length;
+ }
+
+ /* extensions */
+ if (der.peek() === Local(3)) {
+ der.readSequence(Local(3));
+ var extEnd = der.offset + der.length;
+ der.readSequence();
+
+ while (der.offset < extEnd)
+ readExtension(cert, buf, der);
+
+ assert.strictEqual(der.offset, extEnd);
+ }
+
+ assert.strictEqual(der.offset, sigOffset);
+
+ der.readSequence();
+ after = der.offset + der.length;
+ var sigAlgOid = der.readOID();
+ var sigAlg = SIGN_ALGS[sigAlgOid];
+ if (sigAlg === undefined)
+ throw (new Error('unknown signature algorithm ' + sigAlgOid));
+ der._offset = after;
+
+ var sigData = der.readString(asn1.Ber.BitString, true);
+ if (sigData[0] === 0)
+ sigData = sigData.slice(1);
+ var algParts = sigAlg.split('-');
+
+ sig.signature = Signature.parse(sigData, algParts[0], 'asn1');
+ sig.signature.hashAlgorithm = algParts[1];
+ sig.algo = sigAlg;
+ sig.cache = buf.slice(tbsStart, tbsEnd);
+
+ return (new Certificate(cert));
+}
+
+function readDate(der) {
+ if (der.peek() === asn1.Ber.UTCTime) {
+ return (utcTimeToDate(der.readString(asn1.Ber.UTCTime)));
+ } else if (der.peek() === asn1.Ber.GeneralizedTime) {
+ return (gTimeToDate(der.readString(asn1.Ber.GeneralizedTime)));
+ } else {
+ throw (new Error('Unsupported date format'));
+ }
+}
+
+/* RFC5280, section 4.2.1.6 (GeneralName type) */
+var ALTNAME = {
+ OtherName: Local(0),
+ RFC822Name: Context(1),
+ DNSName: Context(2),
+ X400Address: Local(3),
+ DirectoryName: Local(4),
+ EDIPartyName: Local(5),
+ URI: Context(6),
+ IPAddress: Context(7),
+ OID: Context(8)
+};
+
+/* RFC5280, section 4.2.1.12 (KeyPurposeId) */
+var EXTPURPOSE = {
+ 'serverAuth': '1.3.6.1.5.5.7.3.1',
+ 'clientAuth': '1.3.6.1.5.5.7.3.2',
+ 'codeSigning': '1.3.6.1.5.5.7.3.3',
+
+ /* See https://github.com/joyent/oid-docs/blob/master/root.md */
+ 'joyentDocker': '1.3.6.1.4.1.38678.1.4.1',
+ 'joyentCmon': '1.3.6.1.4.1.38678.1.4.2'
+};
+var EXTPURPOSE_REV = {};
+Object.keys(EXTPURPOSE).forEach(function (k) {
+ EXTPURPOSE_REV[EXTPURPOSE[k]] = k;
+});
+
+var KEYUSEBITS = [
+ 'signature', 'identity', 'keyEncryption',
+ 'encryption', 'keyAgreement', 'ca', 'crl'
+];
+
+function readExtension(cert, buf, der) {
+ der.readSequence();
+ var after = der.offset + der.length;
+ var extId = der.readOID();
+ var id;
+ var sig = cert.signatures.x509;
+ sig.extras.exts = [];
+
+ var critical;
+ if (der.peek() === asn1.Ber.Boolean)
+ critical = der.readBoolean();
+
+ switch (extId) {
+ case (EXTS.basicConstraints):
+ der.readSequence(asn1.Ber.OctetString);
+ der.readSequence();
+ var bcEnd = der.offset + der.length;
+ var ca = false;
+ if (der.peek() === asn1.Ber.Boolean)
+ ca = der.readBoolean();
+ if (cert.purposes === undefined)
+ cert.purposes = [];
+ if (ca === true)
+ cert.purposes.push('ca');
+ var bc = { oid: extId, critical: critical };
+ if (der.offset < bcEnd && der.peek() === asn1.Ber.Integer)
+ bc.pathLen = der.readInt();
+ sig.extras.exts.push(bc);
+ break;
+ case (EXTS.extKeyUsage):
+ der.readSequence(asn1.Ber.OctetString);
+ der.readSequence();
+ if (cert.purposes === undefined)
+ cert.purposes = [];
+ var ekEnd = der.offset + der.length;
+ while (der.offset < ekEnd) {
+ var oid = der.readOID();
+ cert.purposes.push(EXTPURPOSE_REV[oid] || oid);
+ }
+ /*
+ * This is a bit of a hack: in the case where we have a cert
+ * that's only allowed to do serverAuth or clientAuth (and not
+ * the other), we want to make sure all our Subjects are of
+ * the right type. But we already parsed our Subjects and
+ * decided if they were hosts or users earlier (since it appears
+ * first in the cert).
+ *
+ * So we go through and mutate them into the right kind here if
+ * it doesn't match. This might not be hugely beneficial, as it
+ * seems that single-purpose certs are not often seen in the
+ * wild.
+ */
+ if (cert.purposes.indexOf('serverAuth') !== -1 &&
+ cert.purposes.indexOf('clientAuth') === -1) {
+ cert.subjects.forEach(function (ide) {
+ if (ide.type !== 'host') {
+ ide.type = 'host';
+ ide.hostname = ide.uid ||
+ ide.email ||
+ ide.components[0].value;
+ }
+ });
+ } else if (cert.purposes.indexOf('clientAuth') !== -1 &&
+ cert.purposes.indexOf('serverAuth') === -1) {
+ cert.subjects.forEach(function (ide) {
+ if (ide.type !== 'user') {
+ ide.type = 'user';
+ ide.uid = ide.hostname ||
+ ide.email ||
+ ide.components[0].value;
+ }
+ });
+ }
+ sig.extras.exts.push({ oid: extId, critical: critical });
+ break;
+ case (EXTS.keyUsage):
+ der.readSequence(asn1.Ber.OctetString);
+ var bits = der.readString(asn1.Ber.BitString, true);
+ var setBits = readBitField(bits, KEYUSEBITS);
+ setBits.forEach(function (bit) {
+ if (cert.purposes === undefined)
+ cert.purposes = [];
+ if (cert.purposes.indexOf(bit) === -1)
+ cert.purposes.push(bit);
+ });
+ sig.extras.exts.push({ oid: extId, critical: critical,
+ bits: bits });
+ break;
+ case (EXTS.altName):
+ der.readSequence(asn1.Ber.OctetString);
+ der.readSequence();
+ var aeEnd = der.offset + der.length;
+ while (der.offset < aeEnd) {
+ switch (der.peek()) {
+ case ALTNAME.OtherName:
+ case ALTNAME.EDIPartyName:
+ der.readSequence();
+ der._offset += der.length;
+ break;
+ case ALTNAME.OID:
+ der.readOID(ALTNAME.OID);
+ break;
+ case ALTNAME.RFC822Name:
+ /* RFC822 specifies email addresses */
+ var email = der.readString(ALTNAME.RFC822Name);
+ id = Identity.forEmail(email);
+ if (!cert.subjects[0].equals(id))
+ cert.subjects.push(id);
+ break;
+ case ALTNAME.DirectoryName:
+ der.readSequence(ALTNAME.DirectoryName);
+ id = Identity.parseAsn1(der);
+ if (!cert.subjects[0].equals(id))
+ cert.subjects.push(id);
+ break;
+ case ALTNAME.DNSName:
+ var host = der.readString(
+ ALTNAME.DNSName);
+ id = Identity.forHost(host);
+ if (!cert.subjects[0].equals(id))
+ cert.subjects.push(id);
+ break;
+ default:
+ der.readString(der.peek());
+ break;
+ }
+ }
+ sig.extras.exts.push({ oid: extId, critical: critical });
+ break;
+ default:
+ sig.extras.exts.push({
+ oid: extId,
+ critical: critical,
+ data: der.readString(asn1.Ber.OctetString, true)
+ });
+ break;
+ }
+
+ der._offset = after;
+}
+
+var UTCTIME_RE =
+ /^([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})?Z$/;
+function utcTimeToDate(t) {
+ var m = t.match(UTCTIME_RE);
+ assert.ok(m, 'timestamps must be in UTC');
+ var d = new Date();
+
+ var thisYear = d.getUTCFullYear();
+ var century = Math.floor(thisYear / 100) * 100;
+
+ var year = parseInt(m[1], 10);
+ if (thisYear % 100 < 50 && year >= 60)
+ year += (century - 1);
+ else
+ year += century;
+ d.setUTCFullYear(year, parseInt(m[2], 10) - 1, parseInt(m[3], 10));
+ d.setUTCHours(parseInt(m[4], 10), parseInt(m[5], 10));
+ if (m[6] && m[6].length > 0)
+ d.setUTCSeconds(parseInt(m[6], 10));
+ return (d);
+}
+
+var GTIME_RE =
+ /^([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})?Z$/;
+function gTimeToDate(t) {
+ var m = t.match(GTIME_RE);
+ assert.ok(m);
+ var d = new Date();
+
+ d.setUTCFullYear(parseInt(m[1], 10), parseInt(m[2], 10) - 1,
+ parseInt(m[3], 10));
+ d.setUTCHours(parseInt(m[4], 10), parseInt(m[5], 10));
+ if (m[6] && m[6].length > 0)
+ d.setUTCSeconds(parseInt(m[6], 10));
+ return (d);
+}
+
+function zeroPad(n) {
+ var s = '' + n;
+ while (s.length < 2)
+ s = '0' + s;
+ return (s);
+}
+
+function dateToUTCTime(d) {
+ var s = '';
+ s += zeroPad(d.getUTCFullYear() % 100);
+ s += zeroPad(d.getUTCMonth() + 1);
+ s += zeroPad(d.getUTCDate());
+ s += zeroPad(d.getUTCHours());
+ s += zeroPad(d.getUTCMinutes());
+ s += zeroPad(d.getUTCSeconds());
+ s += 'Z';
+ return (s);
+}
+
+function sign(cert, key) {
+ if (cert.signatures.x509 === undefined)
+ cert.signatures.x509 = {};
+ var sig = cert.signatures.x509;
+
+ sig.algo = key.type + '-' + key.defaultHashAlgorithm();
+ if (SIGN_ALGS[sig.algo] === undefined)
+ return (false);
+
+ var der = new asn1.BerWriter();
+ writeTBSCert(cert, der);
+ var blob = der.buffer;
+ sig.cache = blob;
+
+ var signer = key.createSign();
+ signer.write(blob);
+ cert.signatures.x509.signature = signer.sign();
+
+ return (true);
+}
+
+function write(cert, options) {
+ var sig = cert.signatures.x509;
+ assert.object(sig, 'x509 signature');
+
+ var der = new asn1.BerWriter();
+ der.startSequence();
+ if (sig.cache) {
+ der._ensure(sig.cache.length);
+ sig.cache.copy(der._buf, der._offset);
+ der._offset += sig.cache.length;
+ } else {
+ writeTBSCert(cert, der);
+ }
+
+ der.startSequence();
+ der.writeOID(SIGN_ALGS[sig.algo]);
+ if (sig.algo.match(/^rsa-/))
+ der.writeNull();
+ der.endSequence();
+
+ var sigData = sig.signature.toBuffer('asn1');
+ var data = new Buffer(sigData.length + 1);
+ data[0] = 0;
+ sigData.copy(data, 1);
+ der.writeBuffer(data, asn1.Ber.BitString);
+ der.endSequence();
+
+ return (der.buffer);
+}
+
+function writeTBSCert(cert, der) {
+ var sig = cert.signatures.x509;
+ assert.object(sig, 'x509 signature');
+
+ der.startSequence();
+
+ der.startSequence(Local(0));
+ der.writeInt(2);
+ der.endSequence();
+
+ der.writeBuffer(utils.mpNormalize(cert.serial), asn1.Ber.Integer);
+
+ der.startSequence();
+ der.writeOID(SIGN_ALGS[sig.algo]);
+ der.endSequence();
+
+ cert.issuer.toAsn1(der);
+
+ der.startSequence();
+ der.writeString(dateToUTCTime(cert.validFrom), asn1.Ber.UTCTime);
+ der.writeString(dateToUTCTime(cert.validUntil), asn1.Ber.UTCTime);
+ der.endSequence();
+
+ var subject = cert.subjects[0];
+ var altNames = cert.subjects.slice(1);
+ subject.toAsn1(der);
+
+ pkcs8.writePkcs8(der, cert.subjectKey);
+
+ if (sig.extras && sig.extras.issuerUniqueID) {
+ der.writeBuffer(sig.extras.issuerUniqueID, Local(1));
+ }
+
+ if (sig.extras && sig.extras.subjectUniqueID) {
+ der.writeBuffer(sig.extras.subjectUniqueID, Local(2));
+ }
+
+ if (altNames.length > 0 || subject.type === 'host' ||
+ (cert.purposes !== undefined && cert.purposes.length > 0) ||
+ (sig.extras && sig.extras.exts)) {
+ der.startSequence(Local(3));
+ der.startSequence();
+
+ var exts = [];
+ if (cert.purposes !== undefined && cert.purposes.length > 0) {
+ exts.push({
+ oid: EXTS.basicConstraints,
+ critical: true
+ });
+ exts.push({
+ oid: EXTS.keyUsage,
+ critical: true
+ });
+ exts.push({
+ oid: EXTS.extKeyUsage,
+ critical: true
+ });
+ }
+ exts.push({ oid: EXTS.altName });
+ if (sig.extras && sig.extras.exts)
+ exts = sig.extras.exts;
+
+ for (var i = 0; i < exts.length; ++i) {
+ der.startSequence();
+ der.writeOID(exts[i].oid);
+
+ if (exts[i].critical !== undefined)
+ der.writeBoolean(exts[i].critical);
+
+ if (exts[i].oid === EXTS.altName) {
+ der.startSequence(asn1.Ber.OctetString);
+ der.startSequence();
+ if (subject.type === 'host') {
+ der.writeString(subject.hostname,
+ Context(2));
+ }
+ for (var j = 0; j < altNames.length; ++j) {
+ if (altNames[j].type === 'host') {
+ der.writeString(
+ altNames[j].hostname,
+ ALTNAME.DNSName);
+ } else if (altNames[j].type ===
+ 'email') {
+ der.writeString(
+ altNames[j].email,
+ ALTNAME.RFC822Name);
+ } else {
+ /*
+ * Encode anything else as a
+ * DN style name for now.
+ */
+ der.startSequence(
+ ALTNAME.DirectoryName);
+ altNames[j].toAsn1(der);
+ der.endSequence();
+ }
+ }
+ der.endSequence();
+ der.endSequence();
+ } else if (exts[i].oid === EXTS.basicConstraints) {
+ der.startSequence(asn1.Ber.OctetString);
+ der.startSequence();
+ var ca = (cert.purposes.indexOf('ca') !== -1);
+ var pathLen = exts[i].pathLen;
+ der.writeBoolean(ca);
+ if (pathLen !== undefined)
+ der.writeInt(pathLen);
+ der.endSequence();
+ der.endSequence();
+ } else if (exts[i].oid === EXTS.extKeyUsage) {
+ der.startSequence(asn1.Ber.OctetString);
+ der.startSequence();
+ cert.purposes.forEach(function (purpose) {
+ if (purpose === 'ca')
+ return;
+ if (KEYUSEBITS.indexOf(purpose) !== -1)
+ return;
+ var oid = purpose;
+ if (EXTPURPOSE[purpose] !== undefined)
+ oid = EXTPURPOSE[purpose];
+ der.writeOID(oid);
+ });
+ der.endSequence();
+ der.endSequence();
+ } else if (exts[i].oid === EXTS.keyUsage) {
+ der.startSequence(asn1.Ber.OctetString);
+ /*
+ * If we parsed this certificate from a byte
+ * stream (i.e. we didn't generate it in sshpk)
+ * then we'll have a ".bits" property on the
+ * ext with the original raw byte contents.
+ *
+ * If we have this, use it here instead of
+ * regenerating it. This guarantees we output
+ * the same data we parsed, so signatures still
+ * validate.
+ */
+ if (exts[i].bits !== undefined) {
+ der.writeBuffer(exts[i].bits,
+ asn1.Ber.BitString);
+ } else {
+ var bits = writeBitField(cert.purposes,
+ KEYUSEBITS);
+ der.writeBuffer(bits,
+ asn1.Ber.BitString);
+ }
+ der.endSequence();
+ } else {
+ der.writeBuffer(exts[i].data,
+ asn1.Ber.OctetString);
+ }
+
+ der.endSequence();
+ }
+
+ der.endSequence();
+ der.endSequence();
+ }
+
+ der.endSequence();
+}
+
+/*
+ * Reads an ASN.1 BER bitfield out of the Buffer produced by doing
+ * `BerReader#readString(asn1.Ber.BitString)`. That function gives us the raw
+ * contents of the BitString tag, which is a count of unused bits followed by
+ * the bits as a right-padded byte string.
+ *
+ * `bits` is the Buffer, `bitIndex` should contain an array of string names
+ * for the bits in the string, ordered starting with bit #0 in the ASN.1 spec.
+ *
+ * Returns an array of Strings, the names of the bits that were set to 1.
+ */
+function readBitField(bits, bitIndex) {
+ var bitLen = 8 * (bits.length - 1) - bits[0];
+ var setBits = {};
+ for (var i = 0; i < bitLen; ++i) {
+ var byteN = 1 + Math.floor(i / 8);
+ var bit = 7 - (i % 8);
+ var mask = 1 << bit;
+ var bitVal = ((bits[byteN] & mask) !== 0);
+ var name = bitIndex[i];
+ if (bitVal && typeof (name) === 'string') {
+ setBits[name] = true;
+ }
+ }
+ return (Object.keys(setBits));
+}
+
+/*
+ * `setBits` is an array of strings, containing the names for each bit that
+ * sould be set to 1. `bitIndex` is same as in `readBitField()`.
+ *
+ * Returns a Buffer, ready to be written out with `BerWriter#writeString()`.
+ */
+function writeBitField(setBits, bitIndex) {
+ var bitLen = bitIndex.length;
+ var blen = Math.ceil(bitLen / 8);
+ var unused = blen * 8 - bitLen;
+ var bits = new Buffer(1 + blen);
+ bits.fill(0);
+ bits[0] = unused;
+ for (var i = 0; i < bitLen; ++i) {
+ var byteN = 1 + Math.floor(i / 8);
+ var bit = 7 - (i % 8);
+ var mask = 1 << bit;
+ var name = bitIndex[i];
+ if (name === undefined)
+ continue;
+ var bitVal = (setBits.indexOf(name) !== -1);
+ if (bitVal) {
+ bits[byteN] |= mask;
+ }
+ }
+ return (bits);
+}