first commit

This commit is contained in:
s.golasch
2023-08-01 13:49:46 +02:00
commit 1fc239fd54
20238 changed files with 3112246 additions and 0 deletions

386
build/node_modules/ssh2-streams/lib/constants.js generated vendored Normal file
View File

@@ -0,0 +1,386 @@
var semver = require('semver');
var i;
var keys;
var len;
var MESSAGE = exports.MESSAGE = {
// Transport layer protocol -- generic (1-19)
DISCONNECT: 1,
IGNORE: 2,
UNIMPLEMENTED: 3,
DEBUG: 4,
SERVICE_REQUEST: 5,
SERVICE_ACCEPT: 6,
// Transport layer protocol -- algorithm negotiation (20-29)
KEXINIT: 20,
NEWKEYS: 21,
// Transport layer protocol -- key exchange method-specific (30-49)
// User auth protocol -- generic (50-59)
USERAUTH_REQUEST: 50,
USERAUTH_FAILURE: 51,
USERAUTH_SUCCESS: 52,
USERAUTH_BANNER: 53,
// User auth protocol -- user auth method-specific (60-79)
// Connection protocol -- generic (80-89)
GLOBAL_REQUEST: 80,
REQUEST_SUCCESS: 81,
REQUEST_FAILURE: 82,
// Connection protocol -- channel-related (90-127)
CHANNEL_OPEN: 90,
CHANNEL_OPEN_CONFIRMATION: 91,
CHANNEL_OPEN_FAILURE: 92,
CHANNEL_WINDOW_ADJUST: 93,
CHANNEL_DATA: 94,
CHANNEL_EXTENDED_DATA: 95,
CHANNEL_EOF: 96,
CHANNEL_CLOSE: 97,
CHANNEL_REQUEST: 98,
CHANNEL_SUCCESS: 99,
CHANNEL_FAILURE: 100
// Reserved for client protocols (128-191)
// Local extensions (192-155)
};
for (i = 0, keys = Object.keys(MESSAGE), len = keys.length; i < len; ++i)
MESSAGE[MESSAGE[keys[i]]] = keys[i];
// context-specific message codes:
MESSAGE.KEXDH_INIT = 30;
MESSAGE.KEXDH_REPLY = 31;
MESSAGE.KEXDH_GEX_REQUEST = 34;
MESSAGE.KEXDH_GEX_GROUP = 31;
MESSAGE.KEXDH_GEX_INIT = 32;
MESSAGE.KEXDH_GEX_REPLY = 33;
MESSAGE.KEXECDH_INIT = 30; // included here for completeness
MESSAGE.KEXECDH_REPLY = 31; // included here for completeness
MESSAGE.USERAUTH_PASSWD_CHANGEREQ = 60;
MESSAGE.USERAUTH_PK_OK = 60;
MESSAGE.USERAUTH_INFO_REQUEST = 60;
MESSAGE.USERAUTH_INFO_RESPONSE = 61;
var DYNAMIC_KEXDH_MESSAGE = exports.DYNAMIC_KEXDH_MESSAGE = {};
DYNAMIC_KEXDH_MESSAGE[MESSAGE.KEXDH_GEX_GROUP] = 'KEXDH_GEX_GROUP';
DYNAMIC_KEXDH_MESSAGE[MESSAGE.KEXDH_GEX_REPLY] = 'KEXDH_GEX_REPLY';
var KEXDH_MESSAGE = exports.KEXDH_MESSAGE = {};
KEXDH_MESSAGE[MESSAGE.KEXDH_INIT] = 'KEXDH_INIT';
KEXDH_MESSAGE[MESSAGE.KEXDH_REPLY] = 'KEXDH_REPLY';
var DISCONNECT_REASON = exports.DISCONNECT_REASON = {
HOST_NOT_ALLOWED_TO_CONNECT: 1,
PROTOCOL_ERROR: 2,
KEY_EXCHANGE_FAILED: 3,
RESERVED: 4,
MAC_ERROR: 5,
COMPRESSION_ERROR: 6,
SERVICE_NOT_AVAILABLE: 7,
PROTOCOL_VERSION_NOT_SUPPORTED: 8,
HOST_KEY_NOT_VERIFIABLE: 9,
CONNECTION_LOST: 10,
BY_APPLICATION: 11,
TOO_MANY_CONNECTIONS: 12,
AUTH_CANCELED_BY_USER: 13,
NO_MORE_AUTH_METHODS_AVAILABLE: 14,
ILLEGAL_USER_NAME: 15
};
for (i = 0, keys = Object.keys(DISCONNECT_REASON), len = keys.length;
i < len;
++i) {
DISCONNECT_REASON[DISCONNECT_REASON[keys[i]]] = keys[i];
}
var CHANNEL_OPEN_FAILURE = exports.CHANNEL_OPEN_FAILURE = {
ADMINISTRATIVELY_PROHIBITED: 1,
CONNECT_FAILED: 2,
UNKNOWN_CHANNEL_TYPE: 3,
RESOURCE_SHORTAGE: 4
};
for (i = 0, keys = Object.keys(CHANNEL_OPEN_FAILURE), len = keys.length;
i < len;
++i) {
CHANNEL_OPEN_FAILURE[CHANNEL_OPEN_FAILURE[keys[i]]] = keys[i];
}
var TERMINAL_MODE = exports.TERMINAL_MODE = {
TTY_OP_END: 0, // Indicates end of options.
VINTR: 1, // Interrupt character; 255 if none. Similarly for the
// other characters. Not all of these characters are
// supported on all systems.
VQUIT: 2, // The quit character (sends SIGQUIT signal on POSIX
// systems).
VERASE: 3, // Erase the character to left of the cursor.
VKILL: 4, // Kill the current input line.
VEOF: 5, // End-of-file character (sends EOF from the terminal).
VEOL: 6, // End-of-line character in addition to carriage return
// and/or linefeed.
VEOL2: 7, // Additional end-of-line character.
VSTART: 8, // Continues paused output (normally control-Q).
VSTOP: 9, // Pauses output (normally control-S).
VSUSP: 10, // Suspends the current program.
VDSUSP: 11, // Another suspend character.
VREPRINT: 12, // Reprints the current input line.
VWERASE: 13, // Erases a word left of cursor.
VLNEXT: 14, // Enter the next character typed literally, even if it
// is a special character
VFLUSH: 15, // Character to flush output.
VSWTCH: 16, // Switch to a different shell layer.
VSTATUS: 17, // Prints system status line (load, command, pid, etc).
VDISCARD: 18, // Toggles the flushing of terminal output.
IGNPAR: 30, // The ignore parity flag. The parameter SHOULD be 0
// if this flag is FALSE, and 1 if it is TRUE.
PARMRK: 31, // Mark parity and framing errors.
INPCK: 32, // Enable checking of parity errors.
ISTRIP: 33, // Strip 8th bit off characters.
INLCR: 34, // Map NL into CR on input.
IGNCR: 35, // Ignore CR on input.
ICRNL: 36, // Map CR to NL on input.
IUCLC: 37, // Translate uppercase characters to lowercase.
IXON: 38, // Enable output flow control.
IXANY: 39, // Any char will restart after stop.
IXOFF: 40, // Enable input flow control.
IMAXBEL: 41, // Ring bell on input queue full.
ISIG: 50, // Enable signals INTR, QUIT, [D]SUSP.
ICANON: 51, // Canonicalize input lines.
XCASE: 52, // Enable input and output of uppercase characters by
// preceding their lowercase equivalents with "\".
ECHO: 53, // Enable echoing.
ECHOE: 54, // Visually erase chars.
ECHOK: 55, // Kill character discards current line.
ECHONL: 56, // Echo NL even if ECHO is off.
NOFLSH: 57, // Don't flush after interrupt.
TOSTOP: 58, // Stop background jobs from output.
IEXTEN: 59, // Enable extensions.
ECHOCTL: 60, // Echo control characters as ^(Char).
ECHOKE: 61, // Visual erase for line kill.
PENDIN: 62, // Retype pending input.
OPOST: 70, // Enable output processing.
OLCUC: 71, // Convert lowercase to uppercase.
ONLCR: 72, // Map NL to CR-NL.
OCRNL: 73, // Translate carriage return to newline (output).
ONOCR: 74, // Translate newline to carriage return-newline
// (output).
ONLRET: 75, // Newline performs a carriage return (output).
CS7: 90, // 7 bit mode.
CS8: 91, // 8 bit mode.
PARENB: 92, // Parity enable.
PARODD: 93, // Odd parity, else even.
TTY_OP_ISPEED: 128, // Specifies the input baud rate in bits per second.
TTY_OP_OSPEED: 129 // Specifies the output baud rate in bits per second.
};
for (i = 0, keys = Object.keys(TERMINAL_MODE), len = keys.length; i < len; ++i)
TERMINAL_MODE[TERMINAL_MODE[keys[i]]] = keys[i];
var CHANNEL_EXTENDED_DATATYPE = exports.CHANNEL_EXTENDED_DATATYPE = {
STDERR: 1
};
for (i = 0, keys = Object.keys(CHANNEL_EXTENDED_DATATYPE), len = keys.length;
i < len;
++i) {
CHANNEL_EXTENDED_DATATYPE[CHANNEL_EXTENDED_DATATYPE[keys[i]]] = keys[i];
}
exports.SIGNALS = ['ABRT', 'ALRM', 'FPE', 'HUP', 'ILL', 'INT',
'QUIT', 'SEGV', 'TERM', 'USR1', 'USR2', 'KILL',
'PIPE'];
var DEFAULT_KEX = [
'diffie-hellman-group14-sha1' // REQUIRED
];
var SUPPORTED_KEX = [
'diffie-hellman-group1-sha1' // REQUIRED
];
if (semver.gte(process.version, '0.11.12')) {
// https://tools.ietf.org/html/rfc4419#section-4
DEFAULT_KEX = [
'diffie-hellman-group-exchange-sha256'
].concat(DEFAULT_KEX);
SUPPORTED_KEX = [
'diffie-hellman-group-exchange-sha1'
].concat(SUPPORTED_KEX);
}
if (semver.gte(process.version, '0.11.14')) {
// https://tools.ietf.org/html/rfc5656#section-10.1
DEFAULT_KEX = [
'ecdh-sha2-nistp256',
'ecdh-sha2-nistp384',
'ecdh-sha2-nistp521'
].concat(DEFAULT_KEX);
}
var KEX_BUF = new Buffer(DEFAULT_KEX.join(','), 'ascii');
SUPPORTED_KEX = DEFAULT_KEX.concat(SUPPORTED_KEX);
var DEFAULT_SERVER_HOST_KEY = [
'ssh-rsa'
];
var SUPPORTED_SERVER_HOST_KEY = [
'ssh-dss'
];
if (semver.gte(process.version, '5.2.0')) {
// ECDSA keys are only supported in v5.2.0+ because of a crypto change that
// made it possible to (efficiently) generate an ECDSA public key from a
// private key (commit nodejs/node#da5ac55c83eb2c09cfb3baf7875529e8f1113529)
DEFAULT_SERVER_HOST_KEY.push(
'ecdsa-sha2-nistp256',
'ecdsa-sha2-nistp384',
'ecdsa-sha2-nistp521'
);
}
var SERVER_HOST_KEY_BUF = new Buffer(DEFAULT_SERVER_HOST_KEY.join(','),
'ascii');
SUPPORTED_SERVER_HOST_KEY = DEFAULT_SERVER_HOST_KEY.concat(
SUPPORTED_SERVER_HOST_KEY
);
var DEFAULT_CIPHER = [];
var SUPPORTED_CIPHER = [
'aes256-cbc',
'aes192-cbc',
'aes128-cbc',
'blowfish-cbc',
'3des-cbc',
// http://tools.ietf.org/html/rfc4345#section-4:
'arcfour256',
'arcfour128',
'cast128-cbc',
'arcfour'
];
if (semver.gte(process.version, '0.11.12')) {
// node v0.11.12 introduced support for setting AAD, which is needed for
// AES-GCM in SSH2
DEFAULT_CIPHER = [
// http://tools.ietf.org/html/rfc5647
'aes128-gcm',
'aes128-gcm@openssh.com',
'aes256-gcm',
'aes256-gcm@openssh.com'
].concat(DEFAULT_CIPHER);
}
DEFAULT_CIPHER = [
// http://tools.ietf.org/html/rfc4344#section-4
'aes128-ctr',
'aes192-ctr',
'aes256-ctr'
].concat(DEFAULT_CIPHER);
var CIPHER_BUF = new Buffer(DEFAULT_CIPHER.join(','), 'ascii');
SUPPORTED_CIPHER = DEFAULT_CIPHER.concat(SUPPORTED_CIPHER);
var DEFAULT_HMAC = [
'hmac-sha2-256',
'hmac-sha2-512',
'hmac-sha1',
];
var SUPPORTED_HMAC = [
'hmac-md5',
'hmac-sha2-256-96', // first 96 bits of HMAC-SHA256
'hmac-sha2-512-96', // first 96 bits of HMAC-SHA512
'hmac-ripemd160',
'hmac-sha1-96', // first 96 bits of HMAC-SHA1
'hmac-md5-96' // first 96 bits of HMAC-MD5
];
var HMAC_BUF = new Buffer(DEFAULT_HMAC.join(','), 'ascii');
SUPPORTED_HMAC = DEFAULT_HMAC.concat(SUPPORTED_HMAC);
var DEFAULT_COMPRESS = [
'none',
'zlib@openssh.com', // ZLIB (LZ77) compression, except
// compression/decompression does not start until after
// successful user authentication
'zlib' // ZLIB (LZ77) compression
];
var SUPPORTED_COMPRESS = [];
var COMPRESS_BUF = new Buffer(DEFAULT_COMPRESS.join(','), 'ascii');
SUPPORTED_COMPRESS = DEFAULT_COMPRESS.concat(SUPPORTED_COMPRESS);
exports.ALGORITHMS = {
KEX: DEFAULT_KEX,
KEX_BUF: KEX_BUF,
SUPPORTED_KEX: SUPPORTED_KEX,
SERVER_HOST_KEY: DEFAULT_SERVER_HOST_KEY,
SERVER_HOST_KEY_BUF: SERVER_HOST_KEY_BUF,
SUPPORTED_SERVER_HOST_KEY: SUPPORTED_SERVER_HOST_KEY,
CIPHER: DEFAULT_CIPHER,
CIPHER_BUF: CIPHER_BUF,
SUPPORTED_CIPHER: SUPPORTED_CIPHER,
HMAC: DEFAULT_HMAC,
HMAC_BUF: HMAC_BUF,
SUPPORTED_HMAC: SUPPORTED_HMAC,
COMPRESS: DEFAULT_COMPRESS,
COMPRESS_BUF: COMPRESS_BUF,
SUPPORTED_COMPRESS: SUPPORTED_COMPRESS
};
exports.SSH_TO_OPENSSL = {
// ECDH key exchange
'ecdh-sha2-nistp256': 'prime256v1', // OpenSSL's name for 'secp256r1'
'ecdh-sha2-nistp384': 'secp384r1',
'ecdh-sha2-nistp521': 'secp521r1',
// Ciphers
'aes128-gcm': 'aes-128-gcm',
'aes256-gcm': 'aes-256-gcm',
'aes128-gcm@openssh.com': 'aes-128-gcm',
'aes256-gcm@openssh.com': 'aes-256-gcm',
'3des-cbc': 'des-ede3-cbc',
'blowfish-cbc': 'bf-cbc',
'aes256-cbc': 'aes-256-cbc',
'aes192-cbc': 'aes-192-cbc',
'aes128-cbc': 'aes-128-cbc',
'idea-cbc': 'idea-cbc',
'cast128-cbc': 'cast-cbc',
'rijndael-cbc@lysator.liu.se': 'aes-256-cbc',
'arcfour128': 'rc4',
'arcfour256': 'rc4',
'arcfour512': 'rc4',
'arcfour': 'rc4',
'camellia128-cbc': 'camellia-128-cbc',
'camellia192-cbc': 'camellia-192-cbc',
'camellia256-cbc': 'camellia-256-cbc',
'camellia128-cbc@openssh.com': 'camellia-128-cbc',
'camellia192-cbc@openssh.com': 'camellia-192-cbc',
'camellia256-cbc@openssh.com': 'camellia-256-cbc',
'3des-ctr': 'des-ede3',
'blowfish-ctr': 'bf-ecb',
'aes256-ctr': 'aes-256-ctr',
'aes192-ctr': 'aes-192-ctr',
'aes128-ctr': 'aes-128-ctr',
'cast128-ctr': 'cast5-ecb',
'camellia128-ctr': 'camellia-128-ecb',
'camellia192-ctr': 'camellia-192-ecb',
'camellia256-ctr': 'camellia-256-ecb',
'camellia128-ctr@openssh.com': 'camellia-128-ecb',
'camellia192-ctr@openssh.com': 'camellia-192-ecb',
'camellia256-ctr@openssh.com': 'camellia-256-ecb',
// HMAC
'hmac-sha1-96': 'sha1',
'hmac-sha1': 'sha1',
'hmac-sha2-256': 'sha256',
'hmac-sha2-256-96': 'sha256',
'hmac-sha2-512': 'sha512',
'hmac-sha2-512-96': 'sha512',
'hmac-md5-96': 'md5',
'hmac-md5': 'md5',
'hmac-ripemd160': 'ripemd160'
};
var BUGS = exports.BUGS = {
BAD_DHGEX: 1,
OLD_EXIT: 2,
DYN_RPORT_BUG: 4
};
exports.BUGGY_IMPLS = [
[ 'Cisco-1.25', BUGS.BAD_DHGEX ],
[ /^[0-9.]+$/, BUGS.OLD_EXIT ], // old SSH.com implementations
[ /^OpenSSH_5\.\d+/, BUGS.DYN_RPORT_BUG ]
];

