mirror of
https://github.com/mgerb/mywebsite
synced 2026-01-12 02:42:48 +00:00
updated bunch of file paths and changed the way posts are loaded
This commit is contained in:
168
node_modules/sshpk/lib/algs.js
generated
vendored
Normal file
168
node_modules/sshpk/lib/algs.js
generated
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
// Copyright 2015 Joyent, Inc.
|
||||
|
||||
var algInfo = {
|
||||
'dsa': {
|
||||
parts: ['p', 'q', 'g', 'y'],
|
||||
sizePart: 'p'
|
||||
},
|
||||
'rsa': {
|
||||
parts: ['e', 'n'],
|
||||
sizePart: 'n'
|
||||
},
|
||||
'ecdsa': {
|
||||
parts: ['curve', 'Q'],
|
||||
sizePart: 'Q'
|
||||
},
|
||||
'ed25519': {
|
||||
parts: ['R'],
|
||||
normalize: false,
|
||||
sizePart: 'R'
|
||||
}
|
||||
};
|
||||
algInfo['curve25519'] = algInfo['ed25519'];
|
||||
|
||||
var algPrivInfo = {
|
||||
'dsa': {
|
||||
parts: ['p', 'q', 'g', 'y', 'x']
|
||||
},
|
||||
'rsa': {
|
||||
parts: ['n', 'e', 'd', 'iqmp', 'p', 'q']
|
||||
},
|
||||
'ecdsa': {
|
||||
parts: ['curve', 'Q', 'd']
|
||||
},
|
||||
'ed25519': {
|
||||
parts: ['R', 'r'],
|
||||
normalize: false
|
||||
}
|
||||
};
|
||||
algPrivInfo['curve25519'] = algPrivInfo['ed25519'];
|
||||
|
||||
var hashAlgs = {
|
||||
'md5': true,
|
||||
'sha1': true,
|
||||
'sha256': true,
|
||||
'sha384': true,
|
||||
'sha512': true
|
||||
};
|
||||
|
||||
/*
|
||||
* Taken from
|
||||
* http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf
|
||||
*/
|
||||
var curves = {
|
||||
'nistp256': {
|
||||
size: 256,
|
||||
pkcs8oid: '1.2.840.10045.3.1.7',
|
||||
p: new Buffer(('00' +
|
||||
'ffffffff 00000001 00000000 00000000' +
|
||||
'00000000 ffffffff ffffffff ffffffff').
|
||||
replace(/ /g, ''), 'hex'),
|
||||
a: new Buffer(('00' +
|
||||
'FFFFFFFF 00000001 00000000 00000000' +
|
||||
'00000000 FFFFFFFF FFFFFFFF FFFFFFFC').
|
||||
replace(/ /g, ''), 'hex'),
|
||||
b: new Buffer((
|
||||
'5ac635d8 aa3a93e7 b3ebbd55 769886bc' +
|
||||
'651d06b0 cc53b0f6 3bce3c3e 27d2604b').
|
||||
replace(/ /g, ''), 'hex'),
|
||||
s: new Buffer(('00' +
|
||||
'c49d3608 86e70493 6a6678e1 139d26b7' +
|
||||
'819f7e90').
|
||||
replace(/ /g, ''), 'hex'),
|
||||
n: new Buffer(('00' +
|
||||
'ffffffff 00000000 ffffffff ffffffff' +
|
||||
'bce6faad a7179e84 f3b9cac2 fc632551').
|
||||
replace(/ /g, ''), 'hex'),
|
||||
G: new Buffer(('04' +
|
||||
'6b17d1f2 e12c4247 f8bce6e5 63a440f2' +
|
||||
'77037d81 2deb33a0 f4a13945 d898c296' +
|
||||
'4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16' +
|
||||
'2bce3357 6b315ece cbb64068 37bf51f5').
|
||||
replace(/ /g, ''), 'hex')
|
||||
},
|
||||
'nistp384': {
|
||||
size: 384,
|
||||
pkcs8oid: '1.3.132.0.34',
|
||||
p: new Buffer(('00' +
|
||||
'ffffffff ffffffff ffffffff ffffffff' +
|
||||
'ffffffff ffffffff ffffffff fffffffe' +
|
||||
'ffffffff 00000000 00000000 ffffffff').
|
||||
replace(/ /g, ''), 'hex'),
|
||||
a: new Buffer(('00' +
|
||||
'FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF' +
|
||||
'FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE' +
|
||||
'FFFFFFFF 00000000 00000000 FFFFFFFC').
|
||||
replace(/ /g, ''), 'hex'),
|
||||
b: new Buffer((
|
||||
'b3312fa7 e23ee7e4 988e056b e3f82d19' +
|
||||
'181d9c6e fe814112 0314088f 5013875a' +
|
||||
'c656398d 8a2ed19d 2a85c8ed d3ec2aef').
|
||||
replace(/ /g, ''), 'hex'),
|
||||
s: new Buffer(('00' +
|
||||
'a335926a a319a27a 1d00896a 6773a482' +
|
||||
'7acdac73').
|
||||
replace(/ /g, ''), 'hex'),
|
||||
n: new Buffer(('00' +
|
||||
'ffffffff ffffffff ffffffff ffffffff' +
|
||||
'ffffffff ffffffff c7634d81 f4372ddf' +
|
||||
'581a0db2 48b0a77a ecec196a ccc52973').
|
||||
replace(/ /g, ''), 'hex'),
|
||||
G: new Buffer(('04' +
|
||||
'aa87ca22 be8b0537 8eb1c71e f320ad74' +
|
||||
'6e1d3b62 8ba79b98 59f741e0 82542a38' +
|
||||
'5502f25d bf55296c 3a545e38 72760ab7' +
|
||||
'3617de4a 96262c6f 5d9e98bf 9292dc29' +
|
||||
'f8f41dbd 289a147c e9da3113 b5f0b8c0' +
|
||||
'0a60b1ce 1d7e819d 7a431d7c 90ea0e5f').
|
||||
replace(/ /g, ''), 'hex')
|
||||
},
|
||||
'nistp521': {
|
||||
size: 521,
|
||||
pkcs8oid: '1.3.132.0.35',
|
||||
p: new Buffer((
|
||||
'01ffffff ffffffff ffffffff ffffffff' +
|
||||
'ffffffff ffffffff ffffffff ffffffff' +
|
||||
'ffffffff ffffffff ffffffff ffffffff' +
|
||||
'ffffffff ffffffff ffffffff ffffffff' +
|
||||
'ffff').replace(/ /g, ''), 'hex'),
|
||||
a: new Buffer(('01FF' +
|
||||
'FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF' +
|
||||
'FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF' +
|
||||
'FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF' +
|
||||
'FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFC').
|
||||
replace(/ /g, ''), 'hex'),
|
||||
b: new Buffer(('51' +
|
||||
'953eb961 8e1c9a1f 929a21a0 b68540ee' +
|
||||
'a2da725b 99b315f3 b8b48991 8ef109e1' +
|
||||
'56193951 ec7e937b 1652c0bd 3bb1bf07' +
|
||||
'3573df88 3d2c34f1 ef451fd4 6b503f00').
|
||||
replace(/ /g, ''), 'hex'),
|
||||
s: new Buffer(('00' +
|
||||
'd09e8800 291cb853 96cc6717 393284aa' +
|
||||
'a0da64ba').replace(/ /g, ''), 'hex'),
|
||||
n: new Buffer(('01ff' +
|
||||
'ffffffff ffffffff ffffffff ffffffff' +
|
||||
'ffffffff ffffffff ffffffff fffffffa' +
|
||||
'51868783 bf2f966b 7fcc0148 f709a5d0' +
|
||||
'3bb5c9b8 899c47ae bb6fb71e 91386409').
|
||||
replace(/ /g, ''), 'hex'),
|
||||
G: new Buffer(('04' +
|
||||
'00c6 858e06b7 0404e9cd 9e3ecb66 2395b442' +
|
||||
'9c648139 053fb521 f828af60 6b4d3dba' +
|
||||
'a14b5e77 efe75928 fe1dc127 a2ffa8de' +
|
||||
'3348b3c1 856a429b f97e7e31 c2e5bd66' +
|
||||
'0118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9' +
|
||||
'98f54449 579b4468 17afbd17 273e662c' +
|
||||
'97ee7299 5ef42640 c550b901 3fad0761' +
|
||||
'353c7086 a272c240 88be9476 9fd16650').
|
||||
replace(/ /g, ''), 'hex')
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
info: algInfo,
|
||||
privInfo: algPrivInfo,
|
||||
hashAlgs: hashAlgs,
|
||||
curves: curves
|
||||
};
|
||||
311
node_modules/sshpk/lib/dhe.js
generated
vendored
Normal file
311
node_modules/sshpk/lib/dhe.js
generated
vendored
Normal file
@@ -0,0 +1,311 @@
|
||||
// Copyright 2015 Joyent, Inc.
|
||||
|
||||
module.exports = DiffieHellman;
|
||||
|
||||
var assert = require('assert-plus');
|
||||
var crypto = require('crypto');
|
||||
var algs = require('./algs');
|
||||
var utils = require('./utils');
|
||||
var ed;
|
||||
|
||||
var Key = require('./key');
|
||||
var PrivateKey = require('./private-key');
|
||||
|
||||
var CRYPTO_HAVE_ECDH = (crypto.createECDH !== undefined);
|
||||
|
||||
var ecdh, ec, jsbn;
|
||||
|
||||
function DiffieHellman(key) {
|
||||
utils.assertCompatible(key, Key, [1, 4], 'key');
|
||||
this._isPriv = PrivateKey.isPrivateKey(key, [1, 3]);
|
||||
this._algo = key.type;
|
||||
this._curve = key.curve;
|
||||
this._key = key;
|
||||
if (key.type === 'dsa') {
|
||||
if (!CRYPTO_HAVE_ECDH) {
|
||||
throw (new Error('Due to bugs in the node 0.10 ' +
|
||||
'crypto API, node 0.12.x or later is required ' +
|
||||
'to use DH'));
|
||||
}
|
||||
this._dh = crypto.createDiffieHellman(
|
||||
key.part.p.data, undefined,
|
||||
key.part.g.data, undefined);
|
||||
this._p = key.part.p;
|
||||
this._g = key.part.g;
|
||||
if (this._isPriv)
|
||||
this._dh.setPrivateKey(key.part.x.data);
|
||||
this._dh.setPublicKey(key.part.y.data);
|
||||
|
||||
} else if (key.type === 'ecdsa') {
|
||||
if (!CRYPTO_HAVE_ECDH) {
|
||||
if (ecdh === undefined)
|
||||
ecdh = require('ecc-jsbn');
|
||||
if (ec === undefined)
|
||||
ec = require('ecc-jsbn/lib/ec');
|
||||
if (jsbn === undefined)
|
||||
jsbn = require('jsbn').BigInteger;
|
||||
|
||||
this._ecParams = new X9ECParameters(this._curve);
|
||||
|
||||
if (this._isPriv) {
|
||||
this._priv = new ECPrivate(
|
||||
this._ecParams, key.part.d.data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var curve = {
|
||||
'nistp256': 'prime256v1',
|
||||
'nistp384': 'secp384r1',
|
||||
'nistp521': 'secp521r1'
|
||||
}[key.curve];
|
||||
this._dh = crypto.createECDH(curve);
|
||||
if (typeof (this._dh) !== 'object' ||
|
||||
typeof (this._dh.setPrivateKey) !== 'function') {
|
||||
CRYPTO_HAVE_ECDH = false;
|
||||
DiffieHellman.call(this, key);
|
||||
return;
|
||||
}
|
||||
if (this._isPriv)
|
||||
this._dh.setPrivateKey(key.part.d.data);
|
||||
this._dh.setPublicKey(key.part.Q.data);
|
||||
|
||||
} else if (key.type === 'curve25519') {
|
||||
if (ed === undefined)
|
||||
ed = require('jodid25519');
|
||||
|
||||
if (this._isPriv) {
|
||||
this._priv = key.part.r.data;
|
||||
if (this._priv[0] === 0x00)
|
||||
this._priv = this._priv.slice(1);
|
||||
this._priv = this._priv.slice(0, 32);
|
||||
}
|
||||
|
||||
} else {
|
||||
throw (new Error('DH not supported for ' + key.type + ' keys'));
|
||||
}
|
||||
}
|
||||
|
||||
DiffieHellman.prototype.getPublicKey = function () {
|
||||
if (this._isPriv)
|
||||
return (this._key.toPublic());
|
||||
return (this._key);
|
||||
};
|
||||
|
||||
DiffieHellman.prototype.getPrivateKey = function () {
|
||||
if (this._isPriv)
|
||||
return (this._key);
|
||||
else
|
||||
return (undefined);
|
||||
};
|
||||
DiffieHellman.prototype.getKey = DiffieHellman.prototype.getPrivateKey;
|
||||
|
||||
DiffieHellman.prototype._keyCheck = function (pk, isPub) {
|
||||
assert.object(pk, 'key');
|
||||
if (!isPub)
|
||||
utils.assertCompatible(pk, PrivateKey, [1, 3], 'key');
|
||||
utils.assertCompatible(pk, Key, [1, 4], 'key');
|
||||
|
||||
if (pk.type !== this._algo) {
|
||||
throw (new Error('A ' + pk.type + ' key cannot be used in ' +
|
||||
this._algo + ' Diffie-Hellman'));
|
||||
}
|
||||
|
||||
if (pk.curve !== this._curve) {
|
||||
throw (new Error('A key from the ' + pk.curve + ' curve ' +
|
||||
'cannot be used with a ' + this._curve +
|
||||
' Diffie-Hellman'));
|
||||
}
|
||||
|
||||
if (pk.type === 'dsa') {
|
||||
assert.deepEqual(pk.part.p, this._p,
|
||||
'DSA key prime does not match');
|
||||
assert.deepEqual(pk.part.g, this._g,
|
||||
'DSA key generator does not match');
|
||||
}
|
||||
};
|
||||
|
||||
DiffieHellman.prototype.setKey = function (pk) {
|
||||
this._keyCheck(pk);
|
||||
|
||||
if (pk.type === 'dsa') {
|
||||
this._dh.setPrivateKey(pk.part.x.data);
|
||||
this._dh.setPublicKey(pk.part.y.data);
|
||||
|
||||
} else if (pk.type === 'ecdsa') {
|
||||
if (CRYPTO_HAVE_ECDH) {
|
||||
this._dh.setPrivateKey(pk.part.d.data);
|
||||
this._dh.setPublicKey(pk.part.Q.data);
|
||||
} else {
|
||||
this._priv = new ECPrivate(
|
||||
this._ecParams, pk.part.d.data);
|
||||
}
|
||||
|
||||
} else if (pk.type === 'curve25519') {
|
||||
this._priv = pk.part.r.data;
|
||||
if (this._priv[0] === 0x00)
|
||||
this._priv = this._priv.slice(1);
|
||||
this._priv = this._priv.slice(0, 32);
|
||||
}
|
||||
this._key = pk;
|
||||
this._isPriv = true;
|
||||
};
|
||||
DiffieHellman.prototype.setPrivateKey = DiffieHellman.prototype.setKey;
|
||||
|
||||
DiffieHellman.prototype.computeSecret = function (otherpk) {
|
||||
this._keyCheck(otherpk, true);
|
||||
if (!this._isPriv)
|
||||
throw (new Error('DH exchange has not been initialized with ' +
|
||||
'a private key yet'));
|
||||
|
||||
var pub;
|
||||
if (this._algo === 'dsa') {
|
||||
return (this._dh.computeSecret(
|
||||
otherpk.part.y.data));
|
||||
|
||||
} else if (this._algo === 'ecdsa') {
|
||||
if (CRYPTO_HAVE_ECDH) {
|
||||
return (this._dh.computeSecret(
|
||||
otherpk.part.Q.data));
|
||||
} else {
|
||||
pub = new ECPublic(
|
||||
this._ecParams, otherpk.part.Q.data);
|
||||
return (this._priv.deriveSharedSecret(pub));
|
||||
}
|
||||
|
||||
} else if (this._algo === 'curve25519') {
|
||||
pub = otherpk.part.R.data;
|
||||
if (pub[0] === 0x00)
|
||||
pub = pub.slice(1);
|
||||
|
||||
var secret = ed.dh.computeKey(
|
||||
this._priv.toString('binary'),
|
||||
pub.toString('binary'));
|
||||
|
||||
return (new Buffer(secret, 'binary'));
|
||||
}
|
||||
|
||||
throw (new Error('Invalid algorithm: ' + this._algo));
|
||||
};
|
||||
|
||||
DiffieHellman.prototype.generateKey = function () {
|
||||
var parts = [];
|
||||
var priv, pub;
|
||||
if (this._algo === 'dsa') {
|
||||
this._dh.generateKeys();
|
||||
|
||||
parts.push({name: 'p', data: this._p.data});
|
||||
parts.push({name: 'q', data: this._key.part.q.data});
|
||||
parts.push({name: 'g', data: this._g.data});
|
||||
parts.push({name: 'y', data: this._dh.getPublicKey()});
|
||||
parts.push({name: 'x', data: this._dh.getPrivateKey()});
|
||||
this._key = new PrivateKey({
|
||||
type: 'dsa',
|
||||
parts: parts
|
||||
});
|
||||
this._isPriv = true;
|
||||
return (this._key);
|
||||
|
||||
} else if (this._algo === 'ecdsa') {
|
||||
if (CRYPTO_HAVE_ECDH) {
|
||||
this._dh.generateKeys();
|
||||
|
||||
parts.push({name: 'curve',
|
||||
data: new Buffer(this._curve)});
|
||||
parts.push({name: 'Q', data: this._dh.getPublicKey()});
|
||||
parts.push({name: 'd', data: this._dh.getPrivateKey()});
|
||||
this._key = new PrivateKey({
|
||||
type: 'ecdsa',
|
||||
curve: this._curve,
|
||||
parts: parts
|
||||
});
|
||||
this._isPriv = true;
|
||||
return (this._key);
|
||||
|
||||
} else {
|
||||
var n = this._ecParams.getN();
|
||||
var r = new jsbn(crypto.randomBytes(n.bitLength()));
|
||||
var n1 = n.subtract(jsbn.ONE);
|
||||
priv = r.mod(n1).add(jsbn.ONE);
|
||||
pub = this._ecParams.getG().multiply(priv);
|
||||
|
||||
priv = new Buffer(priv.toByteArray());
|
||||
pub = new Buffer(this._ecParams.getCurve().
|
||||
encodePointHex(pub), 'hex');
|
||||
|
||||
this._priv = new ECPrivate(this._ecParams, priv);
|
||||
|
||||
parts.push({name: 'curve',
|
||||
data: new Buffer(this._curve)});
|
||||
parts.push({name: 'Q', data: pub});
|
||||
parts.push({name: 'd', data: priv});
|
||||
|
||||
this._key = new PrivateKey({
|
||||
type: 'ecdsa',
|
||||
curve: this._curve,
|
||||
parts: parts
|
||||
});
|
||||
this._isPriv = true;
|
||||
return (this._key);
|
||||
}
|
||||
|
||||
} else if (this._algo === 'curve25519') {
|
||||
priv = ed.dh.generateKey();
|
||||
pub = ed.dh.publicKey(priv);
|
||||
this._priv = priv = new Buffer(priv, 'binary');
|
||||
pub = new Buffer(pub, 'binary');
|
||||
|
||||
parts.push({name: 'R', data: pub});
|
||||
parts.push({name: 'r', data: Buffer.concat([priv, pub])});
|
||||
this._key = new PrivateKey({
|
||||
type: 'curve25519',
|
||||
parts: parts
|
||||
});
|
||||
this._isPriv = true;
|
||||
return (this._key);
|
||||
}
|
||||
|
||||
throw (new Error('Invalid algorithm: ' + this._algo));
|
||||
};
|
||||
DiffieHellman.prototype.generateKeys = DiffieHellman.prototype.generateKey;
|
||||
|
||||
/* These are helpers for using ecc-jsbn (for node 0.10 compatibility). */
|
||||
|
||||
function X9ECParameters(name) {
|
||||
var params = algs.curves[name];
|
||||
assert.object(params);
|
||||
|
||||
var p = new jsbn(params.p);
|
||||
var a = new jsbn(params.a);
|
||||
var b = new jsbn(params.b);
|
||||
var n = new jsbn(params.n);
|
||||
var h = jsbn.ONE;
|
||||
var curve = new ec.ECCurveFp(p, a, b);
|
||||
var G = curve.decodePointHex(params.G.toString('hex'));
|
||||
|
||||
this.curve = curve;
|
||||
this.g = G;
|
||||
this.n = n;
|
||||
this.h = h;
|
||||
}
|
||||
X9ECParameters.prototype.getCurve = function () { return (this.curve); };
|
||||
X9ECParameters.prototype.getG = function () { return (this.g); };
|
||||
X9ECParameters.prototype.getN = function () { return (this.n); };
|
||||
X9ECParameters.prototype.getH = function () { return (this.h); };
|
||||
|
||||
function ECPublic(params, buffer) {
|
||||
this._params = params;
|
||||
if (buffer[0] === 0x00)
|
||||
buffer = buffer.slice(1);
|
||||
this._pub = params.getCurve().decodePointHex(buffer.toString('hex'));
|
||||
}
|
||||
|
||||
function ECPrivate(params, buffer) {
|
||||
this._params = params;
|
||||
this._priv = new jsbn(utils.mpNormalize(buffer));
|
||||
}
|
||||
ECPrivate.prototype.deriveSharedSecret = function (pubKey) {
|
||||
assert.ok(pubKey instanceof ECPublic);
|
||||
var S = pubKey._pub.multiply(this._priv);
|
||||
return (new Buffer(S.getX().toBigInteger().toByteArray()));
|
||||
};
|
||||
94
node_modules/sshpk/lib/ed-compat.js
generated
vendored
Normal file
94
node_modules/sshpk/lib/ed-compat.js
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
// Copyright 2015 Joyent, Inc.
|
||||
|
||||
module.exports = {
|
||||
Verifier: Verifier,
|
||||
Signer: Signer
|
||||
};
|
||||
|
||||
var nacl;
|
||||
var stream = require('stream');
|
||||
var util = require('util');
|
||||
var assert = require('assert-plus');
|
||||
var Signature = require('./signature');
|
||||
|
||||
function Verifier(key, hashAlgo) {
|
||||
if (nacl === undefined)
|
||||
nacl = require('tweetnacl');
|
||||
|
||||
if (hashAlgo.toLowerCase() !== 'sha512')
|
||||
throw (new Error('ED25519 only supports the use of ' +
|
||||
'SHA-512 hashes'));
|
||||
|
||||
this.key = key;
|
||||
this.chunks = [];
|
||||
|
||||
stream.Writable.call(this, {});
|
||||
}
|
||||
util.inherits(Verifier, stream.Writable);
|
||||
|
||||
Verifier.prototype._write = function (chunk, enc, cb) {
|
||||
this.chunks.push(chunk);
|
||||
cb();
|
||||
};
|
||||
|
||||
Verifier.prototype.update = function (chunk) {
|
||||
if (typeof (chunk) === 'string')
|
||||
chunk = new Buffer(chunk, 'binary');
|
||||
this.chunks.push(chunk);
|
||||
};
|
||||
|
||||
Verifier.prototype.verify = function (signature, fmt) {
|
||||
var sig;
|
||||
if (Signature.isSignature(signature, [2, 0])) {
|
||||
sig = signature.toBuffer('raw');
|
||||
|
||||
} else if (typeof (signature) === 'string') {
|
||||
sig = new Buffer(signature, 'base64');
|
||||
|
||||
} else if (Signature.isSignature(signature, [1, 0])) {
|
||||
throw (new Error('signature was created by too old ' +
|
||||
'a version of sshpk and cannot be verified'));
|
||||
}
|
||||
|
||||
assert.buffer(sig);
|
||||
return (nacl.sign.detached.verify(
|
||||
new Uint8Array(Buffer.concat(this.chunks)),
|
||||
new Uint8Array(sig),
|
||||
new Uint8Array(this.key.part.R.data)));
|
||||
};
|
||||
|
||||
function Signer(key, hashAlgo) {
|
||||
if (nacl === undefined)
|
||||
nacl = require('tweetnacl');
|
||||
|
||||
if (hashAlgo.toLowerCase() !== 'sha512')
|
||||
throw (new Error('ED25519 only supports the use of ' +
|
||||
'SHA-512 hashes'));
|
||||
|
||||
this.key = key;
|
||||
this.chunks = [];
|
||||
|
||||
stream.Writable.call(this, {});
|
||||
}
|
||||
util.inherits(Signer, stream.Writable);
|
||||
|
||||
Signer.prototype._write = function (chunk, enc, cb) {
|
||||
this.chunks.push(chunk);
|
||||
cb();
|
||||
};
|
||||
|
||||
Signer.prototype.update = function (chunk) {
|
||||
if (typeof (chunk) === 'string')
|
||||
chunk = new Buffer(chunk, 'binary');
|
||||
this.chunks.push(chunk);
|
||||
};
|
||||
|
||||
Signer.prototype.sign = function () {
|
||||
var sig = nacl.sign.detached(
|
||||
new Uint8Array(Buffer.concat(this.chunks)),
|
||||
new Uint8Array(this.key.part.r.data));
|
||||
var sigBuf = new Buffer(sig);
|
||||
var sigObj = Signature.parse(sigBuf, 'ed25519', 'raw');
|
||||
sigObj.hashAlgorithm = 'sha512';
|
||||
return (sigObj);
|
||||
};
|
||||
58
node_modules/sshpk/lib/errors.js
generated
vendored
Normal file
58
node_modules/sshpk/lib/errors.js
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright 2015 Joyent, Inc.
|
||||
|
||||
var assert = require('assert-plus');
|
||||
var util = require('util');
|
||||
|
||||
function FingerprintFormatError(fp, format) {
|
||||
if (Error.captureStackTrace)
|
||||
Error.captureStackTrace(this, FingerprintFormatError);
|
||||
this.name = 'FingerprintFormatError';
|
||||
this.fingerprint = fp;
|
||||
this.format = format;
|
||||
this.message = 'Fingerprint format is not supported, or is invalid: ';
|
||||
if (fp !== undefined)
|
||||
this.message += ' fingerprint = ' + fp;
|
||||
if (format !== undefined)
|
||||
this.message += ' format = ' + format;
|
||||
}
|
||||
util.inherits(FingerprintFormatError, Error);
|
||||
|
||||
function InvalidAlgorithmError(alg) {
|
||||
if (Error.captureStackTrace)
|
||||
Error.captureStackTrace(this, InvalidAlgorithmError);
|
||||
this.name = 'InvalidAlgorithmError';
|
||||
this.algorithm = alg;
|
||||
this.message = 'Algorithm "' + alg + '" is not supported';
|
||||
}
|
||||
util.inherits(InvalidAlgorithmError, Error);
|
||||
|
||||
function KeyParseError(name, format, innerErr) {
|
||||
if (Error.captureStackTrace)
|
||||
Error.captureStackTrace(this, KeyParseError);
|
||||
this.name = 'KeyParseError';
|
||||
this.format = format;
|
||||
this.keyName = name;
|
||||
this.innerErr = innerErr;
|
||||
this.message = 'Failed to parse ' + name + ' as a valid ' + format +
|
||||
' format key: ' + innerErr.message;
|
||||
}
|
||||
util.inherits(KeyParseError, Error);
|
||||
|
||||
function SignatureParseError(type, format, innerErr) {
|
||||
if (Error.captureStackTrace)
|
||||
Error.captureStackTrace(this, SignatureParseError);
|
||||
this.name = 'SignatureParseError';
|
||||
this.type = type;
|
||||
this.format = format;
|
||||
this.innerErr = innerErr;
|
||||
this.message = 'Failed to parse the given data as a ' + type +
|
||||
' signature in ' + format + ' format: ' + innerErr.message;
|
||||
}
|
||||
util.inherits(SignatureParseError, Error);
|
||||
|
||||
module.exports = {
|
||||
FingerprintFormatError: FingerprintFormatError,
|
||||
InvalidAlgorithmError: InvalidAlgorithmError,
|
||||
KeyParseError: KeyParseError,
|
||||
SignatureParseError: SignatureParseError
|
||||
};
|
||||
140
node_modules/sshpk/lib/fingerprint.js
generated
vendored
Normal file
140
node_modules/sshpk/lib/fingerprint.js
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright 2015 Joyent, Inc.
|
||||
|
||||
module.exports = Fingerprint;
|
||||
|
||||
var assert = require('assert-plus');
|
||||
var algs = require('./algs');
|
||||
var crypto = require('crypto');
|
||||
var errs = require('./errors');
|
||||
var Key = require('./key');
|
||||
var utils = require('./utils');
|
||||
|
||||
var FingerprintFormatError = errs.FingerprintFormatError;
|
||||
var InvalidAlgorithmError = errs.InvalidAlgorithmError;
|
||||
|
||||
function Fingerprint(opts) {
|
||||
assert.object(opts, 'options');
|
||||
assert.buffer(opts.hash, 'options.hash');
|
||||
assert.string(opts.algorithm, 'options.algorithm');
|
||||
|
||||
this.algorithm = opts.algorithm.toLowerCase();
|
||||
if (algs.hashAlgs[this.algorithm] !== true)
|
||||
throw (new InvalidAlgorithmError(this.algorithm));
|
||||
|
||||
this.hash = opts.hash;
|
||||
}
|
||||
|
||||
Fingerprint.prototype.toString = function (format) {
|
||||
if (format === undefined) {
|
||||
if (this.algorithm === 'md5')
|
||||
format = 'hex';
|
||||
else
|
||||
format = 'base64';
|
||||
}
|
||||
assert.string(format);
|
||||
|
||||
switch (format) {
|
||||
case 'hex':
|
||||
return (addColons(this.hash.toString('hex')));
|
||||
case 'base64':
|
||||
return (sshBase64Format(this.algorithm,
|
||||
this.hash.toString('base64')));
|
||||
default:
|
||||
throw (new FingerprintFormatError(undefined, format));
|
||||
}
|
||||
};
|
||||
|
||||
Fingerprint.prototype.matches = function (key) {
|
||||
assert.object(key, 'key');
|
||||
utils.assertCompatible(key, Key, [1, 0], 'key');
|
||||
|
||||
var theirHash = key.hash(this.algorithm);
|
||||
var theirHash2 = crypto.createHash(this.algorithm).
|
||||
update(theirHash).digest('base64');
|
||||
|
||||
if (this.hash2 === undefined)
|
||||
this.hash2 = crypto.createHash(this.algorithm).
|
||||
update(this.hash).digest('base64');
|
||||
|
||||
return (this.hash2 === theirHash2);
|
||||
};
|
||||
|
||||
Fingerprint.parse = function (fp, enAlgs) {
|
||||
assert.string(fp, 'fingerprint');
|
||||
|
||||
var alg, hash;
|
||||
assert.optionalArrayOfString(enAlgs, 'algorithms');
|
||||
|
||||
var parts = fp.split(':');
|
||||
if (parts.length == 2) {
|
||||
alg = parts[0].toLowerCase();
|
||||
/*JSSTYLED*/
|
||||
var base64RE = /^[A-Za-z0-9+\/=]+$/;
|
||||
if (!base64RE.test(parts[1]))
|
||||
throw (new FingerprintFormatError(fp));
|
||||
try {
|
||||
hash = new Buffer(parts[1], 'base64');
|
||||
} catch (e) {
|
||||
throw (new FingerprintFormatError(fp));
|
||||
}
|
||||
} else if (parts.length > 2) {
|
||||
alg = 'md5';
|
||||
if (parts[0].toLowerCase() === 'md5')
|
||||
parts = parts.slice(1);
|
||||
parts = parts.join('');
|
||||
/*JSSTYLED*/
|
||||
var md5RE = /^[a-fA-F0-9]+$/;
|
||||
if (!md5RE.test(parts))
|
||||
throw (new FingerprintFormatError(fp));
|
||||
try {
|
||||
hash = new Buffer(parts, 'hex');
|
||||
} catch (e) {
|
||||
throw (new FingerprintFormatError(fp));
|
||||
}
|
||||
}
|
||||
|
||||
if (alg === undefined)
|
||||
throw (new FingerprintFormatError(fp));
|
||||
|
||||
if (algs.hashAlgs[alg] === undefined)
|
||||
throw (new InvalidAlgorithmError(alg));
|
||||
|
||||
if (enAlgs !== undefined) {
|
||||
enAlgs = enAlgs.map(function (a) { return a.toLowerCase(); });
|
||||
if (enAlgs.indexOf(alg) === -1)
|
||||
throw (new InvalidAlgorithmError(alg));
|
||||
}
|
||||
|
||||
return (new Fingerprint({algorithm: alg, hash: hash}));
|
||||
};
|
||||
|
||||
function addColons(s) {
|
||||
/*JSSTYLED*/
|
||||
return (s.replace(/(.{2})(?=.)/g, '$1:'));
|
||||
}
|
||||
|
||||
function base64Strip(s) {
|
||||
/*JSSTYLED*/
|
||||
return (s.replace(/=*$/, ''));
|
||||
}
|
||||
|
||||
function sshBase64Format(alg, h) {
|
||||
return (alg.toUpperCase() + ':' + base64Strip(h));
|
||||
}
|
||||
|
||||
Fingerprint.isFingerprint = function (obj, ver) {
|
||||
return (utils.isCompatible(obj, Fingerprint, ver));
|
||||
};
|
||||
|
||||
/*
|
||||
* API versions for Fingerprint:
|
||||
* [1,0] -- initial ver
|
||||
* [1,1] -- first tagged ver
|
||||
*/
|
||||
Fingerprint.prototype._sshpkApiVersion = [1, 1];
|
||||
|
||||
Fingerprint._oldVersionDetect = function (obj) {
|
||||
assert.func(obj.toString);
|
||||
assert.func(obj.matches);
|
||||
return ([1, 0]);
|
||||
};
|
||||
73
node_modules/sshpk/lib/formats/auto.js
generated
vendored
Normal file
73
node_modules/sshpk/lib/formats/auto.js
generated
vendored
Normal file
@@ -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) {
|
||||
if (typeof (buf) === 'string') {
|
||||
if (buf.trim().match(/^[-]+[ ]*BEGIN/))
|
||||
return (pem.read(buf));
|
||||
if (buf.match(/^\s*ssh-[a-z]/))
|
||||
return (ssh.read(buf));
|
||||
if (buf.match(/^\s*ecdsa-/))
|
||||
return (ssh.read(buf));
|
||||
buf = new Buffer(buf, 'binary');
|
||||
} else {
|
||||
assert.buffer(buf);
|
||||
if (findPEMHeader(buf))
|
||||
return (pem.read(buf));
|
||||
if (findSSHHeader(buf))
|
||||
return (ssh.read(buf));
|
||||
}
|
||||
if (buf.readUInt32BE(0) < buf.length)
|
||||
return (rfc4253.read(buf));
|
||||
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) {
|
||||
throw (new Error('"auto" format cannot be used for writing'));
|
||||
}
|
||||
152
node_modules/sshpk/lib/formats/pem.js
generated
vendored
Normal file
152
node_modules/sshpk/lib/formats/pem.js
generated
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
// Copyright 2015 Joyent, Inc.
|
||||
|
||||
module.exports = {
|
||||
read: read,
|
||||
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 pkcs1 = require('./pkcs1');
|
||||
var pkcs8 = require('./pkcs8');
|
||||
var sshpriv = require('./ssh-private');
|
||||
var rfc4253 = require('./rfc4253');
|
||||
|
||||
/*
|
||||
* 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, 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];
|
||||
}
|
||||
if (headers['proc-type']) {
|
||||
var parts = headers['proc-type'].split(',');
|
||||
if (parts[0] === '4' && parts[1] === 'ENCRYPTED') {
|
||||
throw (new Error('PEM key is encrypted ' +
|
||||
'(password-protected). Please use the ' +
|
||||
'SSH agent or decrypt the key.'));
|
||||
}
|
||||
}
|
||||
|
||||
/* Chop off the first and last lines */
|
||||
lines = lines.slice(0, -1).join('');
|
||||
buf = new Buffer(lines, 'base64');
|
||||
|
||||
/* The new OpenSSH internal format abuses PEM headers */
|
||||
if (alg && alg.toLowerCase() === 'openssh')
|
||||
return (sshpriv.readSSHPrivate(type, buf));
|
||||
if (alg && alg.toLowerCase() === 'ssh2')
|
||||
return (rfc4253.readType(type, buf));
|
||||
|
||||
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, 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));
|
||||
}
|
||||
320
node_modules/sshpk/lib/formats/pkcs1.js
generated
vendored
Normal file
320
node_modules/sshpk/lib/formats/pkcs1.js
generated
vendored
Normal file
@@ -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) {
|
||||
return (pem.read(buf, 'pkcs1'));
|
||||
}
|
||||
|
||||
function write(key) {
|
||||
return (pem.write(key, '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();
|
||||
}
|
||||
510
node_modules/sshpk/lib/formats/pkcs8.js
generated
vendored
Normal file
510
node_modules/sshpk/lib/formats/pkcs8.js
generated
vendored
Normal file
@@ -0,0 +1,510 @@
|
||||
// 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) {
|
||||
return (pem.read(buf, 'pkcs8'));
|
||||
}
|
||||
|
||||
function write(key) {
|
||||
return (pem.write(key, '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 oid = der.readOID();
|
||||
switch (oid) {
|
||||
case '1.2.840.113549.1.1.1':
|
||||
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) {
|
||||
// Null -- XXX this probably isn't good practice
|
||||
der.readByte();
|
||||
der.readByte();
|
||||
|
||||
// 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.readByte();
|
||||
der.readByte();
|
||||
|
||||
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();
|
||||
}
|
||||
145
node_modules/sshpk/lib/formats/rfc4253.js
generated
vendored
Normal file
145
node_modules/sshpk/lib/formats/rfc4253.js
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
// 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) {
|
||||
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) {
|
||||
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;
|
||||
data = utils.mpNormalize(data);
|
||||
buf.writeBuffer(data);
|
||||
}
|
||||
|
||||
return (buf.toBuffer());
|
||||
}
|
||||
138
node_modules/sshpk/lib/formats/ssh-private.js
generated
vendored
Normal file
138
node_modules/sshpk/lib/formats/ssh-private.js
generated
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
// 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');
|
||||
|
||||
function read(buf) {
|
||||
return (pem.read(buf));
|
||||
}
|
||||
|
||||
var MAGIC = 'openssh-key-v1';
|
||||
|
||||
function readSSHPrivate(type, buf) {
|
||||
buf = new SSHBuffer({buffer: buf});
|
||||
|
||||
var magic = buf.readCString();
|
||||
assert.strictEqual(magic, MAGIC, 'bad magic string');
|
||||
|
||||
var cipher = buf.readString();
|
||||
var kdf = buf.readString();
|
||||
|
||||
/* We only support unencrypted keys. */
|
||||
if (cipher !== 'none' || kdf !== 'none') {
|
||||
throw (new Error('OpenSSH-format key is encrypted ' +
|
||||
'(password-protected). Please use the SSH agent ' +
|
||||
'or decrypt the key.'));
|
||||
}
|
||||
|
||||
/* Skip over kdfoptions. */
|
||||
buf.readString();
|
||||
|
||||
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');
|
||||
|
||||
buf = new SSHBuffer({buffer: privKeyBlob});
|
||||
|
||||
var checkInt1 = buf.readInt();
|
||||
var checkInt2 = buf.readInt();
|
||||
assert.strictEqual(checkInt1, checkInt2, 'checkints do not match');
|
||||
|
||||
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) {
|
||||
var pubKey;
|
||||
if (PrivateKey.isPrivateKey(key))
|
||||
pubKey = key.toPublic();
|
||||
else
|
||||
pubKey = key;
|
||||
|
||||
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 % 8 !== 0)
|
||||
privBuf.writeChar(n++);
|
||||
}
|
||||
|
||||
var buf = new SSHBuffer({});
|
||||
|
||||
buf.writeCString(MAGIC);
|
||||
buf.writeString('none'); /* cipher */
|
||||
buf.writeString('none'); /* kdf */
|
||||
buf.writeBuffer(new Buffer(0)); /* kdfoptions */
|
||||
|
||||
buf.writeInt(1); /* nkeys */
|
||||
buf.writeBuffer(pubKey.toBuffer('rfc4253'));
|
||||
|
||||
if (privBuf)
|
||||
buf.writeBuffer(privBuf.toBuffer());
|
||||
|
||||
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));
|
||||
}
|
||||
114
node_modules/sshpk/lib/formats/ssh.js
generated
vendored
Normal file
114
node_modules/sshpk/lib/formats/ssh.js
generated
vendored
Normal file
@@ -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) {
|
||||
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) {
|
||||
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(' ')));
|
||||
}
|
||||
25
node_modules/sshpk/lib/index.js
generated
vendored
Normal file
25
node_modules/sshpk/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2015 Joyent, Inc.
|
||||
|
||||
var Key = require('./key');
|
||||
var Fingerprint = require('./fingerprint');
|
||||
var Signature = require('./signature');
|
||||
var PrivateKey = require('./private-key');
|
||||
var errs = require('./errors');
|
||||
|
||||
module.exports = {
|
||||
/* top-level classes */
|
||||
Key: Key,
|
||||
parseKey: Key.parse,
|
||||
Fingerprint: Fingerprint,
|
||||
parseFingerprint: Fingerprint.parse,
|
||||
Signature: Signature,
|
||||
parseSignature: Signature.parse,
|
||||
PrivateKey: PrivateKey,
|
||||
parsePrivateKey: PrivateKey.parse,
|
||||
|
||||
/* errors */
|
||||
FingerprintFormatError: errs.FingerprintFormatError,
|
||||
InvalidAlgorithmError: errs.InvalidAlgorithmError,
|
||||
KeyParseError: errs.KeyParseError,
|
||||
SignatureParseError: errs.SignatureParseError
|
||||
};
|
||||
260
node_modules/sshpk/lib/key.js
generated
vendored
Normal file
260
node_modules/sshpk/lib/key.js
generated
vendored
Normal file
@@ -0,0 +1,260 @@
|
||||
// Copyright 2015 Joyent, Inc.
|
||||
|
||||
module.exports = Key;
|
||||
|
||||
var assert = require('assert-plus');
|
||||
var algs = require('./algs');
|
||||
var crypto = require('crypto');
|
||||
var Fingerprint = require('./fingerprint');
|
||||
var Signature = require('./signature');
|
||||
var DiffieHellman = require('./dhe');
|
||||
var errs = require('./errors');
|
||||
var utils = require('./utils');
|
||||
var PrivateKey = require('./private-key');
|
||||
var edCompat;
|
||||
|
||||
try {
|
||||
edCompat = require('./ed-compat');
|
||||
} catch (e) {
|
||||
/* Just continue through, and bail out if we try to use it. */
|
||||
}
|
||||
|
||||
var InvalidAlgorithmError = errs.InvalidAlgorithmError;
|
||||
var KeyParseError = errs.KeyParseError;
|
||||
|
||||
var formats = {};
|
||||
formats['auto'] = require('./formats/auto');
|
||||
formats['pem'] = require('./formats/pem');
|
||||
formats['pkcs1'] = require('./formats/pkcs1');
|
||||
formats['pkcs8'] = require('./formats/pkcs8');
|
||||
formats['rfc4253'] = require('./formats/rfc4253');
|
||||
formats['ssh'] = require('./formats/ssh');
|
||||
formats['ssh-private'] = require('./formats/ssh-private');
|
||||
formats['openssh'] = formats['ssh-private'];
|
||||
|
||||
function Key(opts) {
|
||||
assert.object(opts, 'options');
|
||||
assert.arrayOfObject(opts.parts, 'options.parts');
|
||||
assert.string(opts.type, 'options.type');
|
||||
assert.optionalString(opts.comment, 'options.comment');
|
||||
|
||||
var algInfo = algs.info[opts.type];
|
||||
if (typeof (algInfo) !== 'object')
|
||||
throw (new InvalidAlgorithmError(opts.type));
|
||||
|
||||
var partLookup = {};
|
||||
for (var i = 0; i < opts.parts.length; ++i) {
|
||||
var part = opts.parts[i];
|
||||
partLookup[part.name] = part;
|
||||
}
|
||||
|
||||
this.type = opts.type;
|
||||
this.parts = opts.parts;
|
||||
this.part = partLookup;
|
||||
this.comment = undefined;
|
||||
this.source = opts.source;
|
||||
|
||||
/* for speeding up hashing/fingerprint operations */
|
||||
this._rfc4253Cache = opts._rfc4253Cache;
|
||||
this._hashCache = {};
|
||||
|
||||
var sz;
|
||||
this.curve = undefined;
|
||||
if (this.type === 'ecdsa') {
|
||||
var curve = this.part.curve.data.toString();
|
||||
this.curve = curve;
|
||||
sz = algs.curves[curve].size;
|
||||
} else if (this.type === 'ed25519') {
|
||||
sz = 256;
|
||||
this.curve = 'curve25519';
|
||||
} else {
|
||||
var szPart = this.part[algInfo.sizePart];
|
||||
sz = szPart.data.length;
|
||||
sz = sz * 8 - utils.countZeros(szPart.data);
|
||||
}
|
||||
this.size = sz;
|
||||
}
|
||||
|
||||
Key.formats = formats;
|
||||
|
||||
Key.prototype.toBuffer = function (format) {
|
||||
if (format === undefined)
|
||||
format = 'ssh';
|
||||
assert.string(format, 'format');
|
||||
assert.object(formats[format], 'formats[format]');
|
||||
|
||||
if (format === 'rfc4253') {
|
||||
if (this._rfc4253Cache === undefined)
|
||||
this._rfc4253Cache = formats['rfc4253'].write(this);
|
||||
return (this._rfc4253Cache);
|
||||
}
|
||||
|
||||
return (formats[format].write(this));
|
||||
};
|
||||
|
||||
Key.prototype.toString = function (format) {
|
||||
return (this.toBuffer(format).toString());
|
||||
};
|
||||
|
||||
Key.prototype.hash = function (algo) {
|
||||
assert.string(algo, 'algorithm');
|
||||
algo = algo.toLowerCase();
|
||||
if (algs.hashAlgs[algo] === undefined)
|
||||
throw (new InvalidAlgorithmError(algo));
|
||||
|
||||
if (this._hashCache[algo])
|
||||
return (this._hashCache[algo]);
|
||||
|
||||
var hash = crypto.createHash(algo).
|
||||
update(this.toBuffer('rfc4253')).digest();
|
||||
/* Workaround for node 0.8 */
|
||||
if (typeof (hash) === 'string')
|
||||
hash = new Buffer(hash, 'binary');
|
||||
this._hashCache[algo] = hash;
|
||||
return (hash);
|
||||
};
|
||||
|
||||
Key.prototype.fingerprint = function (algo) {
|
||||
if (algo === undefined)
|
||||
algo = 'sha256';
|
||||
assert.string(algo, 'algorithm');
|
||||
var opts = {
|
||||
hash: this.hash(algo),
|
||||
algorithm: algo
|
||||
};
|
||||
return (new Fingerprint(opts));
|
||||
};
|
||||
|
||||
Key.prototype.defaultHashAlgorithm = function () {
|
||||
var hashAlgo = 'sha1';
|
||||
if (this.type === 'rsa')
|
||||
hashAlgo = 'sha256';
|
||||
if (this.type === 'dsa' && this.size > 1024)
|
||||
hashAlgo = 'sha256';
|
||||
if (this.type === 'ed25519')
|
||||
hashAlgo = 'sha512';
|
||||
if (this.type === 'ecdsa') {
|
||||
if (this.size <= 256)
|
||||
hashAlgo = 'sha256';
|
||||
else if (this.size <= 384)
|
||||
hashAlgo = 'sha384';
|
||||
else
|
||||
hashAlgo = 'sha512';
|
||||
}
|
||||
return (hashAlgo);
|
||||
};
|
||||
|
||||
Key.prototype.createVerify = function (hashAlgo) {
|
||||
if (hashAlgo === undefined)
|
||||
hashAlgo = this.defaultHashAlgorithm();
|
||||
assert.string(hashAlgo, 'hash algorithm');
|
||||
|
||||
/* ED25519 is not supported by OpenSSL, use a javascript impl. */
|
||||
if (this.type === 'ed25519' && edCompat !== undefined)
|
||||
return (new edCompat.Verifier(this, hashAlgo));
|
||||
if (this.type === 'curve25519')
|
||||
throw (new Error('Curve25519 keys are not suitable for ' +
|
||||
'signing or verification'));
|
||||
|
||||
var v, nm, err;
|
||||
try {
|
||||
nm = this.type.toUpperCase() + '-';
|
||||
if (this.type === 'ecdsa')
|
||||
nm = 'ecdsa-with-';
|
||||
nm += hashAlgo.toUpperCase();
|
||||
v = crypto.createVerify(nm);
|
||||
} catch (e) {
|
||||
err = e;
|
||||
}
|
||||
if (v === undefined || (err instanceof Error &&
|
||||
err.message.match(/Unknown message digest/))) {
|
||||
nm = 'RSA-';
|
||||
nm += hashAlgo.toUpperCase();
|
||||
v = crypto.createVerify(nm);
|
||||
}
|
||||
assert.ok(v, 'failed to create verifier');
|
||||
var oldVerify = v.verify.bind(v);
|
||||
var key = this.toBuffer('pkcs8');
|
||||
v.verify = function (signature, fmt) {
|
||||
if (Signature.isSignature(signature, [2, 0])) {
|
||||
return (oldVerify(key, signature.toBuffer('asn1')));
|
||||
|
||||
} else if (typeof (signature) === 'string' ||
|
||||
Buffer.isBuffer(signature)) {
|
||||
return (oldVerify(key, signature, fmt));
|
||||
|
||||
/*
|
||||
* Avoid doing this on valid arguments, walking the prototype
|
||||
* chain can be quite slow.
|
||||
*/
|
||||
} else if (Signature.isSignature(signature, [1, 0])) {
|
||||
throw (new Error('signature was created by too old ' +
|
||||
'a version of sshpk and cannot be verified'));
|
||||
|
||||
} else {
|
||||
throw (new TypeError('signature must be a string, ' +
|
||||
'Buffer, or Signature object'));
|
||||
}
|
||||
};
|
||||
return (v);
|
||||
};
|
||||
|
||||
Key.prototype.createDiffieHellman = function () {
|
||||
if (this.type === 'rsa')
|
||||
throw (new Error('RSA keys do not support Diffie-Hellman'));
|
||||
|
||||
return (new DiffieHellman(this));
|
||||
};
|
||||
Key.prototype.createDH = Key.prototype.createDiffieHellman;
|
||||
|
||||
Key.parse = function (data, format, name) {
|
||||
if (typeof (data) !== 'string')
|
||||
assert.buffer(data, 'data');
|
||||
if (format === undefined)
|
||||
format = 'auto';
|
||||
assert.string(format, 'format');
|
||||
if (name === undefined)
|
||||
name = '(unnamed)';
|
||||
|
||||
assert.object(formats[format], 'formats[format]');
|
||||
|
||||
try {
|
||||
var k = formats[format].read(data);
|
||||
if (k instanceof PrivateKey)
|
||||
k = k.toPublic();
|
||||
if (!k.comment)
|
||||
k.comment = name;
|
||||
return (k);
|
||||
} catch (e) {
|
||||
throw (new KeyParseError(name, format, e));
|
||||
}
|
||||
};
|
||||
|
||||
Key.isKey = function (obj, ver) {
|
||||
return (utils.isCompatible(obj, Key, ver));
|
||||
};
|
||||
|
||||
/*
|
||||
* API versions for Key:
|
||||
* [1,0] -- initial ver, may take Signature for createVerify or may not
|
||||
* [1,1] -- added pkcs1, pkcs8 formats
|
||||
* [1,2] -- added auto, ssh-private, openssh formats
|
||||
* [1,3] -- added defaultHashAlgorithm
|
||||
* [1,4] -- added ed support, createDH
|
||||
* [1,5] -- first explicitly tagged version
|
||||
*/
|
||||
Key.prototype._sshpkApiVersion = [1, 5];
|
||||
|
||||
Key._oldVersionDetect = function (obj) {
|
||||
assert.func(obj.toBuffer);
|
||||
assert.func(obj.fingerprint);
|
||||
if (obj.createDH)
|
||||
return ([1, 4]);
|
||||
if (obj.defaultHashAlgorithm)
|
||||
return ([1, 3]);
|
||||
if (obj.formats['auto'])
|
||||
return ([1, 2]);
|
||||
if (obj.formats['pkcs1'])
|
||||
return ([1, 1]);
|
||||
return ([1, 0]);
|
||||
};
|
||||
224
node_modules/sshpk/lib/private-key.js
generated
vendored
Normal file
224
node_modules/sshpk/lib/private-key.js
generated
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
// Copyright 2015 Joyent, Inc.
|
||||
|
||||
module.exports = PrivateKey;
|
||||
|
||||
var assert = require('assert-plus');
|
||||
var algs = require('./algs');
|
||||
var crypto = require('crypto');
|
||||
var Fingerprint = require('./fingerprint');
|
||||
var Signature = require('./signature');
|
||||
var errs = require('./errors');
|
||||
var util = require('util');
|
||||
var utils = require('./utils');
|
||||
var edCompat;
|
||||
var ed;
|
||||
|
||||
try {
|
||||
edCompat = require('./ed-compat');
|
||||
} catch (e) {
|
||||
/* Just continue through, and bail out if we try to use it. */
|
||||
}
|
||||
|
||||
var Key = require('./key');
|
||||
|
||||
var InvalidAlgorithmError = errs.InvalidAlgorithmError;
|
||||
var KeyParseError = errs.KeyParseError;
|
||||
|
||||
var formats = {};
|
||||
formats['auto'] = require('./formats/auto');
|
||||
formats['pem'] = require('./formats/pem');
|
||||
formats['pkcs1'] = require('./formats/pkcs1');
|
||||
formats['pkcs8'] = require('./formats/pkcs8');
|
||||
formats['rfc4253'] = require('./formats/rfc4253');
|
||||
formats['ssh-private'] = require('./formats/ssh-private');
|
||||
formats['openssh'] = formats['ssh-private'];
|
||||
formats['ssh'] = formats['ssh-private'];
|
||||
|
||||
function PrivateKey(opts) {
|
||||
assert.object(opts, 'options');
|
||||
Key.call(this, opts);
|
||||
|
||||
this._pubCache = undefined;
|
||||
}
|
||||
util.inherits(PrivateKey, Key);
|
||||
|
||||
PrivateKey.formats = formats;
|
||||
|
||||
PrivateKey.prototype.toBuffer = function (format) {
|
||||
if (format === undefined)
|
||||
format = 'pkcs1';
|
||||
assert.string(format, 'format');
|
||||
assert.object(formats[format], 'formats[format]');
|
||||
|
||||
return (formats[format].write(this));
|
||||
};
|
||||
|
||||
PrivateKey.prototype.hash = function (algo) {
|
||||
return (this.toPublic().hash(algo));
|
||||
};
|
||||
|
||||
PrivateKey.prototype.toPublic = function () {
|
||||
if (this._pubCache)
|
||||
return (this._pubCache);
|
||||
|
||||
var algInfo = algs.info[this.type];
|
||||
var pubParts = [];
|
||||
for (var i = 0; i < algInfo.parts.length; ++i) {
|
||||
var p = algInfo.parts[i];
|
||||
pubParts.push(this.part[p]);
|
||||
}
|
||||
|
||||
this._pubCache = new Key({
|
||||
type: this.type,
|
||||
source: this,
|
||||
parts: pubParts
|
||||
});
|
||||
if (this.comment)
|
||||
this._pubCache.comment = this.comment;
|
||||
return (this._pubCache);
|
||||
};
|
||||
|
||||
PrivateKey.prototype.derive = function (newType, newSize) {
|
||||
assert.string(newType, 'type');
|
||||
assert.optionalNumber(newSize, 'size');
|
||||
var priv, pub;
|
||||
|
||||
if (this.type === 'ed25519' && newType === 'curve25519') {
|
||||
if (ed === undefined)
|
||||
ed = require('jodid25519');
|
||||
|
||||
priv = this.part.r.data;
|
||||
if (priv[0] === 0x00)
|
||||
priv = priv.slice(1);
|
||||
priv = priv.slice(0, 32);
|
||||
|
||||
pub = ed.dh.publicKey(priv);
|
||||
priv = utils.mpNormalize(Buffer.concat([priv, pub]));
|
||||
|
||||
return (new PrivateKey({
|
||||
type: 'curve25519',
|
||||
parts: [
|
||||
{ name: 'R', data: utils.mpNormalize(pub) },
|
||||
{ name: 'r', data: priv }
|
||||
]
|
||||
}));
|
||||
} else if (this.type === 'curve25519' && newType === 'ed25519') {
|
||||
if (ed === undefined)
|
||||
ed = require('jodid25519');
|
||||
|
||||
priv = this.part.r.data;
|
||||
if (priv[0] === 0x00)
|
||||
priv = priv.slice(1);
|
||||
priv = priv.slice(0, 32);
|
||||
|
||||
pub = ed.eddsa.publicKey(priv.toString('binary'));
|
||||
pub = new Buffer(pub, 'binary');
|
||||
|
||||
priv = utils.mpNormalize(Buffer.concat([priv, pub]));
|
||||
|
||||
return (new PrivateKey({
|
||||
type: 'ed25519',
|
||||
parts: [
|
||||
{ name: 'R', data: utils.mpNormalize(pub) },
|
||||
{ name: 'r', data: priv }
|
||||
]
|
||||
}));
|
||||
}
|
||||
throw (new Error('Key derivation not supported from ' + this.type +
|
||||
' to ' + newType));
|
||||
};
|
||||
|
||||
PrivateKey.prototype.createVerify = function (hashAlgo) {
|
||||
return (this.toPublic().createVerify(hashAlgo));
|
||||
};
|
||||
|
||||
PrivateKey.prototype.createSign = function (hashAlgo) {
|
||||
if (hashAlgo === undefined)
|
||||
hashAlgo = this.defaultHashAlgorithm();
|
||||
assert.string(hashAlgo, 'hash algorithm');
|
||||
|
||||
/* ED25519 is not supported by OpenSSL, use a javascript impl. */
|
||||
if (this.type === 'ed25519' && edCompat !== undefined)
|
||||
return (new edCompat.Signer(this, hashAlgo));
|
||||
if (this.type === 'curve25519')
|
||||
throw (new Error('Curve25519 keys are not suitable for ' +
|
||||
'signing or verification'));
|
||||
|
||||
var v, nm, err;
|
||||
try {
|
||||
nm = this.type.toUpperCase() + '-';
|
||||
if (this.type === 'ecdsa')
|
||||
nm = 'ecdsa-with-';
|
||||
nm += hashAlgo.toUpperCase();
|
||||
v = crypto.createSign(nm);
|
||||
} catch (e) {
|
||||
err = e;
|
||||
}
|
||||
if (v === undefined || (err instanceof Error &&
|
||||
err.message.match(/Unknown message digest/))) {
|
||||
nm = 'RSA-';
|
||||
nm += hashAlgo.toUpperCase();
|
||||
v = crypto.createSign(nm);
|
||||
}
|
||||
assert.ok(v, 'failed to create verifier');
|
||||
var oldSign = v.sign.bind(v);
|
||||
var key = this.toBuffer('pkcs1');
|
||||
var type = this.type;
|
||||
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;
|
||||
return (sig);
|
||||
};
|
||||
return (v);
|
||||
};
|
||||
|
||||
PrivateKey.parse = function (data, format, name) {
|
||||
if (typeof (data) !== 'string')
|
||||
assert.buffer(data, 'data');
|
||||
if (format === undefined)
|
||||
format = 'auto';
|
||||
assert.string(format, 'format');
|
||||
if (name === undefined)
|
||||
name = '(unnamed)';
|
||||
|
||||
assert.object(formats[format], 'formats[format]');
|
||||
|
||||
try {
|
||||
var k = formats[format].read(data);
|
||||
assert.ok(k instanceof PrivateKey, 'key is not a private key');
|
||||
if (!k.comment)
|
||||
k.comment = name;
|
||||
return (k);
|
||||
} catch (e) {
|
||||
throw (new KeyParseError(name, format, e));
|
||||
}
|
||||
};
|
||||
|
||||
PrivateKey.isPrivateKey = function (obj, ver) {
|
||||
return (utils.isCompatible(obj, PrivateKey, ver));
|
||||
};
|
||||
|
||||
/*
|
||||
* API versions for PrivateKey:
|
||||
* [1,0] -- initial ver
|
||||
* [1,1] -- added auto, pkcs[18], openssh/ssh-private formats
|
||||
* [1,2] -- added defaultHashAlgorithm
|
||||
* [1,3] -- added derive, ed, createDH
|
||||
* [1,4] -- first tagged version
|
||||
*/
|
||||
PrivateKey.prototype._sshpkApiVersion = [1, 4];
|
||||
|
||||
PrivateKey._oldVersionDetect = function (obj) {
|
||||
assert.func(obj.toPublic);
|
||||
assert.func(obj.createSign);
|
||||
if (obj.derive)
|
||||
return ([1, 3]);
|
||||
if (obj.defaultHashAlgorithm)
|
||||
return ([1, 2]);
|
||||
if (obj.formats['auto'])
|
||||
return ([1, 1]);
|
||||
return ([1, 0]);
|
||||
};
|
||||
237
node_modules/sshpk/lib/signature.js
generated
vendored
Normal file
237
node_modules/sshpk/lib/signature.js
generated
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
// Copyright 2015 Joyent, Inc.
|
||||
|
||||
module.exports = Signature;
|
||||
|
||||
var assert = require('assert-plus');
|
||||
var algs = require('./algs');
|
||||
var crypto = require('crypto');
|
||||
var errs = require('./errors');
|
||||
var utils = require('./utils');
|
||||
var asn1 = require('asn1');
|
||||
var SSHBuffer = require('./ssh-buffer');
|
||||
|
||||
var InvalidAlgorithmError = errs.InvalidAlgorithmError;
|
||||
var SignatureParseError = errs.SignatureParseError;
|
||||
|
||||
function Signature(opts) {
|
||||
assert.object(opts, 'options');
|
||||
assert.arrayOfObject(opts.parts, 'options.parts');
|
||||
assert.string(opts.type, 'options.type');
|
||||
|
||||
var partLookup = {};
|
||||
for (var i = 0; i < opts.parts.length; ++i) {
|
||||
var part = opts.parts[i];
|
||||
partLookup[part.name] = part;
|
||||
}
|
||||
|
||||
this.type = opts.type;
|
||||
this.hashAlgorithm = opts.hashAlgo;
|
||||
this.parts = opts.parts;
|
||||
this.part = partLookup;
|
||||
}
|
||||
|
||||
Signature.prototype.toBuffer = function (format) {
|
||||
if (format === undefined)
|
||||
format = 'asn1';
|
||||
assert.string(format, 'format');
|
||||
|
||||
var buf;
|
||||
|
||||
switch (this.type) {
|
||||
case 'rsa':
|
||||
case 'ed25519':
|
||||
if (format === 'ssh') {
|
||||
buf = new SSHBuffer({});
|
||||
buf.writeString('ssh-' + this.type);
|
||||
buf.writePart(this.part.sig);
|
||||
return (buf.toBuffer());
|
||||
} else {
|
||||
return (this.part.sig.data);
|
||||
}
|
||||
|
||||
case 'dsa':
|
||||
case 'ecdsa':
|
||||
var r, s;
|
||||
if (format === 'asn1') {
|
||||
var der = new asn1.BerWriter();
|
||||
der.startSequence();
|
||||
r = utils.mpNormalize(this.part.r.data);
|
||||
s = utils.mpNormalize(this.part.s.data);
|
||||
der.writeBuffer(r, asn1.Ber.Integer);
|
||||
der.writeBuffer(s, asn1.Ber.Integer);
|
||||
der.endSequence();
|
||||
return (der.buffer);
|
||||
} else if (format === 'ssh' && this.type === 'dsa') {
|
||||
buf = new SSHBuffer({});
|
||||
buf.writeString('ssh-dss');
|
||||
r = this.part.r.data;
|
||||
if (r[0] === 0x00)
|
||||
r = r.slice(1);
|
||||
s = this.part.s.data;
|
||||
buf.writeBuffer(Buffer.concat([r, s]));
|
||||
return (buf.toBuffer());
|
||||
} else if (format === 'ssh' && this.type === 'ecdsa') {
|
||||
var inner = new SSHBuffer({});
|
||||
r = this.part.r;
|
||||
if (r[0] === 0x00)
|
||||
r = r.slice(1);
|
||||
inner.writePart(r);
|
||||
inner.writePart(this.part.s);
|
||||
|
||||
buf = new SSHBuffer({});
|
||||
/* XXX: find a more proper way to do this? */
|
||||
var curve;
|
||||
var sz = this.part.r.data.length * 8;
|
||||
if (sz === 256)
|
||||
curve = 'nistp256';
|
||||
else if (sz === 384)
|
||||
curve = 'nistp384';
|
||||
else if (sz === 528)
|
||||
curve = 'nistp521';
|
||||
buf.writeString('ecdsa-sha2-' + curve);
|
||||
buf.writeBuffer(inner.toBuffer());
|
||||
return (buf.toBuffer());
|
||||
}
|
||||
throw (new Error('Invalid signature format'));
|
||||
default:
|
||||
throw (new Error('Invalid signature data'));
|
||||
}
|
||||
};
|
||||
|
||||
Signature.prototype.toString = function (format) {
|
||||
assert.optionalString(format, 'format');
|
||||
return (this.toBuffer(format).toString('base64'));
|
||||
};
|
||||
|
||||
Signature.parse = function (data, type, format) {
|
||||
if (typeof (data) === 'string')
|
||||
data = new Buffer(data, 'base64');
|
||||
assert.buffer(data, 'data');
|
||||
assert.string(format, 'format');
|
||||
assert.string(type, 'type');
|
||||
|
||||
var opts = {};
|
||||
opts.type = type.toLowerCase();
|
||||
opts.parts = [];
|
||||
|
||||
try {
|
||||
assert.ok(data.length > 0, 'signature must not be empty');
|
||||
switch (opts.type) {
|
||||
case 'rsa':
|
||||
return (parseOneNum(data, type, format, opts,
|
||||
'ssh-rsa'));
|
||||
case 'ed25519':
|
||||
return (parseOneNum(data, type, format, opts,
|
||||
'ssh-ed25519'));
|
||||
|
||||
case 'dsa':
|
||||
case 'ecdsa':
|
||||
if (format === 'asn1')
|
||||
return (parseDSAasn1(data, type, format, opts));
|
||||
else if (opts.type === 'dsa')
|
||||
return (parseDSA(data, type, format, opts));
|
||||
else
|
||||
return (parseECDSA(data, type, format, opts));
|
||||
|
||||
default:
|
||||
throw (new InvalidAlgorithmError(type));
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
if (e instanceof InvalidAlgorithmError)
|
||||
throw (e);
|
||||
throw (new SignatureParseError(type, format, e));
|
||||
}
|
||||
};
|
||||
|
||||
function parseOneNum(data, type, format, opts, headType) {
|
||||
if (format === 'ssh') {
|
||||
try {
|
||||
var buf = new SSHBuffer({buffer: data});
|
||||
var head = buf.readString();
|
||||
} catch (e) {
|
||||
/* fall through */
|
||||
}
|
||||
if (head === headType) {
|
||||
var sig = buf.readPart();
|
||||
assert.ok(buf.atEnd(), 'extra trailing bytes');
|
||||
sig.name = 'sig';
|
||||
opts.parts.push(sig);
|
||||
return (new Signature(opts));
|
||||
}
|
||||
}
|
||||
opts.parts.push({name: 'sig', data: data});
|
||||
return (new Signature(opts));
|
||||
}
|
||||
|
||||
function parseDSAasn1(data, type, format, opts) {
|
||||
var der = new asn1.BerReader(data);
|
||||
der.readSequence();
|
||||
var r = der.readString(asn1.Ber.Integer, true);
|
||||
var s = der.readString(asn1.Ber.Integer, true);
|
||||
|
||||
opts.parts.push({name: 'r', data: utils.mpNormalize(r)});
|
||||
opts.parts.push({name: 's', data: utils.mpNormalize(s)});
|
||||
|
||||
return (new Signature(opts));
|
||||
}
|
||||
|
||||
function parseDSA(data, type, format, opts) {
|
||||
if (data.length != 40) {
|
||||
var buf = new SSHBuffer({buffer: data});
|
||||
var d = buf.readBuffer();
|
||||
if (d.toString('ascii') === 'ssh-dss')
|
||||
d = buf.readBuffer();
|
||||
assert.ok(buf.atEnd(), 'extra trailing bytes');
|
||||
assert.strictEqual(d.length, 40, 'invalid inner length');
|
||||
data = d;
|
||||
}
|
||||
opts.parts.push({name: 'r', data: data.slice(0, 20)});
|
||||
opts.parts.push({name: 's', data: data.slice(20, 40)});
|
||||
return (new Signature(opts));
|
||||
}
|
||||
|
||||
function parseECDSA(data, type, format, opts) {
|
||||
var buf = new SSHBuffer({buffer: data});
|
||||
|
||||
var r, s;
|
||||
var inner = buf.readBuffer();
|
||||
if (inner.toString('ascii').match(/^ecdsa-/)) {
|
||||
inner = buf.readBuffer();
|
||||
assert.ok(buf.atEnd(), 'extra trailing bytes on outer');
|
||||
buf = new SSHBuffer({buffer: inner});
|
||||
r = buf.readPart();
|
||||
} else {
|
||||
r = {data: inner};
|
||||
}
|
||||
|
||||
s = buf.readPart();
|
||||
assert.ok(buf.atEnd(), 'extra trailing bytes');
|
||||
|
||||
r.name = 'r';
|
||||
s.name = 's';
|
||||
|
||||
opts.parts.push(r);
|
||||
opts.parts.push(s);
|
||||
return (new Signature(opts));
|
||||
}
|
||||
|
||||
Signature.isSignature = function (obj, ver) {
|
||||
return (utils.isCompatible(obj, Signature, ver));
|
||||
};
|
||||
|
||||
/*
|
||||
* API versions for Signature:
|
||||
* [1,0] -- initial ver
|
||||
* [2,0] -- support for rsa in full ssh format, compat with sshpk-agent
|
||||
* hashAlgorithm property
|
||||
* [2,1] -- first tagged version
|
||||
*/
|
||||
Signature.prototype._sshpkApiVersion = [2, 1];
|
||||
|
||||
Signature._oldVersionDetect = function (obj) {
|
||||
assert.func(obj.toBuffer);
|
||||
if (obj.hasOwnProperty('hashAlgorithm'))
|
||||
return ([2, 0]);
|
||||
return ([1, 0]);
|
||||
};
|
||||
123
node_modules/sshpk/lib/ssh-buffer.js
generated
vendored
Normal file
123
node_modules/sshpk/lib/ssh-buffer.js
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
// Copyright 2015 Joyent, Inc.
|
||||
|
||||
module.exports = SSHBuffer;
|
||||
|
||||
var assert = require('assert-plus');
|
||||
|
||||
function SSHBuffer(opts) {
|
||||
assert.object(opts, 'options');
|
||||
if (opts.buffer !== undefined)
|
||||
assert.buffer(opts.buffer, 'options.buffer');
|
||||
|
||||
this._size = opts.buffer ? opts.buffer.length : 1024;
|
||||
this._buffer = opts.buffer || (new Buffer(this._size));
|
||||
this._offset = 0;
|
||||
}
|
||||
|
||||
SSHBuffer.prototype.toBuffer = function () {
|
||||
return (this._buffer.slice(0, this._offset));
|
||||
};
|
||||
|
||||
SSHBuffer.prototype.atEnd = function () {
|
||||
return (this._offset >= this._buffer.length);
|
||||
};
|
||||
|
||||
SSHBuffer.prototype.remainder = function () {
|
||||
return (this._buffer.slice(this._offset));
|
||||
};
|
||||
|
||||
SSHBuffer.prototype.skip = function (n) {
|
||||
this._offset += n;
|
||||
};
|
||||
|
||||
SSHBuffer.prototype.expand = function () {
|
||||
this._size *= 2;
|
||||
var buf = new Buffer(this._size);
|
||||
this._buffer.copy(buf, 0);
|
||||
this._buffer = buf;
|
||||
};
|
||||
|
||||
SSHBuffer.prototype.readPart = function () {
|
||||
return ({data: this.readBuffer()});
|
||||
};
|
||||
|
||||
SSHBuffer.prototype.readBuffer = function () {
|
||||
var len = this._buffer.readUInt32BE(this._offset);
|
||||
this._offset += 4;
|
||||
assert.ok(this._offset + len <= this._buffer.length,
|
||||
'length out of bounds at +0x' + this._offset.toString(16));
|
||||
var buf = this._buffer.slice(this._offset, this._offset + len);
|
||||
this._offset += len;
|
||||
return (buf);
|
||||
};
|
||||
|
||||
SSHBuffer.prototype.readString = function () {
|
||||
return (this.readBuffer().toString());
|
||||
};
|
||||
|
||||
SSHBuffer.prototype.readCString = function () {
|
||||
var offset = this._offset;
|
||||
while (offset < this._buffer.length &&
|
||||
this._buffer[offset] !== 0x00)
|
||||
offset++;
|
||||
assert.ok(offset < this._buffer.length, 'c string does not terminate');
|
||||
var str = this._buffer.slice(this._offset, offset).toString();
|
||||
this._offset = offset + 1;
|
||||
return (str);
|
||||
};
|
||||
|
||||
SSHBuffer.prototype.readInt = function () {
|
||||
var v = this._buffer.readUInt32BE(this._offset);
|
||||
this._offset += 4;
|
||||
return (v);
|
||||
};
|
||||
|
||||
SSHBuffer.prototype.readChar = function () {
|
||||
var v = this._buffer[this._offset++];
|
||||
return (v);
|
||||
};
|
||||
|
||||
SSHBuffer.prototype.writeBuffer = function (buf) {
|
||||
while (this._offset + 4 + buf.length > this._size)
|
||||
this.expand();
|
||||
this._buffer.writeUInt32BE(buf.length, this._offset);
|
||||
this._offset += 4;
|
||||
buf.copy(this._buffer, this._offset);
|
||||
this._offset += buf.length;
|
||||
};
|
||||
|
||||
SSHBuffer.prototype.writeString = function (str) {
|
||||
this.writeBuffer(new Buffer(str, 'utf8'));
|
||||
};
|
||||
|
||||
SSHBuffer.prototype.writeCString = function (str) {
|
||||
while (this._offset + 1 + str.length > this._size)
|
||||
this.expand();
|
||||
this._buffer.write(str, this._offset);
|
||||
this._offset += str.length;
|
||||
this._buffer[this._offset++] = 0;
|
||||
};
|
||||
|
||||
SSHBuffer.prototype.writeInt = function (v) {
|
||||
while (this._offset + 4 > this._size)
|
||||
this.expand();
|
||||
this._buffer.writeUInt32BE(v, this._offset);
|
||||
this._offset += 4;
|
||||
};
|
||||
|
||||
SSHBuffer.prototype.writeChar = function (v) {
|
||||
while (this._offset + 1 > this._size)
|
||||
this.expand();
|
||||
this._buffer[this._offset++] = v;
|
||||
};
|
||||
|
||||
SSHBuffer.prototype.writePart = function (p) {
|
||||
this.writeBuffer(p.data);
|
||||
};
|
||||
|
||||
SSHBuffer.prototype.write = function (buf) {
|
||||
while (this._offset + buf.length > this._size)
|
||||
this.expand();
|
||||
buf.copy(this._buffer, this._offset);
|
||||
this._offset += buf.length;
|
||||
};
|
||||
207
node_modules/sshpk/lib/utils.js
generated
vendored
Normal file
207
node_modules/sshpk/lib/utils.js
generated
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
// Copyright 2015 Joyent, Inc.
|
||||
|
||||
module.exports = {
|
||||
bufferSplit: bufferSplit,
|
||||
addRSAMissing: addRSAMissing,
|
||||
calculateDSAPublic: calculateDSAPublic,
|
||||
mpNormalize: mpNormalize,
|
||||
ecNormalize: ecNormalize,
|
||||
countZeros: countZeros,
|
||||
assertCompatible: assertCompatible,
|
||||
isCompatible: isCompatible
|
||||
};
|
||||
|
||||
var assert = require('assert-plus');
|
||||
var PrivateKey = require('./private-key');
|
||||
|
||||
var MAX_CLASS_DEPTH = 3;
|
||||
|
||||
function isCompatible(obj, klass, needVer) {
|
||||
if (obj === null || typeof (obj) !== 'object')
|
||||
return (false);
|
||||
if (needVer === undefined)
|
||||
needVer = klass.prototype._sshpkApiVersion;
|
||||
if (obj instanceof klass &&
|
||||
klass.prototype._sshpkApiVersion[0] == needVer[0])
|
||||
return (true);
|
||||
var proto = Object.getPrototypeOf(obj);
|
||||
var depth = 0;
|
||||
while (proto.constructor.name !== klass.name) {
|
||||
proto = Object.getPrototypeOf(proto);
|
||||
if (!proto || ++depth > MAX_CLASS_DEPTH)
|
||||
return (false);
|
||||
}
|
||||
if (proto.constructor.name !== klass.name)
|
||||
return (false);
|
||||
var ver = proto._sshpkApiVersion;
|
||||
if (ver === undefined)
|
||||
ver = klass._oldVersionDetect(obj);
|
||||
if (ver[0] != needVer[0] || ver[1] < needVer[1])
|
||||
return (false);
|
||||
return (true);
|
||||
}
|
||||
|
||||
function assertCompatible(obj, klass, needVer, name) {
|
||||
if (name === undefined)
|
||||
name = 'object';
|
||||
assert.ok(obj, name + ' must not be null');
|
||||
assert.object(obj, name + ' must be an object');
|
||||
if (needVer === undefined)
|
||||
needVer = klass.prototype._sshpkApiVersion;
|
||||
if (obj instanceof klass &&
|
||||
klass.prototype._sshpkApiVersion[0] == needVer[0])
|
||||
return;
|
||||
var proto = Object.getPrototypeOf(obj);
|
||||
var depth = 0;
|
||||
while (proto.constructor.name !== klass.name) {
|
||||
proto = Object.getPrototypeOf(proto);
|
||||
assert.ok(proto && ++depth <= MAX_CLASS_DEPTH,
|
||||
name + ' must be a ' + klass.name + ' instance');
|
||||
}
|
||||
assert.strictEqual(proto.constructor.name, klass.name,
|
||||
name + ' must be a ' + klass.name + ' instance');
|
||||
var ver = proto._sshpkApiVersion;
|
||||
if (ver === undefined)
|
||||
ver = klass._oldVersionDetect(obj);
|
||||
assert.ok(ver[0] == needVer[0] && ver[1] >= needVer[1],
|
||||
name + ' must be compatible with ' + klass.name + ' klass ' +
|
||||
'version ' + needVer[0] + '.' + needVer[1]);
|
||||
}
|
||||
|
||||
/* Count leading zero bits on a buffer */
|
||||
function countZeros(buf) {
|
||||
var o = 0, obit = 8;
|
||||
while (o < buf.length) {
|
||||
var mask = (1 << obit);
|
||||
if ((buf[o] & mask) === mask)
|
||||
break;
|
||||
obit--;
|
||||
if (obit < 0) {
|
||||
o++;
|
||||
obit = 8;
|
||||
}
|
||||
}
|
||||
return (o*8 + (8 - obit) - 1);
|
||||
}
|
||||
|
||||
function bufferSplit(buf, chr) {
|
||||
assert.buffer(buf);
|
||||
assert.string(chr);
|
||||
|
||||
var parts = [];
|
||||
var lastPart = 0;
|
||||
var matches = 0;
|
||||
for (var i = 0; i < buf.length; ++i) {
|
||||
if (buf[i] === chr.charCodeAt(matches))
|
||||
++matches;
|
||||
else if (buf[i] === chr.charCodeAt(0))
|
||||
matches = 1;
|
||||
else
|
||||
matches = 0;
|
||||
|
||||
if (matches >= chr.length) {
|
||||
var newPart = i + 1;
|
||||
parts.push(buf.slice(lastPart, newPart - matches));
|
||||
lastPart = newPart;
|
||||
matches = 0;
|
||||
}
|
||||
}
|
||||
if (lastPart <= buf.length)
|
||||
parts.push(buf.slice(lastPart, buf.length));
|
||||
|
||||
return (parts);
|
||||
}
|
||||
|
||||
function ecNormalize(buf, addZero) {
|
||||
assert.buffer(buf);
|
||||
if (buf[0] === 0x00 && buf[1] === 0x04) {
|
||||
if (addZero)
|
||||
return (buf);
|
||||
return (buf.slice(1));
|
||||
} else if (buf[0] === 0x04) {
|
||||
if (!addZero)
|
||||
return (buf);
|
||||
} else {
|
||||
while (buf[0] === 0x00)
|
||||
buf = buf.slice(1);
|
||||
if (buf[0] === 0x02 || buf[0] === 0x03)
|
||||
throw (new Error('Compressed elliptic curve points ' +
|
||||
'are not supported'));
|
||||
if (buf[0] !== 0x04)
|
||||
throw (new Error('Not a valid elliptic curve point'));
|
||||
if (!addZero)
|
||||
return (buf);
|
||||
}
|
||||
var b = new Buffer(buf.length + 1);
|
||||
b[0] = 0x0;
|
||||
buf.copy(b, 1);
|
||||
return (b);
|
||||
}
|
||||
|
||||
function mpNormalize(buf) {
|
||||
assert.buffer(buf);
|
||||
while (buf.length > 1 && buf[0] === 0x00 && (buf[1] & 0x80) === 0x00)
|
||||
buf = buf.slice(1);
|
||||
if ((buf[0] & 0x80) === 0x80) {
|
||||
var b = new Buffer(buf.length + 1);
|
||||
b[0] = 0x00;
|
||||
buf.copy(b, 1);
|
||||
buf = b;
|
||||
}
|
||||
return (buf);
|
||||
}
|
||||
|
||||
function bigintToMpBuf(bigint) {
|
||||
var buf = new Buffer(bigint.toByteArray());
|
||||
buf = mpNormalize(buf);
|
||||
return (buf);
|
||||
}
|
||||
|
||||
function calculateDSAPublic(g, p, x) {
|
||||
assert.buffer(g);
|
||||
assert.buffer(p);
|
||||
assert.buffer(x);
|
||||
try {
|
||||
var bigInt = require('jsbn').BigInteger;
|
||||
} catch (e) {
|
||||
throw (new Error('To load a PKCS#8 format DSA private key, ' +
|
||||
'the node jsbn library is required.'));
|
||||
}
|
||||
g = new bigInt(g);
|
||||
p = new bigInt(p);
|
||||
x = new bigInt(x);
|
||||
var y = g.modPow(x, p);
|
||||
var ybuf = bigintToMpBuf(y);
|
||||
return (ybuf);
|
||||
}
|
||||
|
||||
function addRSAMissing(key) {
|
||||
assert.object(key);
|
||||
assertCompatible(key, PrivateKey, [1, 1]);
|
||||
try {
|
||||
var bigInt = require('jsbn').BigInteger;
|
||||
} catch (e) {
|
||||
throw (new Error('To write a PEM private key from ' +
|
||||
'this source, the node jsbn lib is required.'));
|
||||
}
|
||||
|
||||
var d = new bigInt(key.part.d.data);
|
||||
var buf;
|
||||
|
||||
if (!key.part.dmodp) {
|
||||
var p = new bigInt(key.part.p.data);
|
||||
var dmodp = d.mod(p.subtract(1));
|
||||
|
||||
buf = bigintToMpBuf(dmodp);
|
||||
key.part.dmodp = {name: 'dmodp', data: buf};
|
||||
key.parts.push(key.part.dmodp);
|
||||
}
|
||||
if (!key.part.dmodq) {
|
||||
var q = new bigInt(key.part.q.data);
|
||||
var dmodq = d.mod(q.subtract(1));
|
||||
|
||||
buf = bigintToMpBuf(dmodq);
|
||||
key.part.dmodq = {name: 'dmodq', data: buf};
|
||||
key.parts.push(key.part.dmodq);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user