diff options
Diffstat (limited to 'deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib')
8 files changed, 272 insertions, 16 deletions
diff --git a/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/dhe.js b/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/dhe.js index 8f9548ce57..74f5e04702 100644 --- a/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/dhe.js +++ b/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/dhe.js @@ -1,12 +1,17 @@ -// Copyright 2015 Joyent, Inc. +// Copyright 2017 Joyent, Inc. -module.exports = DiffieHellman; +module.exports = { + DiffieHellman: DiffieHellman, + generateECDSA: generateECDSA, + generateED25519: generateED25519 +}; var assert = require('assert-plus'); var crypto = require('crypto'); var algs = require('./algs'); var utils = require('./utils'); var ed; +var nacl; var Key = require('./key'); var PrivateKey = require('./private-key'); @@ -309,3 +314,97 @@ ECPrivate.prototype.deriveSharedSecret = function (pubKey) { var S = pubKey._pub.multiply(this._priv); return (new Buffer(S.getX().toBigInteger().toByteArray())); }; + +function generateED25519() { + if (nacl === undefined) + nacl = require('tweetnacl'); + + var pair = nacl.sign.keyPair(); + var priv = new Buffer(pair.secretKey); + var pub = new Buffer(pair.publicKey); + assert.strictEqual(priv.length, 64); + assert.strictEqual(pub.length, 32); + + var parts = []; + parts.push({name: 'R', data: pub}); + parts.push({name: 'r', data: priv}); + var key = new PrivateKey({ + type: 'ed25519', + parts: parts + }); + return (key); +} + +/* Generates a new ECDSA private key on a given curve. */ +function generateECDSA(curve) { + var parts = []; + var key; + + if (CRYPTO_HAVE_ECDH) { + /* + * Node crypto doesn't expose key generation directly, but the + * ECDH instances can generate keys. It turns out this just + * calls into the OpenSSL generic key generator, and we can + * read its output happily without doing an actual DH. So we + * use that here. + */ + var osCurve = { + 'nistp256': 'prime256v1', + 'nistp384': 'secp384r1', + 'nistp521': 'secp521r1' + }[curve]; + + var dh = crypto.createECDH(osCurve); + dh.generateKeys(); + + parts.push({name: 'curve', + data: new Buffer(curve)}); + parts.push({name: 'Q', data: dh.getPublicKey()}); + parts.push({name: 'd', data: dh.getPrivateKey()}); + + key = new PrivateKey({ + type: 'ecdsa', + curve: curve, + parts: parts + }); + return (key); + + } else { + if (ecdh === undefined) + ecdh = require('ecc-jsbn'); + if (ec === undefined) + ec = require('ecc-jsbn/lib/ec'); + if (jsbn === undefined) + jsbn = require('jsbn').BigInteger; + + var ecParams = new X9ECParameters(curve); + + /* This algorithm taken from FIPS PUB 186-4 (section B.4.1) */ + var n = ecParams.getN(); + /* + * The crypto.randomBytes() function can only give us whole + * bytes, so taking a nod from X9.62, we round up. + */ + var cByteLen = Math.ceil((n.bitLength() + 64) / 8); + var c = new jsbn(crypto.randomBytes(cByteLen)); + + var n1 = n.subtract(jsbn.ONE); + var priv = c.mod(n1).add(jsbn.ONE); + var pub = ecParams.getG().multiply(priv); + + priv = new Buffer(priv.toByteArray()); + pub = new Buffer(ecParams.getCurve(). + encodePointHex(pub), 'hex'); + + parts.push({name: 'curve', data: new Buffer(curve)}); + parts.push({name: 'Q', data: pub}); + parts.push({name: 'd', data: priv}); + + key = new PrivateKey({ + type: 'ecdsa', + curve: curve, + parts: parts + }); + return (key); + } +} diff --git a/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/openssh-cert.js b/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/openssh-cert.js index 8ce7350fee..b68155e887 100644 --- a/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/openssh-cert.js +++ b/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/openssh-cert.js @@ -1,9 +1,10 @@ -// Copyright 2016 Joyent, Inc. +// Copyright 2017 Joyent, Inc. module.exports = { read: read, verify: verify, sign: sign, + signAsync: signAsync, write: write, /* Internal private API */ @@ -188,6 +189,38 @@ function sign(cert, key) { return (true); } +function signAsync(cert, signer, done) { + if (cert.signatures.openssh === undefined) + cert.signatures.openssh = {}; + try { + var blob = toBuffer(cert, true); + } catch (e) { + delete (cert.signatures.openssh); + done(e); + return; + } + var sig = cert.signatures.openssh; + + signer(blob, function (err, signature) { + if (err) { + done(err); + return; + } + try { + /* + * This will throw if the signature isn't of a + * type/algo that can be used for SSH. + */ + signature.toBuffer('ssh'); + } catch (e) { + done(e); + return; + } + sig.signature = signature; + done(); + }); +} + function write(cert, options) { if (options === undefined) options = {}; diff --git a/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/x509.js b/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/x509.js index c630ce1059..23acd245fb 100644 --- a/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/x509.js +++ b/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/x509.js @@ -1,9 +1,10 @@ -// Copyright 2016 Joyent, Inc. +// Copyright 2017 Joyent, Inc. module.exports = { read: read, verify: verify, sign: sign, + signAsync: signAsync, write: write }; @@ -451,6 +452,32 @@ function sign(cert, key) { return (true); } +function signAsync(cert, signer, done) { + if (cert.signatures.x509 === undefined) + cert.signatures.x509 = {}; + var sig = cert.signatures.x509; + + var der = new asn1.BerWriter(); + writeTBSCert(cert, der); + var blob = der.buffer; + sig.cache = blob; + + signer(blob, function (err, signature) { + if (err) { + done(err); + return; + } + sig.algo = signature.type + '-' + signature.hashAlgorithm; + if (SIGN_ALGS[sig.algo] === undefined) { + done(new Error('Invalid signing algorithm "' + + sig.algo + '"')); + return; + } + sig.signature = signature; + done(); + }); +} + function write(cert, options) { var sig = cert.signatures.x509; assert.object(sig, 'x509 signature'); diff --git a/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/identity.js b/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/identity.js index eeda3a3219..5e9021f8ee 100644 --- a/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/identity.js +++ b/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/identity.js @@ -1,4 +1,4 @@ -// Copyright 2016 Joyent, Inc. +// Copyright 2017 Joyent, Inc. module.exports = Identity; diff --git a/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/index.js b/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/index.js index 96a1384286..cb8cd1a1b8 100644 --- a/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/index.js +++ b/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/index.js @@ -18,6 +18,7 @@ module.exports = { parseSignature: Signature.parse, PrivateKey: PrivateKey, parsePrivateKey: PrivateKey.parse, + generatePrivateKey: PrivateKey.generate, Certificate: Certificate, parseCertificate: Certificate.parse, createSelfSignedCertificate: Certificate.createSelfSigned, diff --git a/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/key.js b/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/key.js index ff5c363733..56b8cb4f05 100644 --- a/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/key.js +++ b/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/key.js @@ -1,4 +1,4 @@ -// Copyright 2015 Joyent, Inc. +// Copyright 2017 Joyent, Inc. module.exports = Key; @@ -7,7 +7,7 @@ var algs = require('./algs'); var crypto = require('crypto'); var Fingerprint = require('./fingerprint'); var Signature = require('./signature'); -var DiffieHellman = require('./dhe'); +var DiffieHellman = require('./dhe').DiffieHellman; var errs = require('./errors'); var utils = require('./utils'); var PrivateKey = require('./private-key'); @@ -171,6 +171,7 @@ Key.prototype.createVerify = function (hashAlgo) { assert.ok(v, 'failed to create verifier'); var oldVerify = v.verify.bind(v); var key = this.toBuffer('pkcs8'); + var curve = this.curve; var self = this; v.verify = function (signature, fmt) { if (Signature.isSignature(signature, [2, 0])) { @@ -179,6 +180,9 @@ Key.prototype.createVerify = function (hashAlgo) { if (signature.hashAlgorithm && signature.hashAlgorithm !== hashAlgo) return (false); + if (signature.curve && self.type === 'ecdsa' && + signature.curve !== curve) + return (false); return (oldVerify(key, signature.toBuffer('asn1'))); } else if (typeof (signature) === 'string' || diff --git a/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/private-key.js b/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/private-key.js index f80d939662..b56201a189 100644 --- a/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/private-key.js +++ b/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/private-key.js @@ -1,4 +1,4 @@ -// Copyright 2015 Joyent, Inc. +// Copyright 2017 Joyent, Inc. module.exports = PrivateKey; @@ -10,6 +10,9 @@ var Signature = require('./signature'); var errs = require('./errors'); var util = require('util'); var utils = require('./utils'); +var dhe = require('./dhe'); +var generateECDSA = dhe.generateECDSA; +var generateED25519 = dhe.generateED25519; var edCompat; var ed; @@ -163,12 +166,14 @@ PrivateKey.prototype.createSign = function (hashAlgo) { var oldSign = v.sign.bind(v); var key = this.toBuffer('pkcs1'); var type = this.type; + var curve = this.curve; v.sign = function () { var sig = oldSign(key); if (typeof (sig) === 'string') sig = new Buffer(sig, 'binary'); sig = Signature.parse(sig, type, 'asn1'); sig.hashAlgorithm = hashAlgo; + sig.curve = curve; return (sig); }; return (v); @@ -208,6 +213,25 @@ PrivateKey.isPrivateKey = function (obj, ver) { return (utils.isCompatible(obj, PrivateKey, ver)); }; +PrivateKey.generate = function (type, options) { + if (options === undefined) + options = {}; + assert.object(options, 'options'); + + switch (type) { + case 'ecdsa': + if (options.curve === undefined) + options.curve = 'nistp256'; + assert.string(options.curve, 'options.curve'); + return (generateECDSA(options.curve)); + case 'ed25519': + return (generateED25519()); + default: + throw (new Error('Key generation not supported with key ' + + 'type "' + type + '"')); + } +}; + /* * API versions for PrivateKey: * [1,0] -- initial ver diff --git a/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/signature.js b/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/signature.js index 964f55cb56..333bb5d39e 100644 --- a/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/signature.js +++ b/deps/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/signature.js @@ -26,6 +26,7 @@ function Signature(opts) { this.type = opts.type; this.hashAlgorithm = opts.hashAlgo; + this.curve = opts.curve; this.parts = opts.parts; this.part = partLookup; } @@ -36,18 +37,45 @@ Signature.prototype.toBuffer = function (format) { assert.string(format, 'format'); var buf; + var stype = 'ssh-' + this.type; switch (this.type) { case 'rsa': + switch (this.hashAlgorithm) { + case 'sha256': + stype = 'rsa-sha2-256'; + break; + case 'sha512': + stype = 'rsa-sha2-512'; + break; + case 'sha1': + case undefined: + break; + default: + throw (new Error('SSH signature ' + + 'format does not support hash ' + + 'algorithm ' + this.hashAlgorithm)); + } + if (format === 'ssh') { + buf = new SSHBuffer({}); + buf.writeString(stype); + buf.writePart(this.part.sig); + return (buf.toBuffer()); + } else { + return (this.part.sig.data); + } + break; + case 'ed25519': if (format === 'ssh') { buf = new SSHBuffer({}); - buf.writeString('ssh-' + this.type); + buf.writeString(stype); buf.writePart(this.part.sig); return (buf.toBuffer()); } else { return (this.part.sig.data); } + break; case 'dsa': case 'ecdsa': @@ -126,11 +154,9 @@ Signature.parse = function (data, type, format) { assert.ok(data.length > 0, 'signature must not be empty'); switch (opts.type) { case 'rsa': - return (parseOneNum(data, type, format, opts, - 'ssh-rsa')); + return (parseOneNum(data, type, format, opts)); case 'ed25519': - return (parseOneNum(data, type, format, opts, - 'ssh-ed25519')); + return (parseOneNum(data, type, format, opts)); case 'dsa': case 'ecdsa': @@ -152,7 +178,7 @@ Signature.parse = function (data, type, format) { } }; -function parseOneNum(data, type, format, opts, headType) { +function parseOneNum(data, type, format, opts) { if (format === 'ssh') { try { var buf = new SSHBuffer({buffer: data}); @@ -160,7 +186,30 @@ function parseOneNum(data, type, format, opts, headType) { } catch (e) { /* fall through */ } - if (head === headType) { + if (buf !== undefined) { + var msg = 'SSH signature does not match expected ' + + 'type (expected ' + type + ', got ' + head + ')'; + switch (head) { + case 'ssh-rsa': + assert.strictEqual(type, 'rsa', msg); + opts.hashAlgo = 'sha1'; + break; + case 'rsa-sha2-256': + assert.strictEqual(type, 'rsa', msg); + opts.hashAlgo = 'sha256'; + break; + case 'rsa-sha2-512': + assert.strictEqual(type, 'rsa', msg); + opts.hashAlgo = 'sha512'; + break; + case 'ssh-ed25519': + assert.strictEqual(type, 'ed25519', msg); + opts.hashAlgo = 'sha512'; + break; + default: + throw (new Error('Unknown SSH signature ' + + 'type: ' + head)); + } var sig = buf.readPart(); assert.ok(buf.atEnd(), 'extra trailing bytes'); sig.name = 'sig'; @@ -204,7 +253,26 @@ function parseECDSA(data, type, format, opts) { var r, s; var inner = buf.readBuffer(); - if (inner.toString('ascii').match(/^ecdsa-/)) { + var stype = inner.toString('ascii'); + if (stype.slice(0, 6) === 'ecdsa-') { + var parts = stype.split('-'); + assert.strictEqual(parts[0], 'ecdsa'); + assert.strictEqual(parts[1], 'sha2'); + opts.curve = parts[2]; + switch (opts.curve) { + case 'nistp256': + opts.hashAlgo = 'sha256'; + break; + case 'nistp384': + opts.hashAlgo = 'sha384'; + break; + case 'nistp521': + opts.hashAlgo = 'sha512'; + break; + default: + throw (new Error('Unsupported ECDSA curve: ' + + opts.curve)); + } inner = buf.readBuffer(); assert.ok(buf.atEnd(), 'extra trailing bytes on outer'); buf = new SSHBuffer({buffer: inner}); |