1186
build/node_modules/ssh2-streams/lib/jsbn.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

239
build/node_modules/ssh2-streams/lib/keyParser.js generated vendored Normal file
View File

@@ -0,0 +1,239 @@
// TODO:
// * handle multi-line header values (OpenSSH)?
// * more thorough validation?
var utils;
var Ber = require('asn1').Ber;
var semver = require('semver');
var RE_PPK = /^PuTTY-User-Key-File-2: ssh-(rsa|dss)\r?\nEncryption: (aes256-cbc|none)\r?\nComment: ([^\r\n]*)\r?\nPublic-Lines: \d+\r?\n([\s\S]+?)\r?\nPrivate-Lines: \d+\r?\n([\s\S]+?)\r?\nPrivate-MAC: ([^\r\n]+)/;
var RE_HEADER_OPENSSH_PRIV = /^-----BEGIN (RSA|DSA|EC) PRIVATE KEY-----$/i;
var RE_FOOTER_OPENSSH_PRIV = /^-----END (?:RSA|DSA|EC) PRIVATE KEY-----$/i;
var RE_HEADER_OPENSSH_PUB = /^((?:(?:ssh-(rsa|dss))|ecdsa-sha2-nistp(256|384|521))(?:-cert-v0[01]@openssh.com)?) ([A-Z0-9a-z\/+=]+)(?:$|\s+([\S].*)?)$/i;
var RE_HEADER_RFC4716_PUB = /^---- BEGIN SSH2 PUBLIC KEY ----$/i;
var RE_FOOTER_RFC4716_PUB = /^---- END SSH2 PUBLIC KEY ----$/i;
var RE_HEADER_OPENSSH = /^([^:]+):\s*([\S].*)?$/i;
var RE_HEADER_RFC4716 = /^([^:]+): (.*)?$/i;
module.exports = function(data) {
if (Buffer.isBuffer(data))
data = data.toString('utf8');
else if (typeof data !== 'string')
return new Error('Key data must be a Buffer or string');
var ret = {
fulltype: undefined,
type: undefined,
curve: undefined,
extra: undefined,
comment: undefined,
encryption: undefined,
private: undefined,
privateOrig: undefined,
public: undefined,
publicOrig: undefined
};
var m;
var i;
var len;
data = data.trim().split(/\r\n|\n/);
while (!data[0].length)
data.shift();
while (!data.slice(-1)[0].length)
data.pop();
var orig = data.join('\n');
if ((m = RE_HEADER_OPENSSH_PRIV.exec(data[0]))
&& RE_FOOTER_OPENSSH_PRIV.test(data.slice(-1))) {
// OpenSSH private key
var keyType = m[1].toLowerCase();
if (keyType === 'dsa')
keyType = 'dss';
if (keyType === 'ec' && semver.lt(process.version, '5.2.0')) {
return new Error(
'EC private keys are not supported in this version of node'
);
}
if (!RE_HEADER_OPENSSH.test(data[1])) {
// unencrypted, no headers
var privData = new Buffer(data.slice(1, -1).join(''), 'base64');
if (keyType !== 'ec') {
ret.fulltype = 'ssh-' + keyType;
} else {
// ECDSA
var asnReader = new Ber.Reader(privData);
asnReader.readSequence();
asnReader.readInt();
asnReader.readString(Ber.OctetString, true);
asnReader.readByte(); // Skip "complex" context type byte
var offset = asnReader.readLength(); // Skip context length
if (offset !== null) {
asnReader._offset = offset;
switch (asnReader.readOID()) {
case '1.2.840.10045.3.1.7':
// prime256v1/secp256r1
ret.fulltype = 'ecdsa-sha2-nistp256';
break;
case '1.3.132.0.34':
// secp384r1
ret.fulltype = 'ecdsa-sha2-nistp384';
break;
case '1.3.132.0.35':
// secp521r1
ret.fulltype = 'ecdsa-sha2-nistp521';
break;
}
}
if (ret.fulltype === undefined)
return new Error('Unsupported EC private key type');
}
ret.private = privData;
} else {
// possibly encrypted, headers
for (i = 1, len = data.length; i < len; ++i) {
m = RE_HEADER_OPENSSH.exec(data[i]);
if (m) {
m[1] = m[1].toLowerCase();
if (m[1] === 'dek-info') {
m[2] = m[2].split(',');
ret.encryption = m[2][0].toLowerCase();
if (m[2].length > 1)
ret.extra = m[2].slice(1);
}
} else if (data[i].length)
break;
}
ret.private = new Buffer(data.slice(i, -1).join(''), 'base64');
}
ret.type = keyType;
ret.privateOrig = new Buffer(orig);
} else if (m = RE_HEADER_OPENSSH_PUB.exec(data[0])) {
// OpenSSH public key
ret.fulltype = m[1];
ret.type = (m[2] || 'ec').toLowerCase();
ret.public = new Buffer(m[4], 'base64');
ret.publicOrig = new Buffer(orig);
ret.comment = m[5];
if (m[3]) // ECDSA only
ret.curve = 'nistp' + m[3];
} else if (RE_HEADER_RFC4716_PUB.test(data[0])
&& RE_FOOTER_RFC4716_PUB.test(data.slice(-1))) {
if (data[1].indexOf(': ') === -1) {
// no headers
ret.public = new Buffer(data.slice(1, -1).join(''), 'base64');
} else {
// headers
for (i = 1, len = data.length; i < len; ++i) {
if (data[i].indexOf(': ') === -1) {
if (data[i].length)
break; // start of key data
else
continue; // empty line
}
while (data[i].substr(-1) === '\\') {
if (i + 1 < len) {
data[i] = data[i].slice(0, -1) + data[i + 1];
data.splice(i + 1, 1);
--len;
} else
return new Error('RFC4716 public key missing header continuation line');
}
m = RE_HEADER_RFC4716.exec(data[i]);
if (m) {
m[1] = m[1].toLowerCase();
if (m[1] === 'comment') {
ret.comment = m[2] || '';
if (ret.comment[0] === '"' && ret.comment.substr(-1) === '"')
ret.comment = ret.comment.slice(1, -1);
}
} else
return new Error('RFC4716 public key invalid header line');
}
ret.public = new Buffer(data.slice(i, -1).join(''), 'base64');
}
len = ret.public.readUInt32BE(0, true);
var fulltype = ret.public.toString('ascii', 4, 4 + len);
ret.fulltype = fulltype;
if (fulltype === 'ssh-dss')
ret.type = 'dss';
else if (fulltype === 'ssh-rsa')
ret.type = 'rsa';
else
return new Error('Unsupported RFC4716 public key type: ' + fulltype);
ret.public = ret.public.slice(11);
ret.publicOrig = new Buffer(orig);
} else if (m = RE_PPK.exec(orig)) {
// m[1] = short type
// m[2] = encryption type
// m[3] = comment
// m[4] = base64-encoded public key data:
// for "ssh-rsa":
// string "ssh-rsa"
// mpint e (public exponent)
// mpint n (modulus)
// for "ssh-dss":
// string "ssh-dss"
// mpint p (modulus)
// mpint q (prime)
// mpint g (base number)
// mpint y (public key parameter: g^x mod p)
// m[5] = base64-encoded private key data:
// for "ssh-rsa":
// mpint d (private exponent)
// mpint p (prime 1)
// mpint q (prime 2)
// mpint iqmp ([inverse of q] mod p)
// for "ssh-dss":
// mpint x (private key parameter)
// m[6] = SHA1 HMAC over:
// string name of algorithm ("ssh-dss", "ssh-rsa")
// string encryption type
// string comment
// string public key data
// string private-plaintext (including the final padding)
// avoid cyclic require by requiring on first use
if (!utils)
utils = require('./utils');
ret.ppk = true;
ret.type = m[1];
ret.fulltype = 'ssh-' + m[1];
if (m[2] !== 'none')
ret.encryption = m[2];
ret.comment = m[3];
ret.public = new Buffer(m[4].replace(/\r?\n/g, ''), 'base64');
var privateKey = new Buffer(m[5].replace(/\r?\n/g, ''), 'base64');
ret.privateMAC = m[6].replace(/\r?\n/g, '');
// automatically verify private key MAC if we don't need to wait for
// decryption
if (!ret.encryption) {
var valid = utils.verifyPPKMAC(ret, undefined, privateKey);
if (!valid)
throw new Error('PPK MAC mismatch');
}
// generate a PEM encoded version of the public key
var pubkey = utils.genPublicKey(ret);
ret.public = pubkey.public;
ret.publicOrig = pubkey.publicOrig;
ret.private = privateKey;
// automatically convert private key data to OpenSSL format (including PEM)
// if we don't need to wait for decryption
if (!ret.encryption)
utils.convertPPKPrivate(ret);
} else
return new Error('Unsupported key format');
return ret;
};

2967
build/node_modules/ssh2-streams/lib/sftp.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

5403
build/node_modules/ssh2-streams/lib/ssh.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

817
build/node_modules/ssh2-streams/lib/utils.js generated vendored Normal file
View File

@@ -0,0 +1,817 @@
var crypto = require('crypto');
var Ber = require('asn1').Ber;
var BigInteger = require('./jsbn'); // only for converting PPK -> OpenSSL format
var SSH_TO_OPENSSL = require('./constants').SSH_TO_OPENSSL;
var RE_STREAM = /^arcfour/i;
var RE_KEY_LEN = /(.{64})/g;
// XXX the value of 2400 from dropbear is only for certain strings, not all
// strings. for example the list strings used during handshakes
var MAX_STRING_LEN = Infinity;//2400; // taken from dropbear
var PPK_IV = new Buffer([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
module.exports = {
iv_inc: iv_inc,
isStreamCipher: isStreamCipher,
readInt: readInt,
readString: readString,
parseKey: require('./keyParser'),
genPublicKey: genPublicKey,
convertPPKPrivate: convertPPKPrivate,
verifyPPKMAC: verifyPPKMAC,
decryptKey: decryptKey,
DSASigBERToBare: DSASigBERToBare,
DSASigBareToBER: DSASigBareToBER,
ECDSASigASN1ToSSH: ECDSASigASN1ToSSH,
ECDSASigSSHToASN1: ECDSASigSSHToASN1,
RSAKeySSHToASN1: RSAKeySSHToASN1,
DSAKeySSHToASN1: DSAKeySSHToASN1,
ECDSAKeySSHToASN1: ECDSAKeySSHToASN1
};
function iv_inc(iv) {
var n = 12;
var c = 0;
do {
--n;
c = iv[n];
if (c === 255)
iv[n] = 0;
else {
iv[n] = ++c;
return;
}
} while (n > 4);
}
function isStreamCipher(name) {
return RE_STREAM.test(name);
}
function readInt(buffer, start, stream, cb) {
var bufferLen = buffer.length;
if (start < 0 || start >= bufferLen || (bufferLen - start) < 4) {
stream && stream._cleanup(cb);
return false;
}
return buffer.readUInt32BE(start, true);
}
function DSASigBERToBare(signature) {
if (signature.length <= 40)
return signature;
// This is a quick and dirty way to get from BER encoded r and s that
// OpenSSL gives us, to just the bare values back to back (40 bytes
// total) like OpenSSH (and possibly others) are expecting
var asnReader = new Ber.Reader(signature);
asnReader.readSequence();
var r = asnReader.readString(Ber.Integer, true);
var s = asnReader.readString(Ber.Integer, true);
var rOffset = 0;
var sOffset = 0;
if (r.length < 20) {
var rNew = new Buffer(20);
r.copy(rNew, 1);
r = rNew;
r[0] = 0;
}
if (s.length < 20) {
var sNew = new Buffer(20);
s.copy(sNew, 1);
s = sNew;
s[0] = 0;
}
if (r.length > 20 && r[0] === 0x00)
rOffset = 1;
if (s.length > 20 && s[0] === 0x00)
sOffset = 1;
var newSig = new Buffer((r.length - rOffset) + (s.length - sOffset));
r.copy(newSig, 0, rOffset);
s.copy(newSig, r.length - rOffset, sOffset);
return newSig;
}
function DSASigBareToBER(signature) {
if (signature.length > 40)
return signature;
// Change bare signature r and s values to ASN.1 BER values for OpenSSL
var asnWriter = new Ber.Writer();
asnWriter.startSequence();
var r = signature.slice(0, 20);
var s = signature.slice(20);
if (r[0] & 0x80) {
var rNew = new Buffer(21);
rNew[0] = 0x00;
r.copy(rNew, 1);
r = rNew;
} else if (r[0] === 0x00 && !(r[1] & 0x80)) {
r = r.slice(1);
}
if (s[0] & 0x80) {
var sNew = new Buffer(21);
sNew[0] = 0x00;
s.copy(sNew, 1);
s = sNew;
} else if (s[0] === 0x00 && !(s[1] & 0x80)) {
s = s.slice(1);
}
asnWriter.writeBuffer(r, Ber.Integer);
asnWriter.writeBuffer(s, Ber.Integer);
asnWriter.endSequence();
return asnWriter.buffer;
}
function ECDSASigASN1ToSSH(signature) {
if (signature[0] === 0x00)
return signature;
// Convert SSH signature parameters to ASN.1 BER values for OpenSSL
var asnReader = new Ber.Reader(signature);
asnReader.readSequence();
var r = asnReader.readString(Ber.Integer, true);
var s = asnReader.readString(Ber.Integer, true);
if (r === null || s === null)
throw new Error('Invalid signature');
var newSig = new Buffer(4 + r.length + 4 + s.length);
newSig.writeUInt32BE(r.length, 0, true);
r.copy(newSig, 4);
newSig.writeUInt32BE(s.length, 4 + r.length, true);
s.copy(newSig, 4 + 4 + r.length);
return newSig;
}
function ECDSASigSSHToASN1(signature, self, callback) {
// Convert SSH signature parameters to ASN.1 BER values for OpenSSL
var r = readString(signature, 0, self, callback);
if (r === false)
return false;
var s = readString(signature, signature._pos, self, callback);
if (s === false)
return false;
var asnWriter = new Ber.Writer();
asnWriter.startSequence();
asnWriter.writeBuffer(r, Ber.Integer);
asnWriter.writeBuffer(s, Ber.Integer);
asnWriter.endSequence();
return asnWriter.buffer;
}
function RSAKeySSHToASN1(key, self, callback) {
// Convert SSH key parameters to ASN.1 BER values for OpenSSL
var e = readString(key, key._pos, self, callback);
if (e === false)
return false;
var n = readString(key, key._pos, self, callback);
if (n === false)
return false;
var asnWriter = new Ber.Writer();
asnWriter.startSequence();
// algorithm
asnWriter.startSequence();
asnWriter.writeOID('1.2.840.113549.1.1.1'); // rsaEncryption
// algorithm parameters (RSA has none)
asnWriter.writeNull();
asnWriter.endSequence();
// subjectPublicKey
asnWriter.startSequence(Ber.BitString);
asnWriter.writeByte(0x00);
asnWriter.startSequence();
asnWriter.writeBuffer(n, Ber.Integer);
asnWriter.writeBuffer(e, Ber.Integer);
asnWriter.endSequence();
asnWriter.endSequence();
asnWriter.endSequence();
return asnWriter.buffer;
}
function DSAKeySSHToASN1(key, self, callback) {
// Convert SSH key parameters to ASN.1 BER values for OpenSSL
var p = readString(key, key._pos, self, callback);
if (p === false)
return false;
var q = readString(key, key._pos, self, callback);
if (q === false)
return false;
var g = readString(key, key._pos, self, callback);
if (g === false)
return false;
var y = readString(key, key._pos, self, callback);
if (y === false)
return false;
var asnWriter = new Ber.Writer();
asnWriter.startSequence();
// algorithm
asnWriter.startSequence();
asnWriter.writeOID('1.2.840.10040.4.1'); // id-dsa
// algorithm parameters
asnWriter.startSequence();
asnWriter.writeBuffer(p, Ber.Integer);
asnWriter.writeBuffer(q, Ber.Integer);
asnWriter.writeBuffer(g, Ber.Integer);
asnWriter.endSequence();
asnWriter.endSequence();
// subjectPublicKey
asnWriter.startSequence(Ber.BitString);
asnWriter.writeByte(0x00);
asnWriter.writeBuffer(y, Ber.Integer);
asnWriter.endSequence();
asnWriter.endSequence();
return asnWriter.buffer;
}
function ECDSAKeySSHToASN1(key, self, callback) {
// Convert SSH key parameters to ASN.1 BER values for OpenSSL
var curve = readString(key, key._pos, self, callback);
if (curve === false)
return false;
var Q = readString(key, key._pos, self, callback);
if (Q === false)
return false;
var ecCurveOID;
switch (curve.toString('ascii')) {
case 'nistp256':
// prime256v1/secp256r1
ecCurveOID = '1.2.840.10045.3.1.7';
break;
case 'nistp384':
// secp384r1
ecCurveOID = '1.3.132.0.34';
break;
case 'nistp521':
// secp521r1
ecCurveOID = '1.3.132.0.35';
break;
default:
return false;
}
var asnWriter = new Ber.Writer();
asnWriter.startSequence();
// algorithm
asnWriter.startSequence();
asnWriter.writeOID('1.2.840.10045.2.1'); // id-ecPublicKey
// algorithm parameters (namedCurve)
asnWriter.writeOID(ecCurveOID);
asnWriter.endSequence();
// subjectPublicKey
asnWriter.startSequence(Ber.BitString);
asnWriter.writeByte(0x00);
// XXX: hack to write a raw buffer without a tag -- yuck
asnWriter._ensure(Q.length);
Q.copy(asnWriter._buf, asnWriter._offset, 0, Q.length);
asnWriter._offset += Q.length;
// end hack
asnWriter.endSequence();
asnWriter.endSequence();
return asnWriter.buffer;
}
function decryptKey(keyInfo, passphrase) {
if (keyInfo._decrypted || !keyInfo.encryption)
return;
var keylen = 0;
var key;
var iv;
var dc;
keyInfo.encryption = (SSH_TO_OPENSSL[keyInfo.encryption]
|| keyInfo.encryption);
switch (keyInfo.encryption) {
case 'aes-256-cbc':
case 'aes-256-ctr':
keylen = 32;
break;
case 'des-ede3-cbc':
case 'des-ede3':
case 'aes-192-cbc':
case 'aes-192-ctr':
keylen = 24;
break;
case 'aes-128-cbc':
case 'aes-128-ctr':
case 'cast-cbc':
case 'bf-cbc':
keylen = 16;
break;
default:
throw new Error('Unsupported cipher for encrypted key: '
+ keyInfo.encryption);
}
if (keyInfo.ppk) {
iv = PPK_IV;
key = Buffer.concat([
crypto.createHash('sha1')
.update('\x00\x00\x00\x00' + passphrase, 'utf8')
.digest(),
crypto.createHash('sha1')
.update('\x00\x00\x00\x01' + passphrase, 'utf8')
.digest()
]);
key = key.slice(0, keylen);
} else {
iv = new Buffer(keyInfo.extra[0], 'hex');
key = crypto.createHash('md5')
.update(passphrase, 'utf8')
.update(iv.slice(0, 8))
.digest();
while (keylen > key.length) {
key = Buffer.concat([
key,
(crypto.createHash('md5')
.update(key)
.update(passphrase, 'utf8')
.update(iv)
.digest()).slice(0, 8)
]);
}
if (key.length > keylen)
key = key.slice(0, keylen);
}
dc = crypto.createDecipheriv(keyInfo.encryption, key, iv);
dc.setAutoPadding(false);
keyInfo.private = Buffer.concat([ dc.update(keyInfo.private), dc.final() ]);
keyInfo._decrypted = true;
if (keyInfo.privateOrig) {
// Update our original base64-encoded version of the private key
var orig = keyInfo.privateOrig.toString('utf8');
var newOrig = /^(.+(?:\r\n|\n))/.exec(orig)[1];
var b64key = keyInfo.private.toString('base64');
newOrig += b64key.match(/.{1,70}/g).join('\n');
newOrig += /((?:\r\n|\n).+)$/.exec(orig)[1];
keyInfo.privateOrig = newOrig;
} else if (keyInfo.ppk) {
var valid = verifyPPKMAC(keyInfo, passphrase, keyInfo.private);
if (!valid)
throw new Error('PPK MAC mismatch');
// Automatically convert private key data to OpenSSL format
// (including PEM)
convertPPKPrivate(keyInfo);
}
// Fill in full key type
// TODO: make DRY, we do this also in keyParser
if (keyInfo.type !== 'ec') {
keyInfo.fulltype = 'ssh-' + keyInfo.type;
} else {
// ECDSA
var asnReader = new Ber.Reader(keyInfo.private);
asnReader.readSequence();
asnReader.readInt();
asnReader.readString(Ber.OctetString, true);
asnReader.readByte(); // Skip "complex" context type byte
var offset = asnReader.readLength(); // Skip context length
if (offset !== null) {
asnReader._offset = offset;
switch (asnReader.readOID()) {
case '1.2.840.10045.3.1.7':
// prime256v1/secp256r1
keyInfo.fulltype = 'ecdsa-sha2-nistp256';
break;
case '1.3.132.0.34':
// secp384r1
keyInfo.fulltype = 'ecdsa-sha2-nistp384';
break;
case '1.3.132.0.35':
// secp521r1
keyInfo.fulltype = 'ecdsa-sha2-nistp521';
break;
}
}
if (keyInfo.fulltype === undefined)
return new Error('Unsupported EC private key type');
}
}
function genPublicKey(keyInfo) {
var publicKey;
var i;
// RSA
var n;
var e;
// DSA
var p;
var q;
var g;
var y;
// ECDSA
var d;
var Q;
var ecCurveOID;
var ecCurveName;
if (keyInfo.private) {
// parsing private key in ASN.1 format in order to generate a public key
var privKey = keyInfo.private;
var asnReader = new Ber.Reader(privKey);
var errMsg;
if (asnReader.readSequence() === null) {
errMsg = 'Malformed private key (expected sequence)';
if (keyInfo._decrypted)
errMsg += '. Bad passphrase?';
throw new Error(errMsg);
}
// version (ignored)
if (asnReader.readInt() === null) {
errMsg = 'Malformed private key (expected version)';
if (keyInfo._decrypted)
errMsg += '. Bad passphrase?';
throw new Error(errMsg);
}
if (keyInfo.type === 'rsa') {
// modulus (n) -- integer
n = asnReader.readString(Ber.Integer, true);
if (n === null) {
errMsg = 'Malformed private key (expected RSA n value)';
if (keyInfo._decrypted)
errMsg += '. Bad passphrase?';
throw new Error(errMsg);
}
// public exponent (e) -- integer
e = asnReader.readString(Ber.Integer, true);
if (e === null) {
errMsg = 'Malformed private key (expected RSA e value)';
if (keyInfo._decrypted)
errMsg += '. Bad passphrase?';
throw new Error(errMsg);
}
publicKey = new Buffer(4 + 7 // ssh-rsa
+ 4 + n.length
+ 4 + e.length);
publicKey.writeUInt32BE(7, 0, true);
publicKey.write('ssh-rsa', 4, 7, 'ascii');
i = 4 + 7;
publicKey.writeUInt32BE(e.length, i, true);
e.copy(publicKey, i += 4);
publicKey.writeUInt32BE(n.length, i += e.length, true);
n.copy(publicKey, i += 4);
} else if (keyInfo.type === 'dss') { // DSA
// prime (p) -- integer
p = asnReader.readString(Ber.Integer, true);
if (p === null) {
errMsg = 'Malformed private key (expected DSA p value)';
if (keyInfo._decrypted)
errMsg += '. Bad passphrase?';
throw new Error(errMsg);
}
// group order (q) -- integer
q = asnReader.readString(Ber.Integer, true);
if (q === null) {
errMsg = 'Malformed private key (expected DSA q value)';
if (keyInfo._decrypted)
errMsg += '. Bad passphrase?';
throw new Error(errMsg);
}
// group generator (g) -- integer
g = asnReader.readString(Ber.Integer, true);
if (g === null) {
errMsg = 'Malformed private key (expected DSA g value)';
if (keyInfo._decrypted)
errMsg += '. Bad passphrase?';
throw new Error(errMsg);
}
// public key value (y) -- integer
y = asnReader.readString(Ber.Integer, true);
if (y === null) {
errMsg = 'Malformed private key (expected DSA y value)';
if (keyInfo._decrypted)
errMsg += '. Bad passphrase?';
throw new Error(errMsg);
}
publicKey = new Buffer(4 + 7 // ssh-dss
+ 4 + p.length
+ 4 + q.length
+ 4 + g.length
+ 4 + y.length);
publicKey.writeUInt32BE(7, 0, true);
publicKey.write('ssh-dss', 4, 7, 'ascii');
i = 4 + 7;
publicKey.writeUInt32BE(p.length, i, true);
p.copy(publicKey, i += 4);
publicKey.writeUInt32BE(q.length, i += p.length, true);
q.copy(publicKey, i += 4);
publicKey.writeUInt32BE(g.length, i += q.length, true);
g.copy(publicKey, i += 4);
publicKey.writeUInt32BE(y.length, i += g.length, true);
y.copy(publicKey, i += 4);
} else { // ECDSA
d = asnReader.readString(Ber.OctetString, true);
if (d === null)
throw new Error('Malformed private key (expected ECDSA private key)');
asnReader.readByte(); // Skip "complex" context type byte
var offset = asnReader.readLength(); // Skip context length
if (offset === null)
throw new Error('Malformed private key (expected ECDSA context value)');
asnReader._offset = offset;
ecCurveOID = asnReader.readOID();
if (ecCurveOID === null)
throw new Error('Malformed private key (expected ECDSA curve)');
var tempECDH;
switch (ecCurveOID) {
case '1.2.840.10045.3.1.7':
// prime256v1/secp256r1
keyInfo.curve = ecCurveName = 'nistp256';
tempECDH = crypto.createECDH('prime256v1');
break;
case '1.3.132.0.34':
// secp384r1
keyInfo.curve = ecCurveName = 'nistp384';
tempECDH = crypto.createECDH('secp384r1');
break;
case '1.3.132.0.35':
// secp521r1
keyInfo.curve = ecCurveName = 'nistp521';
tempECDH = crypto.createECDH('secp521r1');
break;
default:
throw new Error('Malformed private key (unsupported EC curve)');
}
tempECDH.setPrivateKey(d);
Q = tempECDH.getPublicKey();
publicKey = new Buffer(4 + 19 // ecdsa-sha2-<curve name>
+ 4 + 8 // <curve name>
+ 4 + Q.length);
publicKey.writeUInt32BE(19, 0, true);
publicKey.write('ecdsa-sha2-' + ecCurveName, 4, 19, 'ascii');
publicKey.writeUInt32BE(8, 23, true);
publicKey.write(ecCurveName, 27, 8, 'ascii');
publicKey.writeUInt32BE(Q.length, 35, true);
Q.copy(publicKey, 39);
}
} else if (keyInfo.public) {
publicKey = keyInfo.public;
if (keyInfo.type === 'ec') {
// TODO: support adding ecdsa-* prefix
ecCurveName = keyInfo.curve;
} else if (publicKey[0] !== 0
// check for missing ssh-{dsa,rsa} prefix
|| publicKey[1] !== 0
|| publicKey[2] !== 0
|| publicKey[3] !== 7
|| publicKey[4] !== 115
|| publicKey[5] !== 115
|| publicKey[6] !== 104
|| publicKey[7] !== 45
|| ((publicKey[8] !== 114
|| publicKey[9] !== 115
|| publicKey[10] !== 97)
&&
((publicKey[8] !== 100
|| publicKey[9] !== 115
|| publicKey[10] !== 115)))) {
var newPK = new Buffer(4 + 7 + publicKey.length);
publicKey.copy(newPK, 11);
newPK.writeUInt32BE(7, 0, true);
if (keyInfo.type === 'rsa')
newPK.write('ssh-rsa', 4, 7, 'ascii');
else
newPK.write('ssh-dss', 4, 7, 'ascii');
publicKey = newPK;
}
} else
throw new Error('Missing data generated by parseKey()');
// generate a public key format for use with OpenSSL
i = 4 + 7;
var fulltype;
var asn1KeyBuf;
if (keyInfo.type === 'rsa') {
fulltype = 'ssh-rsa';
asn1KeyBuf = RSAKeySSHToASN1(publicKey.slice(4 + 7));
} else if (keyInfo.type === 'dss') {
fulltype = 'ssh-dss';
asn1KeyBuf = DSAKeySSHToASN1(publicKey.slice(4 + 7));
} else { // ECDSA
fulltype = 'ecdsa-sha2-' + ecCurveName;
asn1KeyBuf = ECDSAKeySSHToASN1(publicKey.slice(4 + 19));
}
if (!asn1KeyBuf)
throw new Error('Invalid SSH-formatted public key');
var b64key = asn1KeyBuf.toString('base64').replace(RE_KEY_LEN, '$1\n');
var fullkey = '-----BEGIN PUBLIC KEY-----\n'
+ b64key
+ (b64key[b64key.length - 1] === '\n' ? '' : '\n')
+ '-----END PUBLIC KEY-----';
return {
type: keyInfo.type,
fulltype: fulltype,
curve: ecCurveName,
public: publicKey,
publicOrig: new Buffer(fullkey)
};
}
function verifyPPKMAC(keyInfo, passphrase, privateKey) {
if (keyInfo._macresult !== undefined)
return keyInfo._macresult;
else if (!keyInfo.ppk)
throw new Error("Key isn't a PPK");
else if (!keyInfo.privateMAC)
throw new Error('Missing MAC');
else if (!privateKey)
throw new Error('Missing raw private key data');
else if (keyInfo.encryption && typeof passphrase !== 'string')
throw new Error('Missing passphrase for encrypted PPK');
else if (keyInfo.encryption && !keyInfo._decrypted)
throw new Error('PPK must be decrypted before verifying MAC');
var mac = keyInfo.privateMAC;
var typelen = keyInfo.fulltype.length;
// encryption algorithm is converted at this point for use with OpenSSL,
// so we need to use the original value so that the MAC is calculated
// correctly
var enc = (keyInfo.encryption ? 'aes256-cbc' : 'none');
var enclen = enc.length;
var commlen = Buffer.byteLength(keyInfo.comment);
var pub = keyInfo.public;
var publen = pub.length;
var privlen = privateKey.length;
var macdata = new Buffer(4 + typelen
+ 4 + enclen
+ 4 + commlen
+ 4 + publen
+ 4 + privlen);
var p = 0;
macdata.writeUInt32BE(typelen, p, true);
macdata.write(keyInfo.fulltype, p += 4, typelen, 'ascii');
macdata.writeUInt32BE(enclen, p += typelen, true);
macdata.write(enc, p += 4, enclen, 'ascii');
macdata.writeUInt32BE(commlen, p += enclen, true);
macdata.write(keyInfo.comment, p += 4, commlen, 'utf8');
macdata.writeUInt32BE(publen, p += commlen, true);
pub.copy(macdata, p += 4);
macdata.writeUInt32BE(privlen, p += publen, true);
privateKey.copy(macdata, p += 4);
if (typeof passphrase !== 'string')
passphrase = '';
var mackey = crypto.createHash('sha1')
.update('putty-private-key-file-mac-key', 'ascii')
.update(passphrase, 'utf8')
.digest();
var calcMAC = crypto.createHmac('sha1', mackey)
.update(macdata)
.digest('hex');
return (keyInfo._macresult = (calcMAC === mac));
}
function convertPPKPrivate(keyInfo) {
if (!keyInfo.ppk || !keyInfo.public || !keyInfo.private)
throw new Error("Key isn't a PPK");
else if (keyInfo._converted)
return false;
var pub = keyInfo.public;
var priv = keyInfo.private;
var asnWriter = new Ber.Writer();
var p;
var q;
if (keyInfo.type === 'rsa') {
var e = readString(pub, 4 + 7);
var n = readString(pub, pub._pos);
var d = readString(priv, 0);
p = readString(priv, priv._pos);
q = readString(priv, priv._pos);
var iqmp = readString(priv, priv._pos);
var p1 = new BigInteger(p, 256);
var q1 = new BigInteger(q, 256);
var dmp1 = new BigInteger(d, 256);
var dmq1 = new BigInteger(d, 256);
dmp1 = new Buffer(dmp1.mod(p1.subtract(BigInteger.ONE)).toByteArray());
dmq1 = new Buffer(dmq1.mod(q1.subtract(BigInteger.ONE)).toByteArray());
asnWriter.startSequence();
asnWriter.writeInt(0x00, Ber.Integer);
asnWriter.writeBuffer(n, Ber.Integer);
asnWriter.writeBuffer(e, Ber.Integer);
asnWriter.writeBuffer(d, Ber.Integer);
asnWriter.writeBuffer(p, Ber.Integer);
asnWriter.writeBuffer(q, Ber.Integer);
asnWriter.writeBuffer(dmp1, Ber.Integer);
asnWriter.writeBuffer(dmq1, Ber.Integer);
asnWriter.writeBuffer(iqmp, Ber.Integer);
asnWriter.endSequence();
} else {
p = readString(pub, 4 + 7);
q = readString(pub, pub._pos);
var g = readString(pub, pub._pos);
var y = readString(pub, pub._pos);
var x = readString(priv, 0);
asnWriter.startSequence();
asnWriter.writeInt(0x00, Ber.Integer);
asnWriter.writeBuffer(p, Ber.Integer);
asnWriter.writeBuffer(q, Ber.Integer);
asnWriter.writeBuffer(g, Ber.Integer);
asnWriter.writeBuffer(y, Ber.Integer);
asnWriter.writeBuffer(x, Ber.Integer);
asnWriter.endSequence();
}
var b64key = asnWriter.buffer.toString('base64').replace(RE_KEY_LEN, '$1\n');
var fullkey = '-----BEGIN '
+ (keyInfo.type === 'rsa' ? 'RSA' : 'DSA')
+ ' PRIVATE KEY-----\n'
+ b64key
+ (b64key[b64key.length - 1] === '\n' ? '' : '\n')
+ '-----END '
+ (keyInfo.type === 'rsa' ? 'RSA' : 'DSA')
+ ' PRIVATE KEY-----';
keyInfo.private = asnWriter.buffer;
keyInfo.privateOrig = new Buffer(fullkey);
keyInfo._converted = true;
return true;
}
function readString(buffer, start, encoding, stream, cb, maxLen) {
if (encoding && !Buffer.isBuffer(encoding) && typeof encoding !== 'string') {
if (typeof cb === 'number')
maxLen = cb;
cb = stream;
stream = encoding;
encoding = undefined;
}
start || (start = 0);
var bufferLen = buffer.length;
var left = (bufferLen - start);
var len;
var end;
if (start < 0 || start >= bufferLen || left < 4) {
stream && stream._cleanup(cb);
return false;
}
len = buffer.readUInt32BE(start, true);
if (len > (maxLen || MAX_STRING_LEN) || left < (4 + len)) {
stream && stream._cleanup(cb);
return false;
}
start += 4;
end = start + len;
buffer._pos = end;
if (encoding) {
if (Buffer.isBuffer(encoding)) {
buffer.copy(encoding, 0, start, end);
return encoding;
} else
return buffer.toString(encoding, start, end);
} else
return buffer.slice(start, end);
}