summaryrefslogtreecommitdiff
path: root/node_modules/sshpk
diff options
context:
space:
mode:
authorLinuxWizard42 <computerwizard@linuxmail.org>2022-10-12 22:54:37 +0300
committerLinuxWizard42 <computerwizard@linuxmail.org>2022-10-12 22:54:37 +0300
commit703e03aba33f234712206769f57717ba7d92d23d (patch)
tree0041f04ccb75bd5379c764e9fe42249fffe75fc3 /node_modules/sshpk
parentab6e257e6e9d9a483d7e86f220d8b209a2cd7753 (diff)
downloadFlashRunner-703e03aba33f234712206769f57717ba7d92d23d.tar.gz
FlashRunner-703e03aba33f234712206769f57717ba7d92d23d.tar.zst
Added export_allowed file to make repository visible in cgit
Diffstat (limited to 'node_modules/sshpk')
-rw-r--r--node_modules/sshpk/.npmignore9
-rw-r--r--node_modules/sshpk/.travis.yml11
-rw-r--r--node_modules/sshpk/LICENSE18
-rw-r--r--node_modules/sshpk/README.md804
-rwxr-xr-xnode_modules/sshpk/bin/sshpk-conv243
-rwxr-xr-xnode_modules/sshpk/bin/sshpk-sign191
-rwxr-xr-xnode_modules/sshpk/bin/sshpk-verify167
-rw-r--r--node_modules/sshpk/lib/algs.js168
-rw-r--r--node_modules/sshpk/lib/certificate.js410
-rw-r--r--node_modules/sshpk/lib/dhe.js397
-rw-r--r--node_modules/sshpk/lib/ed-compat.js92
-rw-r--r--node_modules/sshpk/lib/errors.js84
-rw-r--r--node_modules/sshpk/lib/fingerprint.js220
-rw-r--r--node_modules/sshpk/lib/formats/auto.js124
-rw-r--r--node_modules/sshpk/lib/formats/dnssec.js287
-rw-r--r--node_modules/sshpk/lib/formats/openssh-cert.js352
-rw-r--r--node_modules/sshpk/lib/formats/pem.js290
-rw-r--r--node_modules/sshpk/lib/formats/pkcs1.js373
-rw-r--r--node_modules/sshpk/lib/formats/pkcs8.js631
-rw-r--r--node_modules/sshpk/lib/formats/putty.js99
-rw-r--r--node_modules/sshpk/lib/formats/rfc4253.js166
-rw-r--r--node_modules/sshpk/lib/formats/ssh-private.js262
-rw-r--r--node_modules/sshpk/lib/formats/ssh.js115
-rw-r--r--node_modules/sshpk/lib/formats/x509-pem.js88
-rw-r--r--node_modules/sshpk/lib/formats/x509.js752
-rw-r--r--node_modules/sshpk/lib/identity.js373
-rw-r--r--node_modules/sshpk/lib/index.js40
-rw-r--r--node_modules/sshpk/lib/key.js294
-rw-r--r--node_modules/sshpk/lib/private-key.js246
-rw-r--r--node_modules/sshpk/lib/signature.js314
-rw-r--r--node_modules/sshpk/lib/ssh-buffer.js149
-rw-r--r--node_modules/sshpk/lib/utils.js404
-rw-r--r--node_modules/sshpk/man/man1/sshpk-conv.1135
-rw-r--r--node_modules/sshpk/man/man1/sshpk-sign.181
-rw-r--r--node_modules/sshpk/man/man1/sshpk-verify.168
-rw-r--r--node_modules/sshpk/package.json60
36 files changed, 8517 insertions, 0 deletions
diff --git a/node_modules/sshpk/.npmignore b/node_modules/sshpk/.npmignore
new file mode 100644
index 0000000..8000b59
--- /dev/null
+++ b/node_modules/sshpk/.npmignore
@@ -0,0 +1,9 @@
+.gitmodules
+deps
+docs
+Makefile
+node_modules
+test
+tools
+coverage
+man/src
diff --git a/node_modules/sshpk/.travis.yml b/node_modules/sshpk/.travis.yml
new file mode 100644
index 0000000..c3394c2
--- /dev/null
+++ b/node_modules/sshpk/.travis.yml
@@ -0,0 +1,11 @@
+language: node_js
+node_js:
+ - "5.10"
+ - "4.4"
+ - "4.1"
+ - "0.12"
+ - "0.10"
+before_install:
+ - "make check"
+after_success:
+ - '[ "${TRAVIS_NODE_VERSION}" = "4.4" ] && make codecovio'
diff --git a/node_modules/sshpk/LICENSE b/node_modules/sshpk/LICENSE
new file mode 100644
index 0000000..f6d947d
--- /dev/null
+++ b/node_modules/sshpk/LICENSE
@@ -0,0 +1,18 @@
+Copyright Joyent, Inc. All rights reserved.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
diff --git a/node_modules/sshpk/README.md b/node_modules/sshpk/README.md
new file mode 100644
index 0000000..5740f74
--- /dev/null
+++ b/node_modules/sshpk/README.md
@@ -0,0 +1,804 @@
+sshpk
+=========
+
+Parse, convert, fingerprint and use SSH keys (both public and private) in pure
+node -- no `ssh-keygen` or other external dependencies.
+
+Supports RSA, DSA, ECDSA (nistp-\*) and ED25519 key types, in PEM (PKCS#1,
+PKCS#8) and OpenSSH formats.
+
+This library has been extracted from
+[`node-http-signature`](https://github.com/joyent/node-http-signature)
+(work by [Mark Cavage](https://github.com/mcavage) and
+[Dave Eddy](https://github.com/bahamas10)) and
+[`node-ssh-fingerprint`](https://github.com/bahamas10/node-ssh-fingerprint)
+(work by Dave Eddy), with additions (including ECDSA support) by
+[Alex Wilson](https://github.com/arekinath).
+
+Install
+-------
+
+```
+npm install sshpk
+```
+
+Examples
+--------
+
+```js
+var sshpk = require('sshpk');
+
+var fs = require('fs');
+
+/* Read in an OpenSSH-format public key */
+var keyPub = fs.readFileSync('id_rsa.pub');
+var key = sshpk.parseKey(keyPub, 'ssh');
+
+/* Get metadata about the key */
+console.log('type => %s', key.type);
+console.log('size => %d bits', key.size);
+console.log('comment => %s', key.comment);
+
+/* Compute key fingerprints, in new OpenSSH (>6.7) format, and old MD5 */
+console.log('fingerprint => %s', key.fingerprint().toString());
+console.log('old-style fingerprint => %s', key.fingerprint('md5').toString());
+```
+
+Example output:
+
+```
+type => rsa
+size => 2048 bits
+comment => foo@foo.com
+fingerprint => SHA256:PYC9kPVC6J873CSIbfp0LwYeczP/W4ffObNCuDJ1u5w
+old-style fingerprint => a0:c8:ad:6c:32:9a:32:fa:59:cc:a9:8c:0a:0d:6e:bd
+```
+
+More examples: converting between formats:
+
+```js
+/* Read in a PEM public key */
+var keyPem = fs.readFileSync('id_rsa.pem');
+var key = sshpk.parseKey(keyPem, 'pem');
+
+/* Convert to PEM PKCS#8 public key format */
+var pemBuf = key.toBuffer('pkcs8');
+
+/* Convert to SSH public key format (and return as a string) */
+var sshKey = key.toString('ssh');
+```
+
+Signing and verifying:
+
+```js
+/* Read in an OpenSSH/PEM *private* key */
+var keyPriv = fs.readFileSync('id_ecdsa');
+var key = sshpk.parsePrivateKey(keyPriv, 'pem');
+
+var data = 'some data';
+
+/* Sign some data with the key */
+var s = key.createSign('sha1');
+s.update(data);
+var signature = s.sign();
+
+/* Now load the public key (could also use just key.toPublic()) */
+var keyPub = fs.readFileSync('id_ecdsa.pub');
+key = sshpk.parseKey(keyPub, 'ssh');
+
+/* Make a crypto.Verifier with this key */
+var v = key.createVerify('sha1');
+v.update(data);
+var valid = v.verify(signature);
+/* => true! */
+```
+
+Matching fingerprints with keys:
+
+```js
+var fp = sshpk.parseFingerprint('SHA256:PYC9kPVC6J873CSIbfp0LwYeczP/W4ffObNCuDJ1u5w');
+
+var keys = [sshpk.parseKey(...), sshpk.parseKey(...), ...];
+
+keys.forEach(function (key) {
+ if (fp.matches(key))
+ console.log('found it!');
+});
+```
+
+Usage
+-----
+
+## Public keys
+
+### `parseKey(data[, format = 'auto'[, options]])`
+
+Parses a key from a given data format and returns a new `Key` object.
+
+Parameters
+
+- `data` -- Either a Buffer or String, containing the key
+- `format` -- String name of format to use, valid options are:
+ - `auto`: choose automatically from all below
+ - `pem`: supports both PKCS#1 and PKCS#8
+ - `ssh`: standard OpenSSH format,
+ - `pkcs1`, `pkcs8`: variants of `pem`
+ - `rfc4253`: raw OpenSSH wire format
+ - `openssh`: new post-OpenSSH 6.5 internal format, produced by
+ `ssh-keygen -o`
+ - `dnssec`: `.key` file format output by `dnssec-keygen` etc
+ - `putty`: the PuTTY `.ppk` file format (supports truncated variant without
+ all the lines from `Private-Lines:` onwards)
+- `options` -- Optional Object, extra options, with keys:
+ - `filename` -- Optional String, name for the key being parsed
+ (eg. the filename that was opened). Used to generate
+ Error messages
+ - `passphrase` -- Optional String, encryption passphrase used to decrypt an
+ encrypted PEM file
+
+### `Key.isKey(obj)`
+
+Returns `true` if the given object is a valid `Key` object created by a version
+of `sshpk` compatible with this one.
+
+Parameters
+
+- `obj` -- Object to identify
+
+### `Key#type`
+
+String, the type of key. Valid options are `rsa`, `dsa`, `ecdsa`.
+
+### `Key#size`
+
+Integer, "size" of the key in bits. For RSA/DSA this is the size of the modulus;
+for ECDSA this is the bit size of the curve in use.
+
+### `Key#comment`
+
+Optional string, a key comment used by some formats (eg the `ssh` format).
+
+### `Key#curve`
+
+Only present if `this.type === 'ecdsa'`, string containing the name of the
+named curve used with this key. Possible values include `nistp256`, `nistp384`
+and `nistp521`.
+
+### `Key#toBuffer([format = 'ssh'])`
+
+Convert the key into a given data format and return the serialized key as
+a Buffer.
+
+Parameters
+
+- `format` -- String name of format to use, for valid options see `parseKey()`
+
+### `Key#toString([format = 'ssh])`
+
+Same as `this.toBuffer(format).toString()`.
+
+### `Key#fingerprint([algorithm = 'sha256'[, hashType = 'ssh']])`
+
+Creates a new `Fingerprint` object representing this Key's fingerprint.
+
+Parameters
+
+- `algorithm` -- String name of hash algorithm to use, valid options are `md5`,
+ `sha1`, `sha256`, `sha384`, `sha512`
+- `hashType` -- String name of fingerprint hash type to use, valid options are
+ `ssh` (the type of fingerprint used by OpenSSH, e.g. in
+ `ssh-keygen`), `spki` (used by HPKP, some OpenSSL applications)
+
+### `Key#createVerify([hashAlgorithm])`
+
+Creates a `crypto.Verifier` specialized to use this Key (and the correct public
+key algorithm to match it). The returned Verifier has the same API as a regular
+one, except that the `verify()` function takes only the target signature as an
+argument.
+
+Parameters
+
+- `hashAlgorithm` -- optional String name of hash algorithm to use, any
+ supported by OpenSSL are valid, usually including
+ `sha1`, `sha256`.
+
+`v.verify(signature[, format])` Parameters
+
+- `signature` -- either a Signature object, or a Buffer or String
+- `format` -- optional String, name of format to interpret given String with.
+ Not valid if `signature` is a Signature or Buffer.
+
+### `Key#createDiffieHellman()`
+### `Key#createDH()`
+
+Creates a Diffie-Hellman key exchange object initialized with this key and all
+necessary parameters. This has the same API as a `crypto.DiffieHellman`
+instance, except that functions take `Key` and `PrivateKey` objects as
+arguments, and return them where indicated for.
+
+This is only valid for keys belonging to a cryptosystem that supports DHE
+or a close analogue (i.e. `dsa`, `ecdsa` and `curve25519` keys). An attempt
+to call this function on other keys will yield an `Error`.
+
+## Private keys
+
+### `parsePrivateKey(data[, format = 'auto'[, options]])`
+
+Parses a private key from a given data format and returns a new
+`PrivateKey` object.
+
+Parameters
+
+- `data` -- Either a Buffer or String, containing the key
+- `format` -- String name of format to use, valid options are:
+ - `auto`: choose automatically from all below
+ - `pem`: supports both PKCS#1 and PKCS#8
+ - `ssh`, `openssh`: new post-OpenSSH 6.5 internal format, produced by
+ `ssh-keygen -o`
+ - `pkcs1`, `pkcs8`: variants of `pem`
+ - `rfc4253`: raw OpenSSH wire format
+ - `dnssec`: `.private` format output by `dnssec-keygen` etc.
+- `options` -- Optional Object, extra options, with keys:
+ - `filename` -- Optional String, name for the key being parsed
+ (eg. the filename that was opened). Used to generate
+ Error messages
+ - `passphrase` -- Optional String, encryption passphrase used to decrypt an
+ encrypted PEM file
+
+### `generatePrivateKey(type[, options])`
+
+Generates a new private key of a certain key type, from random data.
+
+Parameters
+
+- `type` -- String, type of key to generate. Currently supported are `'ecdsa'`
+ and `'ed25519'`
+- `options` -- optional Object, with keys:
+ - `curve` -- optional String, for `'ecdsa'` keys, specifies the curve to use.
+ If ECDSA is specified and this option is not given, defaults to
+ using `'nistp256'`.
+
+### `PrivateKey.isPrivateKey(obj)`
+
+Returns `true` if the given object is a valid `PrivateKey` object created by a
+version of `sshpk` compatible with this one.
+
+Parameters
+
+- `obj` -- Object to identify
+
+### `PrivateKey#type`
+
+String, the type of key. Valid options are `rsa`, `dsa`, `ecdsa`.
+
+### `PrivateKey#size`
+
+Integer, "size" of the key in bits. For RSA/DSA this is the size of the modulus;
+for ECDSA this is the bit size of the curve in use.
+
+### `PrivateKey#curve`
+
+Only present if `this.type === 'ecdsa'`, string containing the name of the
+named curve used with this key. Possible values include `nistp256`, `nistp384`
+and `nistp521`.
+
+### `PrivateKey#toBuffer([format = 'pkcs1'])`
+
+Convert the key into a given data format and return the serialized key as
+a Buffer.
+
+Parameters
+
+- `format` -- String name of format to use, valid options are listed under
+ `parsePrivateKey`. Note that ED25519 keys default to `openssh`
+ format instead (as they have no `pkcs1` representation).
+
+### `PrivateKey#toString([format = 'pkcs1'])`
+
+Same as `this.toBuffer(format).toString()`.
+
+### `PrivateKey#toPublic()`
+
+Extract just the public part of this private key, and return it as a `Key`
+object.
+
+### `PrivateKey#fingerprint([algorithm = 'sha256'])`
+
+Same as `this.toPublic().fingerprint()`.
+
+### `PrivateKey#createVerify([hashAlgorithm])`
+
+Same as `this.toPublic().createVerify()`.
+
+### `PrivateKey#createSign([hashAlgorithm])`
+
+Creates a `crypto.Sign` specialized to use this PrivateKey (and the correct
+key algorithm to match it). The returned Signer has the same API as a regular
+one, except that the `sign()` function takes no arguments, and returns a
+`Signature` object.
+
+Parameters
+
+- `hashAlgorithm` -- optional String name of hash algorithm to use, any
+ supported by OpenSSL are valid, usually including
+ `sha1`, `sha256`.
+
+`v.sign()` Parameters
+
+- none
+
+### `PrivateKey#derive(newType)`
+
+Derives a related key of type `newType` from this key. Currently this is
+only supported to change between `ed25519` and `curve25519` keys which are
+stored with the same private key (but usually distinct public keys in order
+to avoid degenerate keys that lead to a weak Diffie-Hellman exchange).
+
+Parameters
+
+- `newType` -- String, type of key to derive, either `ed25519` or `curve25519`
+
+## Fingerprints
+
+### `parseFingerprint(fingerprint[, options])`
+
+Pre-parses a fingerprint, creating a `Fingerprint` object that can be used to
+quickly locate a key by using the `Fingerprint#matches` function.
+
+Parameters
+
+- `fingerprint` -- String, the fingerprint value, in any supported format
+- `options` -- Optional Object, with properties:
+ - `algorithms` -- Array of strings, names of hash algorithms to limit
+ support to. If `fingerprint` uses a hash algorithm not on
+ this list, throws `InvalidAlgorithmError`.
+ - `hashType` -- String, the type of hash the fingerprint uses, either `ssh`
+ or `spki` (normally auto-detected based on the format, but
+ can be overridden)
+ - `type` -- String, the entity this fingerprint identifies, either `key` or
+ `certificate`
+
+### `Fingerprint.isFingerprint(obj)`
+
+Returns `true` if the given object is a valid `Fingerprint` object created by a
+version of `sshpk` compatible with this one.
+
+Parameters
+
+- `obj` -- Object to identify
+
+### `Fingerprint#toString([format])`
+
+Returns a fingerprint as a string, in the given format.
+
+Parameters
+
+- `format` -- Optional String, format to use, valid options are `hex` and
+ `base64`. If this `Fingerprint` uses the `md5` algorithm, the
+ default format is `hex`. Otherwise, the default is `base64`.
+
+### `Fingerprint#matches(keyOrCertificate)`
+
+Verifies whether or not this `Fingerprint` matches a given `Key` or
+`Certificate`. This function uses double-hashing to avoid leaking timing
+information. Returns a boolean.
+
+Note that a `Key`-type Fingerprint will always return `false` if asked to match
+a `Certificate` and vice versa.
+
+Parameters
+
+- `keyOrCertificate` -- a `Key` object or `Certificate` object, the entity to
+ match this fingerprint against
+
+## Signatures
+
+### `parseSignature(signature, algorithm, format)`
+
+Parses a signature in a given format, creating a `Signature` object. Useful
+for converting between the SSH and ASN.1 (PKCS/OpenSSL) signature formats, and
+also returned as output from `PrivateKey#createSign().sign()`.
+
+A Signature object can also be passed to a verifier produced by
+`Key#createVerify()` and it will automatically be converted internally into the
+correct format for verification.
+
+Parameters
+
+- `signature` -- a Buffer (binary) or String (base64), data of the actual
+ signature in the given format
+- `algorithm` -- a String, name of the algorithm to be used, possible values
+ are `rsa`, `dsa`, `ecdsa`
+- `format` -- a String, either `asn1` or `ssh`
+
+### `Signature.isSignature(obj)`
+
+Returns `true` if the given object is a valid `Signature` object created by a
+version of `sshpk` compatible with this one.
+
+Parameters
+
+- `obj` -- Object to identify
+
+### `Signature#toBuffer([format = 'asn1'])`
+
+Converts a Signature to the given format and returns it as a Buffer.
+
+Parameters
+
+- `format` -- a String, either `asn1` or `ssh`
+
+### `Signature#toString([format = 'asn1'])`
+
+Same as `this.toBuffer(format).toString('base64')`.
+
+## Certificates
+
+`sshpk` includes basic support for parsing certificates in X.509 (PEM) format
+and the OpenSSH certificate format. This feature is intended to be used mainly
+to access basic metadata about certificates, extract public keys from them, and
+also to generate simple self-signed certificates from an existing key.
+
+Notably, there is no implementation of CA chain-of-trust verification, and only
+very minimal support for key usage restrictions. Please do the security world
+a favour, and DO NOT use this code for certificate verification in the
+traditional X.509 CA chain style.
+
+### `parseCertificate(data, format)`
+
+Parameters
+
+ - `data` -- a Buffer or String
+ - `format` -- a String, format to use, one of `'openssh'`, `'pem'` (X.509 in a
+ PEM wrapper), or `'x509'` (raw DER encoded)
+
+### `createSelfSignedCertificate(subject, privateKey[, options])`
+
+Parameters
+
+ - `subject` -- an Identity, the subject of the certificate
+ - `privateKey` -- a PrivateKey, the key of the subject: will be used both to be
+ placed in the certificate and also to sign it (since this is
+ a self-signed certificate)
+ - `options` -- optional Object, with keys:
+ - `lifetime` -- optional Number, lifetime of the certificate from now in
+ seconds
+ - `validFrom`, `validUntil` -- optional Dates, beginning and end of
+ certificate validity period. If given
+ `lifetime` will be ignored
+ - `serial` -- optional Buffer, the serial number of the certificate
+ - `purposes` -- optional Array of String, X.509 key usage restrictions
+
+### `createCertificate(subject, key, issuer, issuerKey[, options])`
+
+Parameters
+
+ - `subject` -- an Identity, the subject of the certificate
+ - `key` -- a Key, the public key of the subject
+ - `issuer` -- an Identity, the issuer of the certificate who will sign it
+ - `issuerKey` -- a PrivateKey, the issuer's private key for signing
+ - `options` -- optional Object, with keys:
+ - `lifetime` -- optional Number, lifetime of the certificate from now in
+ seconds
+ - `validFrom`, `validUntil` -- optional Dates, beginning and end of
+ certificate validity period. If given
+ `lifetime` will be ignored
+ - `serial` -- optional Buffer, the serial number of the certificate
+ - `purposes` -- optional Array of String, X.509 key usage restrictions
+
+### `Certificate#subjects`
+
+Array of `Identity` instances describing the subject of this certificate.
+
+### `Certificate#issuer`
+
+The `Identity` of the Certificate's issuer (signer).
+
+### `Certificate#subjectKey`
+
+The public key of the subject of the certificate, as a `Key` instance.
+
+### `Certificate#issuerKey`
+
+The public key of the signing issuer of this certificate, as a `Key` instance.
+May be `undefined` if the issuer's key is unknown (e.g. on an X509 certificate).
+
+### `Certificate#serial`
+
+The serial number of the certificate. As this is normally a 64-bit or wider
+integer, it is returned as a Buffer.
+
+### `Certificate#purposes`
+
+Array of Strings indicating the X.509 key usage purposes that this certificate
+is valid for. The possible strings at the moment are:
+
+ * `'signature'` -- key can be used for digital signatures
+ * `'identity'` -- key can be used to attest about the identity of the signer
+ (X.509 calls this `nonRepudiation`)
+ * `'codeSigning'` -- key can be used to sign executable code
+ * `'keyEncryption'` -- key can be used to encrypt other keys
+ * `'encryption'` -- key can be used to encrypt data (only applies for RSA)
+ * `'keyAgreement'` -- key can be used for key exchange protocols such as
+ Diffie-Hellman
+ * `'ca'` -- key can be used to sign other certificates (is a Certificate
+ Authority)
+ * `'crl'` -- key can be used to sign Certificate Revocation Lists (CRLs)
+
+### `Certificate#getExtension(nameOrOid)`
+
+Retrieves information about a certificate extension, if present, or returns
+`undefined` if not. The string argument `nameOrOid` should be either the OID
+(for X509 extensions) or the name (for OpenSSH extensions) of the extension
+to retrieve.
+
+The object returned will have the following properties:
+
+ * `format` -- String, set to either `'x509'` or `'openssh'`
+ * `name` or `oid` -- String, only one set based on value of `format`
+ * `data` -- Buffer, the raw data inside the extension
+
+### `Certificate#getExtensions()`
+
+Returns an Array of all present certificate extensions, in the same manner and
+format as `getExtension()`.
+
+### `Certificate#isExpired([when])`
+
+Tests whether the Certificate is currently expired (i.e. the `validFrom` and
+`validUntil` dates specify a range of time that does not include the current
+time).
+
+Parameters
+
+ - `when` -- optional Date, if specified, tests whether the Certificate was or
+ will be expired at the specified time instead of now
+
+Returns a Boolean.
+
+### `Certificate#isSignedByKey(key)`
+
+Tests whether the Certificate was validly signed by the given (public) Key.
+
+Parameters
+
+ - `key` -- a Key instance
+
+Returns a Boolean.
+
+### `Certificate#isSignedBy(certificate)`
+
+Tests whether this Certificate was validly signed by the subject of the given
+certificate. Also tests that the issuer Identity of this Certificate and the
+subject Identity of the other Certificate are equivalent.
+
+Parameters
+
+ - `certificate` -- another Certificate instance
+
+Returns a Boolean.
+
+### `Certificate#fingerprint([hashAlgo])`
+
+Returns the X509-style fingerprint of the entire certificate (as a Fingerprint
+instance). This matches what a web-browser or similar would display as the
+certificate fingerprint and should not be confused with the fingerprint of the
+subject's public key.
+
+Parameters
+
+ - `hashAlgo` -- an optional String, any hash function name
+
+### `Certificate#toBuffer([format])`
+
+Serializes the Certificate to a Buffer and returns it.
+
+Parameters
+
+ - `format` -- an optional String, output format, one of `'openssh'`, `'pem'` or
+ `'x509'`. Defaults to `'x509'`.
+
+Returns a Buffer.
+
+### `Certificate#toString([format])`
+
+ - `format` -- an optional String, output format, one of `'openssh'`, `'pem'` or
+ `'x509'`. Defaults to `'pem'`.
+
+Returns a String.
+
+## Certificate identities
+
+### `identityForHost(hostname)`
+
+Constructs a host-type Identity for a given hostname.
+
+Parameters
+
+ - `hostname` -- the fully qualified DNS name of the host
+
+Returns an Identity instance.
+
+### `identityForUser(uid)`
+
+Constructs a user-type Identity for a given UID.
+
+Parameters
+
+ - `uid` -- a String, user identifier (login name)
+
+Returns an Identity instance.
+
+### `identityForEmail(email)`
+
+Constructs an email-type Identity for a given email address.
+
+Parameters
+
+ - `email` -- a String, email address
+
+Returns an Identity instance.
+
+### `identityFromDN(dn)`
+
+Parses an LDAP-style DN string (e.g. `'CN=foo, C=US'`) and turns it into an
+Identity instance.
+
+Parameters
+
+ - `dn` -- a String
+
+Returns an Identity instance.
+
+### `identityFromArray(arr)`
+
+Constructs an Identity from an array of DN components (see `Identity#toArray()`
+for the format).
+
+Parameters
+
+ - `arr` -- an Array of Objects, DN components with `name` and `value`
+
+Returns an Identity instance.
+
+
+Supported attributes in DNs:
+
+| Attribute name | OID |
+| -------------- | --- |
+| `cn` | `2.5.4.3` |
+| `o` | `2.5.4.10` |
+| `ou` | `2.5.4.11` |
+| `l` | `2.5.4.7` |
+| `s` | `2.5.4.8` |
+| `c` | `2.5.4.6` |
+| `sn` | `2.5.4.4` |
+| `postalCode` | `2.5.4.17` |
+| `serialNumber` | `2.5.4.5` |
+| `street` | `2.5.4.9` |
+| `x500UniqueIdentifier` | `2.5.4.45` |
+| `role` | `2.5.4.72` |
+| `telephoneNumber` | `2.5.4.20` |
+| `description` | `2.5.4.13` |
+| `dc` | `0.9.2342.19200300.100.1.25` |
+| `uid` | `0.9.2342.19200300.100.1.1` |
+| `mail` | `0.9.2342.19200300.100.1.3` |
+| `title` | `2.5.4.12` |
+| `gn` | `2.5.4.42` |
+| `initials` | `2.5.4.43` |
+| `pseudonym` | `2.5.4.65` |
+
+### `Identity#toString()`
+
+Returns the identity as an LDAP-style DN string.
+e.g. `'CN=foo, O=bar corp, C=us'`
+
+### `Identity#type`
+
+The type of identity. One of `'host'`, `'user'`, `'email'` or `'unknown'`
+
+### `Identity#hostname`
+### `Identity#uid`
+### `Identity#email`
+
+Set when `type` is `'host'`, `'user'`, or `'email'`, respectively. Strings.
+
+### `Identity#cn`
+
+The value of the first `CN=` in the DN, if any. It's probably better to use
+the `#get()` method instead of this property.
+
+### `Identity#get(name[, asArray])`
+
+Returns the value of a named attribute in the Identity DN. If there is no
+attribute of the given name, returns `undefined`. If multiple components
+of the DN contain an attribute of this name, an exception is thrown unless
+the `asArray` argument is given as `true` -- then they will be returned as
+an Array in the same order they appear in the DN.
+
+Parameters
+
+ - `name` -- a String
+ - `asArray` -- an optional Boolean
+
+### `Identity#toArray()`
+
+Returns the Identity as an Array of DN component objects. This looks like:
+
+```js
+[ {
+ "name": "cn",
+ "value": "Joe Bloggs"
+},
+{
+ "name": "o",
+ "value": "Organisation Ltd"
+} ]
+```
+
+Each object has a `name` and a `value` property. The returned objects may be
+safely modified.
+
+Errors
+------
+
+### `InvalidAlgorithmError`
+
+The specified algorithm is not valid, either because it is not supported, or
+because it was not included on a list of allowed algorithms.
+
+Thrown by `Fingerprint.parse`, `Key#fingerprint`.
+
+Properties
+
+- `algorithm` -- the algorithm that could not be validated
+
+### `FingerprintFormatError`
+
+The fingerprint string given could not be parsed as a supported fingerprint
+format, or the specified fingerprint format is invalid.
+
+Thrown by `Fingerprint.parse`, `Fingerprint#toString`.
+
+Properties
+
+- `fingerprint` -- if caused by a fingerprint, the string value given
+- `format` -- if caused by an invalid format specification, the string value given
+
+### `KeyParseError`
+
+The key data given could not be parsed as a valid key.
+
+Properties
+
+- `keyName` -- `filename` that was given to `parseKey`
+- `format` -- the `format` that was trying to parse the key (see `parseKey`)
+- `innerErr` -- the inner Error thrown by the format parser
+
+### `KeyEncryptedError`
+
+The key is encrypted with a symmetric key (ie, it is password protected). The
+parsing operation would succeed if it was given the `passphrase` option.
+
+Properties
+
+- `keyName` -- `filename` that was given to `parseKey`
+- `format` -- the `format` that was trying to parse the key (currently can only
+ be `"pem"`)
+
+### `CertificateParseError`
+
+The certificate data given could not be parsed as a valid certificate.
+
+Properties
+
+- `certName` -- `filename` that was given to `parseCertificate`
+- `format` -- the `format` that was trying to parse the key
+ (see `parseCertificate`)
+- `innerErr` -- the inner Error thrown by the format parser
+
+Friends of sshpk
+----------------
+
+ * [`sshpk-agent`](https://github.com/arekinath/node-sshpk-agent) is a library
+ for speaking the `ssh-agent` protocol from node.js, which uses `sshpk`
diff --git a/node_modules/sshpk/bin/sshpk-conv b/node_modules/sshpk/bin/sshpk-conv
new file mode 100755
index 0000000..e839ede
--- /dev/null
+++ b/node_modules/sshpk/bin/sshpk-conv
@@ -0,0 +1,243 @@
+#!/usr/bin/env node
+// -*- mode: js -*-
+// vim: set filetype=javascript :
+// Copyright 2018 Joyent, Inc. All rights reserved.
+
+var dashdash = require('dashdash');
+var sshpk = require('../lib/index');
+var fs = require('fs');
+var path = require('path');
+var tty = require('tty');
+var readline = require('readline');
+var getPassword = require('getpass').getPass;
+
+var options = [
+ {
+ names: ['outformat', 't'],
+ type: 'string',
+ help: 'Output format'
+ },
+ {
+ names: ['informat', 'T'],
+ type: 'string',
+ help: 'Input format'
+ },
+ {
+ names: ['file', 'f'],
+ type: 'string',
+ help: 'Input file name (default stdin)'
+ },
+ {
+ names: ['out', 'o'],
+ type: 'string',
+ help: 'Output file name (default stdout)'
+ },
+ {
+ names: ['private', 'p'],
+ type: 'bool',
+ help: 'Produce a private key as output'
+ },
+ {
+ names: ['derive', 'd'],
+ type: 'string',
+ help: 'Output a new key derived from this one, with given algo'
+ },
+ {
+ names: ['identify', 'i'],
+ type: 'bool',
+ help: 'Print key metadata instead of converting'
+ },
+ {
+ names: ['fingerprint', 'F'],
+ type: 'bool',
+ help: 'Output key fingerprint'
+ },
+ {
+ names: ['hash', 'H'],
+ type: 'string',
+ help: 'Hash function to use for key fingeprint with -F'
+ },
+ {
+ names: ['spki', 's'],
+ type: 'bool',
+ help: 'With -F, generates an SPKI fingerprint instead of SSH'
+ },
+ {
+ names: ['comment', 'c'],
+ type: 'string',
+ help: 'Set key comment, if output format supports'
+ },
+ {
+ names: ['help', 'h'],
+ type: 'bool',
+ help: 'Shows this help text'
+ }
+];
+
+if (require.main === module) {
+ var parser = dashdash.createParser({
+ options: options
+ });
+
+ try {
+ var opts = parser.parse(process.argv);
+ } catch (e) {
+ console.error('sshpk-conv: error: %s', e.message);
+ process.exit(1);
+ }
+
+ if (opts.help || opts._args.length > 1) {
+ var help = parser.help({}).trimRight();
+ console.error('sshpk-conv: converts between SSH key formats\n');
+ console.error(help);
+ console.error('\navailable key formats:');
+ console.error(' - pem, pkcs1 eg id_rsa');
+ console.error(' - ssh eg id_rsa.pub');
+ console.error(' - pkcs8 format you want for openssl');
+ console.error(' - openssh like output of ssh-keygen -o');
+ console.error(' - rfc4253 raw OpenSSH wire format');
+ console.error(' - dnssec dnssec-keygen format');
+ console.error(' - putty PuTTY ppk format');
+ console.error('\navailable fingerprint formats:');
+ console.error(' - hex colon-separated hex for SSH');
+ console.error(' straight hex for SPKI');
+ console.error(' - base64 SHA256:* format from OpenSSH');
+ process.exit(1);
+ }
+
+ /*
+ * Key derivation can only be done on private keys, so use of the -d
+ * option necessarily implies -p.
+ */
+ if (opts.derive)
+ opts.private = true;
+
+ var inFile = process.stdin;
+ var inFileName = 'stdin';
+
+ var inFilePath;
+ if (opts.file) {
+ inFilePath = opts.file;
+ } else if (opts._args.length === 1) {
+ inFilePath = opts._args[0];
+ }
+
+ if (inFilePath)
+ inFileName = path.basename(inFilePath);
+
+ try {
+ if (inFilePath) {
+ fs.accessSync(inFilePath, fs.R_OK);
+ inFile = fs.createReadStream(inFilePath);
+ }
+ } catch (e) {
+ ifError(e, 'error opening input file');
+ }
+
+ var outFile = process.stdout;
+
+ try {
+ if (opts.out && !opts.identify) {
+ fs.accessSync(path.dirname(opts.out), fs.W_OK);
+ outFile = fs.createWriteStream(opts.out);
+ }
+ } catch (e) {
+ ifError(e, 'error opening output file');
+ }
+
+ var bufs = [];
+ inFile.on('readable', function () {
+ var data;
+ while ((data = inFile.read()))
+ bufs.push(data);
+ });
+ var parseOpts = {};
+ parseOpts.filename = inFileName;
+ inFile.on('end', function processKey() {
+ var buf = Buffer.concat(bufs);
+ var fmt = 'auto';
+ if (opts.informat)
+ fmt = opts.informat;
+ var f = sshpk.parseKey;
+ if (opts.private)
+ f = sshpk.parsePrivateKey;
+ try {
+ var key = f(buf, fmt, parseOpts);
+ } catch (e) {
+ if (e.name === 'KeyEncryptedError') {
+ getPassword(function (err, pw) {
+ if (err)
+ ifError(err);
+ parseOpts.passphrase = pw;
+ processKey();
+ });
+ return;
+ }
+ ifError(e);
+ }
+
+ if (opts.derive)
+ key = key.derive(opts.derive);
+
+ if (opts.comment)
+ key.comment = opts.comment;
+
+ if (opts.identify) {
+ var kind = 'public';
+ if (sshpk.PrivateKey.isPrivateKey(key))
+ kind = 'private';
+ console.log('%s: a %d bit %s %s key', inFileName,
+ key.size, key.type.toUpperCase(), kind);
+ if (key.type === 'ecdsa')
+ console.log('ECDSA curve: %s', key.curve);
+ if (key.comment)
+ console.log('Comment: %s', key.comment);
+ console.log('SHA256 fingerprint: ' +
+ key.fingerprint('sha256').toString());
+ console.log('MD5 fingerprint: ' +
+ key.fingerprint('md5').toString());
+ console.log('SPKI-SHA256 fingerprint: ' +
+ key.fingerprint('sha256', 'spki').toString());
+ process.exit(0);
+ return;
+ }
+
+ if (opts.fingerprint) {
+ var hash = opts.hash;
+ var type = opts.spki ? 'spki' : 'ssh';
+ var format = opts.outformat;
+ var fp = key.fingerprint(hash, type).toString(format);
+ outFile.write(fp);
+ outFile.write('\n');
+ outFile.once('drain', function () {
+ process.exit(0);
+ });
+ return;
+ }
+
+ fmt = undefined;
+ if (opts.outformat)
+ fmt = opts.outformat;
+ outFile.write(key.toBuffer(fmt));
+ if (fmt === 'ssh' ||
+ (!opts.private && fmt === undefined))
+ outFile.write('\n');
+ outFile.once('drain', function () {
+ process.exit(0);
+ });
+ });
+}
+
+function ifError(e, txt) {
+ if (txt)
+ txt = txt + ': ';
+ else
+ txt = '';
+ console.error('sshpk-conv: ' + txt + e.name + ': ' + e.message);
+ if (process.env['DEBUG'] || process.env['V']) {
+ console.error(e.stack);
+ if (e.innerErr)
+ console.error(e.innerErr.stack);
+ }
+ process.exit(1);
+}
diff --git a/node_modules/sshpk/bin/sshpk-sign b/node_modules/sshpk/bin/sshpk-sign
new file mode 100755
index 0000000..673fc98
--- /dev/null
+++ b/node_modules/sshpk/bin/sshpk-sign
@@ -0,0 +1,191 @@
+#!/usr/bin/env node
+// -*- mode: js -*-
+// vim: set filetype=javascript :
+// Copyright 2015 Joyent, Inc. All rights reserved.
+
+var dashdash = require('dashdash');
+var sshpk = require('../lib/index');
+var fs = require('fs');
+var path = require('path');
+var getPassword = require('getpass').getPass;
+
+var options = [
+ {
+ names: ['hash', 'H'],
+ type: 'string',
+ help: 'Hash algorithm (sha1, sha256, sha384, sha512)'
+ },
+ {
+ names: ['verbose', 'v'],
+ type: 'bool',
+ help: 'Display verbose info about key and hash used'
+ },
+ {
+ names: ['identity', 'i'],
+ type: 'string',
+ help: 'Path to key to use'
+ },
+ {
+ names: ['file', 'f'],
+ type: 'string',
+ help: 'Input filename'
+ },
+ {
+ names: ['out', 'o'],
+ type: 'string',
+ help: 'Output filename'
+ },
+ {
+ names: ['format', 't'],
+ type: 'string',
+ help: 'Signature format (asn1, ssh, raw)'
+ },
+ {
+ names: ['binary', 'b'],
+ type: 'bool',
+ help: 'Output raw binary instead of base64'
+ },
+ {
+ names: ['help', 'h'],
+ type: 'bool',
+ help: 'Shows this help text'
+ }
+];
+
+var parseOpts = {};
+
+if (require.main === module) {
+ var parser = dashdash.createParser({
+ options: options
+ });
+
+ try {
+ var opts = parser.parse(process.argv);
+ } catch (e) {
+ console.error('sshpk-sign: error: %s', e.message);
+ process.exit(1);
+ }
+
+ if (opts.help || opts._args.length > 1) {
+ var help = parser.help({}).trimRight();
+ console.error('sshpk-sign: sign data using an SSH key\n');
+ console.error(help);
+ process.exit(1);
+ }
+
+ if (!opts.identity) {
+ var help = parser.help({}).trimRight();
+ console.error('sshpk-sign: the -i or --identity option ' +
+ 'is required\n');
+ console.error(help);
+ process.exit(1);
+ }
+
+ var keyData = fs.readFileSync(opts.identity);
+ parseOpts.filename = opts.identity;
+
+ run();
+}
+
+function run() {
+ var key;
+ try {
+ key = sshpk.parsePrivateKey(keyData, 'auto', parseOpts);
+ } catch (e) {
+ if (e.name === 'KeyEncryptedError') {
+ getPassword(function (err, pw) {
+ parseOpts.passphrase = pw;
+ run();
+ });
+ return;
+ }
+ console.error('sshpk-sign: error loading private key "' +
+ opts.identity + '": ' + e.name + ': ' + e.message);
+ process.exit(1);
+ }
+
+ var hash = opts.hash || key.defaultHashAlgorithm();
+
+ var signer;
+ try {
+ signer = key.createSign(hash);
+ } catch (e) {
+ console.error('sshpk-sign: error creating signer: ' +
+ e.name + ': ' + e.message);
+ process.exit(1);
+ }
+
+ if (opts.verbose) {
+ console.error('sshpk-sign: using %s-%s with a %d bit key',
+ key.type, hash, key.size);
+ }
+
+ var inFile = process.stdin;
+ var inFileName = 'stdin';
+
+ var inFilePath;
+ if (opts.file) {
+ inFilePath = opts.file;
+ } else if (opts._args.length === 1) {
+ inFilePath = opts._args[0];
+ }
+
+ if (inFilePath)
+ inFileName = path.basename(inFilePath);
+
+ try {
+ if (inFilePath) {
+ fs.accessSync(inFilePath, fs.R_OK);
+ inFile = fs.createReadStream(inFilePath);
+ }
+ } catch (e) {
+ console.error('sshpk-sign: error opening input file' +
+ ': ' + e.name + ': ' + e.message);
+ process.exit(1);
+ }
+
+ var outFile = process.stdout;
+
+ try {
+ if (opts.out && !opts.identify) {
+ fs.accessSync(path.dirname(opts.out), fs.W_OK);
+ outFile = fs.createWriteStream(opts.out);
+ }
+ } catch (e) {
+ console.error('sshpk-sign: error opening output file' +
+ ': ' + e.name + ': ' + e.message);
+ process.exit(1);
+ }
+
+ inFile.pipe(signer);
+ inFile.on('end', function () {
+ var sig;
+ try {
+ sig = signer.sign();
+ } catch (e) {
+ console.error('sshpk-sign: error signing data: ' +
+ e.name + ': ' + e.message);
+ process.exit(1);
+ }
+
+ var fmt = opts.format || 'asn1';
+ var output;
+ try {
+ output = sig.toBuffer(fmt);
+ if (!opts.binary)
+ output = output.toString('base64');
+ } catch (e) {
+ console.error('sshpk-sign: error converting signature' +
+ ' to ' + fmt + ' format: ' + e.name + ': ' +
+ e.message);
+ process.exit(1);
+ }
+
+ outFile.write(output);
+ if (!opts.binary)
+ outFile.write('\n');
+ outFile.once('drain', function () {
+ process.exit(0);
+ });
+ });
+}
diff --git a/node_modules/sshpk/bin/sshpk-verify b/node_modules/sshpk/bin/sshpk-verify
new file mode 100755
index 0000000..fc71a82
--- /dev/null
+++ b/node_modules/sshpk/bin/sshpk-verify
@@ -0,0 +1,167 @@
+#!/usr/bin/env node
+// -*- mode: js -*-
+// vim: set filetype=javascript :
+// Copyright 2015 Joyent, Inc. All rights reserved.
+
+var dashdash = require('dashdash');
+var sshpk = require('../lib/index');
+var fs = require('fs');
+var path = require('path');
+var Buffer = require('safer-buffer').Buffer;
+
+var options = [
+ {
+ names: ['hash', 'H'],
+ type: 'string',
+ help: 'Hash algorithm (sha1, sha256, sha384, sha512)'
+ },
+ {
+ names: ['verbose', 'v'],
+ type: 'bool',
+ help: 'Display verbose info about key and hash used'
+ },
+ {
+ names: ['identity', 'i'],
+ type: 'string',
+ help: 'Path to (public) key to use'
+ },
+ {
+ names: ['file', 'f'],
+ type: 'string',
+ help: 'Input filename'
+ },
+ {
+ names: ['format', 't'],
+ type: 'string',
+ help: 'Signature format (asn1, ssh, raw)'
+ },
+ {
+ names: ['signature', 's'],
+ type: 'string',
+ help: 'base64-encoded signature data'
+ },
+ {
+ names: ['help', 'h'],
+ type: 'bool',
+ help: 'Shows this help text'
+ }
+];
+
+if (require.main === module) {
+ var parser = dashdash.createParser({
+ options: options
+ });
+
+ try {
+ var opts = parser.parse(process.argv);
+ } catch (e) {
+ console.error('sshpk-verify: error: %s', e.message);
+ process.exit(3);
+ }
+
+ if (opts.help || opts._args.length > 1) {
+ var help = parser.help({}).trimRight();
+ console.error('sshpk-verify: sign data using an SSH key\n');
+ console.error(help);
+ process.exit(3);
+ }
+
+ if (!opts.identity) {
+ var help = parser.help({}).trimRight();
+ console.error('sshpk-verify: the -i or --identity option ' +
+ 'is required\n');
+ console.error(help);
+ process.exit(3);
+ }
+
+ if (!opts.signature) {
+ var help = parser.help({}).trimRight();
+ console.error('sshpk-verify: the -s or --signature option ' +
+ 'is required\n');
+ console.error(help);
+ process.exit(3);
+ }
+
+ var keyData = fs.readFileSync(opts.identity);
+
+ var key;
+ try {
+ key = sshpk.parseKey(keyData);
+ } catch (e) {
+ console.error('sshpk-verify: error loading key "' +
+ opts.identity + '": ' + e.name + ': ' + e.message);
+ process.exit(2);
+ }
+
+ var fmt = opts.format || 'asn1';
+ var sigData = Buffer.from(opts.signature, 'base64');
+
+ var sig;
+ try {
+ sig = sshpk.parseSignature(sigData, key.type, fmt);
+ } catch (e) {
+ console.error('sshpk-verify: error parsing signature: ' +
+ e.name + ': ' + e.message);
+ process.exit(2);
+ }
+
+ var hash = opts.hash || key.defaultHashAlgorithm();
+
+ var verifier;
+ try {
+ verifier = key.createVerify(hash);
+ } catch (e) {
+ console.error('sshpk-verify: error creating verifier: ' +
+ e.name + ': ' + e.message);
+ process.exit(2);
+ }
+
+ if (opts.verbose) {
+ console.error('sshpk-verify: using %s-%s with a %d bit key',
+ key.type, hash, key.size);
+ }
+
+ var inFile = process.stdin;
+ var inFileName = 'stdin';
+
+ var inFilePath;
+ if (opts.file) {
+ inFilePath = opts.file;
+ } else if (opts._args.length === 1) {
+ inFilePath = opts._args[0];
+ }
+
+ if (inFilePath)
+ inFileName = path.basename(inFilePath);
+
+ try {
+ if (inFilePath) {
+ fs.accessSync(inFilePath, fs.R_OK);
+ inFile = fs.createReadStream(inFilePath);
+ }
+ } catch (e) {
+ console.error('sshpk-verify: error opening input file' +
+ ': ' + e.name + ': ' + e.message);
+ process.exit(2);
+ }
+
+ inFile.pipe(verifier);
+ inFile.on('end', function () {
+ var ret;
+ try {
+ ret = verifier.verify(sig);
+ } catch (e) {
+ console.error('sshpk-verify: error verifying data: ' +
+ e.name + ': ' + e.message);
+ process.exit(1);
+ }
+
+ if (ret) {
+ console.error('OK');
+ process.exit(0);
+ }
+
+ console.error('NOT OK');
+ process.exit(1);
+ });
+}
diff --git a/node_modules/sshpk/lib/algs.js b/node_modules/sshpk/lib/algs.js
new file mode 100644
index 0000000..3b01e7d
--- /dev/null
+++ b/node_modules/sshpk/lib/algs.js
@@ -0,0 +1,168 @@
+// Copyright 2015 Joyent, Inc.
+
+var Buffer = require('safer-buffer').Buffer;
+
+var algInfo = {
+ 'dsa': {
+ parts: ['p', 'q', 'g', 'y'],
+ sizePart: 'p'
+ },
+ 'rsa': {
+ parts: ['e', 'n'],
+ sizePart: 'n'
+ },
+ 'ecdsa': {
+ parts: ['curve', 'Q'],
+ sizePart: 'Q'
+ },
+ 'ed25519': {
+ parts: ['A'],
+ sizePart: 'A'
+ }
+};
+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: ['A', 'k']
+ }
+};
+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: Buffer.from(('00' +
+ 'ffffffff 00000001 00000000 00000000' +
+ '00000000 ffffffff ffffffff ffffffff').
+ replace(/ /g, ''), 'hex'),
+ a: Buffer.from(('00' +
+ 'FFFFFFFF 00000001 00000000 00000000' +
+ '00000000 FFFFFFFF FFFFFFFF FFFFFFFC').
+ replace(/ /g, ''), 'hex'),
+ b: Buffer.from((
+ '5ac635d8 aa3a93e7 b3ebbd55 769886bc' +
+ '651d06b0 cc53b0f6 3bce3c3e 27d2604b').
+ replace(/ /g, ''), 'hex'),
+ s: Buffer.from(('00' +
+ 'c49d3608 86e70493 6a6678e1 139d26b7' +
+ '819f7e90').
+ replace(/ /g, ''), 'hex'),
+ n: Buffer.from(('00' +
+ 'ffffffff 00000000 ffffffff ffffffff' +
+ 'bce6faad a7179e84 f3b9cac2 fc632551').
+ replace(/ /g, ''), 'hex'),
+ G: Buffer.from(('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: Buffer.from(('00' +
+ 'ffffffff ffffffff ffffffff ffffffff' +
+ 'ffffffff ffffffff ffffffff fffffffe' +
+ 'ffffffff 00000000 00000000 ffffffff').
+ replace(/ /g, ''), 'hex'),
+ a: Buffer.from(('00' +
+ 'FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF' +
+ 'FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE' +
+ 'FFFFFFFF 00000000 00000000 FFFFFFFC').
+ replace(/ /g, ''), 'hex'),
+ b: Buffer.from((
+ 'b3312fa7 e23ee7e4 988e056b e3f82d19' +
+ '181d9c6e fe814112 0314088f 5013875a' +
+ 'c656398d 8a2ed19d 2a85c8ed d3ec2aef').
+ replace(/ /g, ''), 'hex'),
+ s: Buffer.from(('00' +
+ 'a335926a a319a27a 1d00896a 6773a482' +
+ '7acdac73').
+ replace(/ /g, ''), 'hex'),
+ n: Buffer.from(('00' +
+ 'ffffffff ffffffff ffffffff ffffffff' +
+ 'ffffffff ffffffff c7634d81 f4372ddf' +
+ '581a0db2 48b0a77a ecec196a ccc52973').
+ replace(/ /g, ''), 'hex'),
+ G: Buffer.from(('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: Buffer.from((
+ '01ffffff ffffffff ffffffff ffffffff' +
+ 'ffffffff ffffffff ffffffff ffffffff' +
+ 'ffffffff ffffffff ffffffff ffffffff' +
+ 'ffffffff ffffffff ffffffff ffffffff' +
+ 'ffff').replace(/ /g, ''), 'hex'),
+ a: Buffer.from(('01FF' +
+ 'FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF' +
+ 'FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF' +
+ 'FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF' +
+ 'FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFC').
+ replace(/ /g, ''), 'hex'),
+ b: Buffer.from(('51' +
+ '953eb961 8e1c9a1f 929a21a0 b68540ee' +
+ 'a2da725b 99b315f3 b8b48991 8ef109e1' +
+ '56193951 ec7e937b 1652c0bd 3bb1bf07' +
+ '3573df88 3d2c34f1 ef451fd4 6b503f00').
+ replace(/ /g, ''), 'hex'),
+ s: Buffer.from(('00' +
+ 'd09e8800 291cb853 96cc6717 393284aa' +
+ 'a0da64ba').replace(/ /g, ''), 'hex'),
+ n: Buffer.from(('01ff' +
+ 'ffffffff ffffffff ffffffff ffffffff' +
+ 'ffffffff ffffffff ffffffff fffffffa' +
+ '51868783 bf2f966b 7fcc0148 f709a5d0' +
+ '3bb5c9b8 899c47ae bb6fb71e 91386409').
+ replace(/ /g, ''), 'hex'),
+ G: Buffer.from(('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
+};
diff --git a/node_modules/sshpk/lib/certificate.js b/node_modules/sshpk/lib/certificate.js
new file mode 100644
index 0000000..6932357
--- /dev/null
+++ b/node_modules/sshpk/lib/certificate.js
@@ -0,0 +1,410 @@
+// Copyright 2016 Joyent, Inc.
+
+module.exports = Certificate;
+
+var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
+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 Key = require('./key');
+var PrivateKey = require('./private-key');
+var Identity = require('./identity');
+
+var formats = {};
+formats['openssh'] = require('./formats/openssh-cert');
+formats['x509'] = require('./formats/x509');
+formats['pem'] = require('./formats/x509-pem');
+
+var CertificateParseError = errs.CertificateParseError;
+var InvalidAlgorithmError = errs.InvalidAlgorithmError;
+
+function Certificate(opts) {
+ assert.object(opts, 'options');
+ assert.arrayOfObject(opts.subjects, 'options.subjects');
+ utils.assertCompatible(opts.subjects[0], Identity, [1, 0],
+ 'options.subjects');
+ utils.assertCompatible(opts.subjectKey, Key, [1, 0],
+ 'options.subjectKey');
+ utils.assertCompatible(opts.issuer, Identity, [1, 0], 'options.issuer');
+ if (opts.issuerKey !== undefined) {
+ utils.assertCompatible(opts.issuerKey, Key, [1, 0],
+ 'options.issuerKey');
+ }
+ assert.object(opts.signatures, 'options.signatures');
+ assert.buffer(opts.serial, 'options.serial');
+ assert.date(opts.validFrom, 'options.validFrom');
+ assert.date(opts.validUntil, 'optons.validUntil');
+
+ assert.optionalArrayOfString(opts.purposes, 'options.purposes');
+
+ this._hashCache = {};
+
+ this.subjects = opts.subjects;
+ this.issuer = opts.issuer;
+ this.subjectKey = opts.subjectKey;
+ this.issuerKey = opts.issuerKey;
+ this.signatures = opts.signatures;
+ this.serial = opts.serial;
+ this.validFrom = opts.validFrom;
+ this.validUntil = opts.validUntil;
+ this.purposes = opts.purposes;
+}
+
+Certificate.formats = formats;
+
+Certificate.prototype.toBuffer = function (format, options) {
+ if (format === undefined)
+ format = 'x509';
+ assert.string(format, 'format');
+ assert.object(formats[format], 'formats[format]');
+ assert.optionalObject(options, 'options');
+
+ return (formats[format].write(this, options));
+};
+
+Certificate.prototype.toString = function (format, options) {
+ if (format === undefined)
+ format = 'pem';
+ return (this.toBuffer(format, options).toString());
+};
+
+Certificate.prototype.fingerprint = function (algo) {
+ if (algo === undefined)
+ algo = 'sha256';
+ assert.string(algo, 'algorithm');
+ var opts = {
+ type: 'certificate',
+ hash: this.hash(algo),
+ algorithm: algo
+ };
+ return (new Fingerprint(opts));
+};
+
+Certificate.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('x509')).digest();
+ this._hashCache[algo] = hash;
+ return (hash);
+};
+
+Certificate.prototype.isExpired = function (when) {
+ if (when === undefined)
+ when = new Date();
+ return (!((when.getTime() >= this.validFrom.getTime()) &&
+ (when.getTime() < this.validUntil.getTime())));
+};
+
+Certificate.prototype.isSignedBy = function (issuerCert) {
+ utils.assertCompatible(issuerCert, Certificate, [1, 0], 'issuer');
+
+ if (!this.issuer.equals(issuerCert.subjects[0]))
+ return (false);
+ if (this.issuer.purposes && this.issuer.purposes.length > 0 &&
+ this.issuer.purposes.indexOf('ca') === -1) {
+ return (false);
+ }
+
+ return (this.isSignedByKey(issuerCert.subjectKey));
+};
+
+Certificate.prototype.getExtension = function (keyOrOid) {
+ assert.string(keyOrOid, 'keyOrOid');
+ var ext = this.getExtensions().filter(function (maybeExt) {
+ if (maybeExt.format === 'x509')
+ return (maybeExt.oid === keyOrOid);
+ if (maybeExt.format === 'openssh')
+ return (maybeExt.name === keyOrOid);
+ return (false);
+ })[0];
+ return (ext);
+};
+
+Certificate.prototype.getExtensions = function () {
+ var exts = [];
+ var x509 = this.signatures.x509;
+ if (x509 && x509.extras && x509.extras.exts) {
+ x509.extras.exts.forEach(function (ext) {
+ ext.format = 'x509';
+ exts.push(ext);
+ });
+ }
+ var openssh = this.signatures.openssh;
+ if (openssh && openssh.exts) {
+ openssh.exts.forEach(function (ext) {
+ ext.format = 'openssh';
+ exts.push(ext);
+ });
+ }
+ return (exts);
+};
+
+Certificate.prototype.isSignedByKey = function (issuerKey) {
+ utils.assertCompatible(issuerKey, Key, [1, 2], 'issuerKey');
+
+ if (this.issuerKey !== undefined) {
+ return (this.issuerKey.
+ fingerprint('sha512').matches(issuerKey));
+ }
+
+ var fmt = Object.keys(this.signatures)[0];
+ var valid = formats[fmt].verify(this, issuerKey);
+ if (valid)
+ this.issuerKey = issuerKey;
+ return (valid);
+};
+
+Certificate.prototype.signWith = function (key) {
+ utils.assertCompatible(key, PrivateKey, [1, 2], 'key');
+ var fmts = Object.keys(formats);
+ var didOne = false;
+ for (var i = 0; i < fmts.length; ++i) {
+ if (fmts[i] !== 'pem') {
+ var ret = formats[fmts[i]].sign(this, key);
+ if (ret === true)
+ didOne = true;
+ }
+ }
+ if (!didOne) {
+ throw (new Error('Failed to sign the certificate for any ' +
+ 'available certificate formats'));
+ }
+};
+
+Certificate.createSelfSigned = function (subjectOrSubjects, key, options) {
+ var subjects;
+ if (Array.isArray(subjectOrSubjects))
+ subjects = subjectOrSubjects;
+ else
+ subjects = [subjectOrSubjects];
+
+ assert.arrayOfObject(subjects);
+ subjects.forEach(function (subject) {
+ utils.assertCompatible(subject, Identity, [1, 0], 'subject');
+ });
+
+ utils.assertCompatible(key, PrivateKey, [1, 2], 'private key');
+
+ assert.optionalObject(options, 'options');
+ if (options === undefined)
+ options = {};
+ assert.optionalObject(options.validFrom, 'options.validFrom');
+ assert.optionalObject(options.validUntil, 'options.validUntil');
+ var validFrom = options.validFrom;
+ var validUntil = options.validUntil;
+ if (validFrom === undefined)
+ validFrom = new Date();
+ if (validUntil === undefined) {
+ assert.optionalNumber(options.lifetime, 'options.lifetime');
+ var lifetime = options.lifetime;
+ if (lifetime === undefined)
+ lifetime = 10*365*24*3600;
+ validUntil = new Date();
+ validUntil.setTime(validUntil.getTime() + lifetime*1000);
+ }
+ assert.optionalBuffer(options.serial, 'options.serial');
+ var serial = options.serial;
+ if (serial === undefined)
+ serial = Buffer.from('0000000000000001', 'hex');
+
+ var purposes = options.purposes;
+ if (purposes === undefined)
+ purposes = [];
+
+ if (purposes.indexOf('signature') === -1)
+ purposes.push('signature');
+
+ /* Self-signed certs are always CAs. */
+ if (purposes.indexOf('ca') === -1)
+ purposes.push('ca');
+ if (purposes.indexOf('crl') === -1)
+ purposes.push('crl');
+
+ /*
+ * If we weren't explicitly given any other purposes, do the sensible
+ * thing and add some basic ones depending on the subject type.
+ */
+ if (purposes.length <= 3) {
+ var hostSubjects = subjects.filter(function (subject) {
+ return (subject.type === 'host');
+ });
+ var userSubjects = subjects.filter(function (subject) {
+ return (subject.type === 'user');
+ });
+ if (hostSubjects.length > 0) {
+ if (purposes.indexOf('serverAuth') === -1)
+ purposes.push('serverAuth');
+ }
+ if (userSubjects.length > 0) {
+ if (purposes.indexOf('clientAuth') === -1)
+ purposes.push('clientAuth');
+ }
+ if (userSubjects.length > 0 || hostSubjects.length > 0) {
+ if (purposes.indexOf('keyAgreement') === -1)
+ purposes.push('keyAgreement');
+ if (key.type === 'rsa' &&
+ purposes.indexOf('encryption') === -1)
+ purposes.push('encryption');
+ }
+ }
+
+ var cert = new Certificate({
+ subjects: subjects,
+ issuer: subjects[0],
+ subjectKey: key.toPublic(),
+ issuerKey: key.toPublic(),
+ signatures: {},
+ serial: serial,
+ validFrom: validFrom,
+ validUntil: validUntil,
+ purposes: purposes
+ });
+ cert.signWith(key);
+
+ return (cert);
+};
+
+Certificate.create =
+ function (subjectOrSubjects, key, issuer, issuerKey, options) {
+ var subjects;
+ if (Array.isArray(subjectOrSubjects))
+ subjects = subjectOrSubjects;
+ else
+ subjects = [subjectOrSubjects];
+
+ assert.arrayOfObject(subjects);
+ subjects.forEach(function (subject) {
+ utils.assertCompatible(subject, Identity, [1, 0], 'subject');
+ });
+
+ utils.assertCompatible(key, Key, [1, 0], 'key');
+ if (PrivateKey.isPrivateKey(key))
+ key = key.toPublic();
+ utils.assertCompatible(issuer, Identity, [1, 0], 'issuer');
+ utils.assertCompatible(issuerKey, PrivateKey, [1, 2], 'issuer key');
+
+ assert.optionalObject(options, 'options');
+ if (options === undefined)
+ options = {};
+ assert.optionalObject(options.validFrom, 'options.validFrom');
+ assert.optionalObject(options.validUntil, 'options.validUntil');
+ var validFrom = options.validFrom;
+ var validUntil = options.validUntil;
+ if (validFrom === undefined)
+ validFrom = new Date();
+ if (validUntil === undefined) {
+ assert.optionalNumber(options.lifetime, 'options.lifetime');
+ var lifetime = options.lifetime;
+ if (lifetime === undefined)
+ lifetime = 10*365*24*3600;
+ validUntil = new Date();
+ validUntil.setTime(validUntil.getTime() + lifetime*1000);
+ }
+ assert.optionalBuffer(options.serial, 'options.serial');
+ var serial = options.serial;
+ if (serial === undefined)
+ serial = Buffer.from('0000000000000001', 'hex');
+
+ var purposes = options.purposes;
+ if (purposes === undefined)
+ purposes = [];
+
+ if (purposes.indexOf('signature') === -1)
+ purposes.push('signature');
+
+ if (options.ca === true) {
+ if (purposes.indexOf('ca') === -1)
+ purposes.push('ca');
+ if (purposes.indexOf('crl') === -1)
+ purposes.push('crl');
+ }
+
+ var hostSubjects = subjects.filter(function (subject) {
+ return (subject.type === 'host');
+ });
+ var userSubjects = subjects.filter(function (subject) {
+ return (subject.type === 'user');
+ });
+ if (hostSubjects.length > 0) {
+ if (purposes.indexOf('serverAuth') === -1)
+ purposes.push('serverAuth');
+ }
+ if (userSubjects.length > 0) {
+ if (purposes.indexOf('clientAuth') === -1)
+ purposes.push('clientAuth');
+ }
+ if (userSubjects.length > 0 || hostSubjects.length > 0) {
+ if (purposes.indexOf('keyAgreement') === -1)
+ purposes.push('keyAgreement');
+ if (key.type === 'rsa' &&
+ purposes.indexOf('encryption') === -1)
+ purposes.push('encryption');
+ }
+
+ var cert = new Certificate({
+ subjects: subjects,
+ issuer: issuer,
+ subjectKey: key,
+ issuerKey: issuerKey.toPublic(),
+ signatures: {},
+ serial: serial,
+ validFrom: validFrom,
+ validUntil: validUntil,
+ purposes: purposes
+ });
+ cert.signWith(issuerKey);
+
+ return (cert);
+};
+
+Certificate.parse = function (data, format, options) {
+ if (typeof (data) !== 'string')
+ assert.buffer(data, 'data');
+ if (format === undefined)
+ format = 'auto';
+ assert.string(format, 'format');
+ if (typeof (options) === 'string')
+ options = { filename: options };
+ assert.optionalObject(options, 'options');
+ if (options === undefined)
+ options = {};
+ assert.optionalString(options.filename, 'options.filename');
+ if (options.filename === undefined)
+ options.filename = '(unnamed)';
+
+ assert.object(formats[format], 'formats[format]');
+
+ try {
+ var k = formats[format].read(data, options);
+ return (k);
+ } catch (e) {
+ throw (new CertificateParseError(options.filename, format, e));
+ }
+};
+
+Certificate.isCertificate = function (obj, ver) {
+ return (utils.isCompatible(obj, Certificate, ver));
+};
+
+/*
+ * API versions for Certificate:
+ * [1,0] -- initial ver
+ * [1,1] -- openssh format now unpacks extensions
+ */
+Certificate.prototype._sshpkApiVersion = [1, 1];
+
+Certificate._oldVersionDetect = function (obj) {
+ return ([1, 0]);
+};
diff --git a/node_modules/sshpk/lib/dhe.js b/node_modules/sshpk/lib/dhe.js
new file mode 100644
index 0000000..a3c8032
--- /dev/null
+++ b/node_modules/sshpk/lib/dhe.js
@@ -0,0 +1,397 @@
+// Copyright 2017 Joyent, Inc.
+
+module.exports = {
+ DiffieHellman: DiffieHellman,
+ generateECDSA: generateECDSA,
+ generateED25519: generateED25519
+};
+
+var assert = require('assert-plus');
+var crypto = require('crypto');
+var Buffer = require('safer-buffer').Buffer;
+var algs = require('./algs');
+var utils = require('./utils');
+var nacl = require('tweetnacl');
+
+var Key = require('./key');
+var PrivateKey = require('./private-key');
+
+var CRYPTO_HAVE_ECDH = (crypto.createECDH !== undefined);
+
+var ecdh = require('ecc-jsbn');
+var ec = require('ecc-jsbn/lib/ec');
+var jsbn = require('jsbn').BigInteger;
+
+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) {
+ 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 (this._isPriv) {
+ utils.assertCompatible(key, PrivateKey, [1, 5], 'key');
+ this._priv = key.part.k.data;
+ }
+
+ } 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') {
+ var k = pk.part.k;
+ if (!pk.part.k)
+ k = pk.part.r;
+ this._priv = k.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.A.data;
+ while (pub[0] === 0x00 && pub.length > 32)
+ pub = pub.slice(1);
+ var priv = this._priv;
+ assert.strictEqual(pub.length, 32);
+ assert.strictEqual(priv.length, 32);
+
+ var secret = nacl.box.before(new Uint8Array(pub),
+ new Uint8Array(priv));
+
+ return (Buffer.from(secret));
+ }
+
+ 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: Buffer.from(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 = Buffer.from(priv.toByteArray());
+ pub = Buffer.from(this._ecParams.getCurve().
+ encodePointHex(pub), 'hex');
+
+ this._priv = new ECPrivate(this._ecParams, priv);
+
+ parts.push({name: 'curve',
+ data: Buffer.from(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') {
+ var pair = nacl.box.keyPair();
+ priv = Buffer.from(pair.secretKey);
+ pub = Buffer.from(pair.publicKey);
+ priv = Buffer.concat([priv, pub]);
+ assert.strictEqual(priv.length, 64);
+ assert.strictEqual(pub.length, 32);
+
+ parts.push({name: 'A', data: pub});
+ parts.push({name: 'k', data: priv});
+ 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 (Buffer.from(S.getX().toBigInteger().toByteArray()));
+};
+
+function generateED25519() {
+ var pair = nacl.sign.keyPair();
+ var priv = Buffer.from(pair.secretKey);
+ var pub = Buffer.from(pair.publicKey);
+ assert.strictEqual(priv.length, 64);
+ assert.strictEqual(pub.length, 32);
+
+ var parts = [];
+ parts.push({name: 'A', data: pub});
+ parts.push({name: 'k', data: priv.slice(0, 32)});
+ var key = new PrivateKey({
+ type: 'ed25519',
+ parts: parts
+ });
+ return (key);
+}
+
+/* Generates a new ECDSA private key on a given curve. */
+function generateECDSA(curve) {
+ var parts = [];
+ var key;
+
+ if (CRYPTO_HAVE_ECDH) {
+ /*
+ * Node crypto doesn't expose key generation directly, but the
+ * ECDH instances can generate keys. It turns out this just
+ * calls into the OpenSSL generic key generator, and we can
+ * read its output happily without doing an actual DH. So we
+ * use that here.
+ */
+ var osCurve = {
+ 'nistp256': 'prime256v1',
+ 'nistp384': 'secp384r1',
+ 'nistp521': 'secp521r1'
+ }[curve];
+
+ var dh = crypto.createECDH(osCurve);
+ dh.generateKeys();
+
+ parts.push({name: 'curve',
+ data: Buffer.from(curve)});
+ parts.push({name: 'Q', data: dh.getPublicKey()});
+ parts.push({name: 'd', data: dh.getPrivateKey()});
+
+ key = new PrivateKey({
+ type: 'ecdsa',
+ curve: curve,
+ parts: parts
+ });
+ return (key);
+ } else {
+
+ var ecParams = new X9ECParameters(curve);
+
+ /* This algorithm taken from FIPS PUB 186-4 (section B.4.1) */
+ var n = ecParams.getN();
+ /*
+ * The crypto.randomBytes() function can only give us whole
+ * bytes, so taking a nod from X9.62, we round up.
+ */
+ var cByteLen = Math.ceil((n.bitLength() + 64) / 8);
+ var c = new jsbn(crypto.randomBytes(cByteLen));
+
+ var n1 = n.subtract(jsbn.ONE);
+ var priv = c.mod(n1).add(jsbn.ONE);
+ var pub = ecParams.getG().multiply(priv);
+
+ priv = Buffer.from(priv.toByteArray());
+ pub = Buffer.from(ecParams.getCurve().
+ encodePointHex(pub), 'hex');
+
+ parts.push({name: 'curve', data: Buffer.from(curve)});
+ parts.push({name: 'Q', data: pub});
+ parts.push({name: 'd', data: priv});
+
+ key = new PrivateKey({
+ type: 'ecdsa',
+ curve: curve,
+ parts: parts
+ });
+ return (key);
+ }
+}
diff --git a/node_modules/sshpk/lib/ed-compat.js b/node_modules/sshpk/lib/ed-compat.js
new file mode 100644
index 0000000..70732e1
--- /dev/null
+++ b/node_modules/sshpk/lib/ed-compat.js
@@ -0,0 +1,92 @@
+// Copyright 2015 Joyent, Inc.
+
+module.exports = {
+ Verifier: Verifier,
+ Signer: Signer
+};
+
+var nacl = require('tweetnacl');
+var stream = require('stream');
+var util = require('util');
+var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
+var Signature = require('./signature');
+
+function Verifier(key, hashAlgo) {
+ 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 = Buffer.from(chunk, 'binary');
+ this.chunks.push(chunk);
+};
+
+Verifier.prototype.verify = function (signature, fmt) {
+ var sig;
+ if (Signature.isSignature(signature, [2, 0])) {
+ if (signature.type !== 'ed25519')
+ return (false);
+ sig = signature.toBuffer('raw');
+
+ } else if (typeof (signature) === 'string') {
+ sig = Buffer.from(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.A.data)));
+};
+
+function Signer(key, hashAlgo) {
+ 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 = Buffer.from(chunk, 'binary');
+ this.chunks.push(chunk);
+};
+
+Signer.prototype.sign = function () {
+ var sig = nacl.sign.detached(
+ new Uint8Array(Buffer.concat(this.chunks)),
+ new Uint8Array(Buffer.concat([
+ this.key.part.k.data, this.key.part.A.data])));
+ var sigBuf = Buffer.from(sig);
+ var sigObj = Signature.parse(sigBuf, 'ed25519', 'raw');
+ sigObj.hashAlgorithm = 'sha512';
+ return (sigObj);
+};
diff --git a/node_modules/sshpk/lib/errors.js b/node_modules/sshpk/lib/errors.js
new file mode 100644
index 0000000..1cc09ec
--- /dev/null
+++ b/node_modules/sshpk/lib/errors.js
@@ -0,0 +1,84 @@
+// 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);
+
+function CertificateParseError(name, format, innerErr) {
+ if (Error.captureStackTrace)
+ Error.captureStackTrace(this, CertificateParseError);
+ this.name = 'CertificateParseError';
+ this.format = format;
+ this.certName = name;
+ this.innerErr = innerErr;
+ this.message = 'Failed to parse ' + name + ' as a valid ' + format +
+ ' format certificate: ' + innerErr.message;
+}
+util.inherits(CertificateParseError, Error);
+
+function KeyEncryptedError(name, format) {
+ if (Error.captureStackTrace)
+ Error.captureStackTrace(this, KeyEncryptedError);
+ this.name = 'KeyEncryptedError';
+ this.format = format;
+ this.keyName = name;
+ this.message = 'The ' + format + ' format key ' + name + ' is ' +
+ 'encrypted (password-protected), and no passphrase was ' +
+ 'provided in `options`';
+}
+util.inherits(KeyEncryptedError, Error);
+
+module.exports = {
+ FingerprintFormatError: FingerprintFormatError,
+ InvalidAlgorithmError: InvalidAlgorithmError,
+ KeyParseError: KeyParseError,
+ SignatureParseError: SignatureParseError,
+ KeyEncryptedError: KeyEncryptedError,
+ CertificateParseError: CertificateParseError
+};
diff --git a/node_modules/sshpk/lib/fingerprint.js b/node_modules/sshpk/lib/fingerprint.js
new file mode 100644
index 0000000..0004b37
--- /dev/null
+++ b/node_modules/sshpk/lib/fingerprint.js
@@ -0,0 +1,220 @@
+// Copyright 2018 Joyent, Inc.
+
+module.exports = Fingerprint;
+
+var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
+var algs = require('./algs');
+var crypto = require('crypto');
+var errs = require('./errors');
+var Key = require('./key');
+var PrivateKey = require('./private-key');
+var Certificate = require('./certificate');
+var utils = require('./utils');
+
+var FingerprintFormatError = errs.FingerprintFormatError;
+var InvalidAlgorithmError = errs.InvalidAlgorithmError;
+
+function Fingerprint(opts) {
+ assert.object(opts, 'options');
+ assert.string(opts.type, 'options.type');
+ 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;
+ this.type = opts.type;
+ this.hashType = opts.hashType;
+}
+
+Fingerprint.prototype.toString = function (format) {
+ if (format === undefined) {
+ if (this.algorithm === 'md5' || this.hashType === 'spki')
+ format = 'hex';
+ else
+ format = 'base64';
+ }
+ assert.string(format);
+
+ switch (format) {
+ case 'hex':
+ if (this.hashType === 'spki')
+ return (this.hash.toString('hex'));
+ return (addColons(this.hash.toString('hex')));
+ case 'base64':
+ if (this.hashType === 'spki')
+ return (this.hash.toString('base64'));
+ return (sshBase64Format(this.algorithm,
+ this.hash.toString('base64')));
+ default:
+ throw (new FingerprintFormatError(undefined, format));
+ }
+};
+
+Fingerprint.prototype.matches = function (other) {
+ assert.object(other, 'key or certificate');
+ if (this.type === 'key' && this.hashType !== 'ssh') {
+ utils.assertCompatible(other, Key, [1, 7], 'key with spki');
+ if (PrivateKey.isPrivateKey(other)) {
+ utils.assertCompatible(other, PrivateKey, [1, 6],
+ 'privatekey with spki support');
+ }
+ } else if (this.type === 'key') {
+ utils.assertCompatible(other, Key, [1, 0], 'key');
+ } else {
+ utils.assertCompatible(other, Certificate, [1, 0],
+ 'certificate');
+ }
+
+ var theirHash = other.hash(this.algorithm, this.hashType);
+ 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);
+};
+
+/*JSSTYLED*/
+var base64RE = /^[A-Za-z0-9+\/=]+$/;
+/*JSSTYLED*/
+var hexRE = /^[a-fA-F0-9]+$/;
+
+Fingerprint.parse = function (fp, options) {
+ assert.string(fp, 'fingerprint');
+
+ var alg, hash, enAlgs;
+ if (Array.isArray(options)) {
+ enAlgs = options;
+ options = {};
+ }
+ assert.optionalObject(options, 'options');
+ if (options === undefined)
+ options = {};
+ if (options.enAlgs !== undefined)
+ enAlgs = options.enAlgs;
+ if (options.algorithms !== undefined)
+ enAlgs = options.algorithms;
+ assert.optionalArrayOfString(enAlgs, 'algorithms');
+
+ var hashType = 'ssh';
+ if (options.hashType !== undefined)
+ hashType = options.hashType;
+ assert.string(hashType, 'options.hashType');
+
+ var parts = fp.split(':');
+ if (parts.length == 2) {
+ alg = parts[0].toLowerCase();
+ if (!base64RE.test(parts[1]))
+ throw (new FingerprintFormatError(fp));
+ try {
+ hash = Buffer.from(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.map(function (p) {
+ while (p.length < 2)
+ p = '0' + p;
+ if (p.length > 2)
+ throw (new FingerprintFormatError(fp));
+ return (p);
+ });
+ parts = parts.join('');
+ if (!hexRE.test(parts) || parts.length % 2 !== 0)
+ throw (new FingerprintFormatError(fp));
+ try {
+ hash = Buffer.from(parts, 'hex');
+ } catch (e) {
+ throw (new FingerprintFormatError(fp));
+ }
+ } else {
+ if (hexRE.test(fp)) {
+ hash = Buffer.from(fp, 'hex');
+ } else if (base64RE.test(fp)) {
+ hash = Buffer.from(fp, 'base64');
+ } else {
+ throw (new FingerprintFormatError(fp));
+ }
+
+ switch (hash.length) {
+ case 32:
+ alg = 'sha256';
+ break;
+ case 16:
+ alg = 'md5';
+ break;
+ case 20:
+ alg = 'sha1';
+ break;
+ case 64:
+ alg = 'sha512';
+ break;
+ default:
+ throw (new FingerprintFormatError(fp));
+ }
+
+ /* Plain hex/base64: guess it's probably SPKI unless told. */
+ if (options.hashType === undefined)
+ hashType = 'spki';
+ }
+
+ 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,
+ type: options.type || 'key',
+ hashType: hashType
+ }));
+};
+
+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
+ * [1,2] -- hashType and spki support
+ */
+Fingerprint.prototype._sshpkApiVersion = [1, 2];
+
+Fingerprint._oldVersionDetect = function (obj) {
+ assert.func(obj.toString);
+ assert.func(obj.matches);
+ return ([1, 0]);
+};
diff --git a/node_modules/sshpk/lib/formats/auto.js b/node_modules/sshpk/lib/formats/auto.js
new file mode 100644
index 0000000..f32cd96
--- /dev/null
+++ b/node_modules/sshpk/lib/formats/auto.js
@@ -0,0 +1,124 @@
+// Copyright 2018 Joyent, Inc.
+
+module.exports = {
+ read: read,
+ write: write
+};
+
+var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
+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');
+var dnssec = require('./dnssec');
+var putty = require('./putty');
+
+var DNSSEC_PRIVKEY_HEADER_PREFIX = 'Private-key-format: v1';
+
+function read(buf, options) {
+ if (typeof (buf) === 'string') {
+ if (buf.trim().match(/^[-]+[ ]*BEGIN/))
+ return (pem.read(buf, options));
+ if (buf.match(/^\s*ssh-[a-z]/))
+ return (ssh.read(buf, options));
+ if (buf.match(/^\s*ecdsa-/))
+ return (ssh.read(buf, options));
+ if (buf.match(/^putty-user-key-file-2:/i))
+ return (putty.read(buf, options));
+ if (findDNSSECHeader(buf))
+ return (dnssec.read(buf, options));
+ buf = Buffer.from(buf, 'binary');
+ } else {
+ assert.buffer(buf);
+ if (findPEMHeader(buf))
+ return (pem.read(buf, options));
+ if (findSSHHeader(buf))
+ return (ssh.read(buf, options));
+ if (findPuTTYHeader(buf))
+ return (putty.read(buf, options));
+ if (findDNSSECHeader(buf))
+ return (dnssec.read(buf, options));
+ }
+ if (buf.readUInt32BE(0) < buf.length)
+ return (rfc4253.read(buf, options));
+ throw (new Error('Failed to auto-detect format of key'));
+}
+
+function findPuTTYHeader(buf) {
+ var offset = 0;
+ while (offset < buf.length &&
+ (buf[offset] === 32 || buf[offset] === 10 || buf[offset] === 9))
+ ++offset;
+ if (offset + 22 <= buf.length &&
+ buf.slice(offset, offset + 22).toString('ascii').toLowerCase() ===
+ 'putty-user-key-file-2:')
+ return (true);
+ return (false);
+}
+
+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 findDNSSECHeader(buf) {
+ // private case first
+ if (buf.length <= DNSSEC_PRIVKEY_HEADER_PREFIX.length)
+ return (false);
+ var headerCheck = buf.slice(0, DNSSEC_PRIVKEY_HEADER_PREFIX.length);
+ if (headerCheck.toString('ascii') === DNSSEC_PRIVKEY_HEADER_PREFIX)
+ return (true);
+
+ // public-key RFC3110 ?
+ // 'domain.com. IN KEY ...' or 'domain.com. IN DNSKEY ...'
+ // skip any comment-lines
+ if (typeof (buf) !== 'string') {
+ buf = buf.toString('ascii');
+ }
+ var lines = buf.split('\n');
+ var line = 0;
+ /* JSSTYLED */
+ while (lines[line].match(/^\;/))
+ line++;
+ if (lines[line].toString('ascii').match(/\. IN KEY /))
+ return (true);
+ if (lines[line].toString('ascii').match(/\. IN DNSKEY /))
+ return (true);
+ return (false);
+}
+
+function write(key, options) {
+ throw (new Error('"auto" format cannot be used for writing'));
+}
diff --git a/node_modules/sshpk/lib/formats/dnssec.js b/node_modules/sshpk/lib/formats/dnssec.js
new file mode 100644
index 0000000..a74ea9c
--- /dev/null
+++ b/node_modules/sshpk/lib/formats/dnssec.js
@@ -0,0 +1,287 @@
+// Copyright 2017 Joyent, Inc.
+
+module.exports = {
+ read: read,
+ write: write
+};
+
+var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+var utils = require('../utils');
+var SSHBuffer = require('../ssh-buffer');
+var Dhe = require('../dhe');
+
+var supportedAlgos = {
+ 'rsa-sha1' : 5,
+ 'rsa-sha256' : 8,
+ 'rsa-sha512' : 10,
+ 'ecdsa-p256-sha256' : 13,
+ 'ecdsa-p384-sha384' : 14
+ /*
+ * ed25519 is hypothetically supported with id 15
+ * but the common tools available don't appear to be
+ * capable of generating/using ed25519 keys
+ */
+};
+
+var supportedAlgosById = {};
+Object.keys(supportedAlgos).forEach(function (k) {
+ supportedAlgosById[supportedAlgos[k]] = k.toUpperCase();
+});
+
+function read(buf, options) {
+ if (typeof (buf) !== 'string') {
+ assert.buffer(buf, 'buf');
+ buf = buf.toString('ascii');
+ }
+ var lines = buf.split('\n');
+ if (lines[0].match(/^Private-key-format\: v1/)) {
+ var algElems = lines[1].split(' ');
+ var algoNum = parseInt(algElems[1], 10);
+ var algoName = algElems[2];
+ if (!supportedAlgosById[algoNum])
+ throw (new Error('Unsupported algorithm: ' + algoName));
+ return (readDNSSECPrivateKey(algoNum, lines.slice(2)));
+ }
+
+ // skip any comment-lines
+ var line = 0;
+ /* JSSTYLED */
+ while (lines[line].match(/^\;/))
+ line++;
+ // we should now have *one single* line left with our KEY on it.
+ if ((lines[line].match(/\. IN KEY /) ||
+ lines[line].match(/\. IN DNSKEY /)) && lines[line+1].length === 0) {
+ return (readRFC3110(lines[line]));
+ }
+ throw (new Error('Cannot parse dnssec key'));
+}
+
+function readRFC3110(keyString) {
+ var elems = keyString.split(' ');
+ //unused var flags = parseInt(elems[3], 10);
+ //unused var protocol = parseInt(elems[4], 10);
+ var algorithm = parseInt(elems[5], 10);
+ if (!supportedAlgosById[algorithm])
+ throw (new Error('Unsupported algorithm: ' + algorithm));
+ var base64key = elems.slice(6, elems.length).join();
+ var keyBuffer = Buffer.from(base64key, 'base64');
+ if (supportedAlgosById[algorithm].match(/^RSA-/)) {
+ // join the rest of the body into a single base64-blob
+ var publicExponentLen = keyBuffer.readUInt8(0);
+ if (publicExponentLen != 3 && publicExponentLen != 1)
+ throw (new Error('Cannot parse dnssec key: ' +
+ 'unsupported exponent length'));
+
+ var publicExponent = keyBuffer.slice(1, publicExponentLen+1);
+ publicExponent = utils.mpNormalize(publicExponent);
+ var modulus = keyBuffer.slice(1+publicExponentLen);
+ modulus = utils.mpNormalize(modulus);
+ // now, make the key
+ var rsaKey = {
+ type: 'rsa',
+ parts: []
+ };
+ rsaKey.parts.push({ name: 'e', data: publicExponent});
+ rsaKey.parts.push({ name: 'n', data: modulus});
+ return (new Key(rsaKey));
+ }
+ if (supportedAlgosById[algorithm] === 'ECDSA-P384-SHA384' ||
+ supportedAlgosById[algorithm] === 'ECDSA-P256-SHA256') {
+ var curve = 'nistp384';
+ var size = 384;
+ if (supportedAlgosById[algorithm].match(/^ECDSA-P256-SHA256/)) {
+ curve = 'nistp256';
+ size = 256;
+ }
+
+ var ecdsaKey = {
+ type: 'ecdsa',
+ curve: curve,
+ size: size,
+ parts: [
+ {name: 'curve', data: Buffer.from(curve) },
+ {name: 'Q', data: utils.ecNormalize(keyBuffer) }
+ ]
+ };
+ return (new Key(ecdsaKey));
+ }
+ throw (new Error('Unsupported algorithm: ' +
+ supportedAlgosById[algorithm]));
+}
+
+function elementToBuf(e) {
+ return (Buffer.from(e.split(' ')[1], 'base64'));
+}
+
+function readDNSSECRSAPrivateKey(elements) {
+ var rsaParams = {};
+ elements.forEach(function (element) {
+ if (element.split(' ')[0] === 'Modulus:')
+ rsaParams['n'] = elementToBuf(element);
+ else if (element.split(' ')[0] === 'PublicExponent:')
+ rsaParams['e'] = elementToBuf(element);
+ else if (element.split(' ')[0] === 'PrivateExponent:')
+ rsaParams['d'] = elementToBuf(element);
+ else if (element.split(' ')[0] === 'Prime1:')
+ rsaParams['p'] = elementToBuf(element);
+ else if (element.split(' ')[0] === 'Prime2:')
+ rsaParams['q'] = elementToBuf(element);
+ else if (element.split(' ')[0] === 'Exponent1:')
+ rsaParams['dmodp'] = elementToBuf(element);
+ else if (element.split(' ')[0] === 'Exponent2:')
+ rsaParams['dmodq'] = elementToBuf(element);
+ else if (element.split(' ')[0] === 'Coefficient:')
+ rsaParams['iqmp'] = elementToBuf(element);
+ });
+ // now, make the key
+ var key = {
+ type: 'rsa',
+ parts: [
+ { name: 'e', data: utils.mpNormalize(rsaParams['e'])},
+ { name: 'n', data: utils.mpNormalize(rsaParams['n'])},
+ { name: 'd', data: utils.mpNormalize(rsaParams['d'])},
+ { name: 'p', data: utils.mpNormalize(rsaParams['p'])},
+ { name: 'q', data: utils.mpNormalize(rsaParams['q'])},
+ { name: 'dmodp',
+ data: utils.mpNormalize(rsaParams['dmodp'])},
+ { name: 'dmodq',
+ data: utils.mpNormalize(rsaParams['dmodq'])},
+ { name: 'iqmp',
+ data: utils.mpNormalize(rsaParams['iqmp'])}
+ ]
+ };
+ return (new PrivateKey(key));
+}
+
+function readDNSSECPrivateKey(alg, elements) {
+ if (supportedAlgosById[alg].match(/^RSA-/)) {
+ return (readDNSSECRSAPrivateKey(elements));
+ }
+ if (supportedAlgosById[alg] === 'ECDSA-P384-SHA384' ||
+ supportedAlgosById[alg] === 'ECDSA-P256-SHA256') {
+ var d = Buffer.from(elements[0].split(' ')[1], 'base64');
+ var curve = 'nistp384';
+ var size = 384;
+ if (supportedAlgosById[alg] === 'ECDSA-P256-SHA256') {
+ curve = 'nistp256';
+ size = 256;
+ }
+ // DNSSEC generates the public-key on the fly (go calculate it)
+ var publicKey = utils.publicFromPrivateECDSA(curve, d);
+ var Q = publicKey.part['Q'].data;
+ var ecdsaKey = {
+ type: 'ecdsa',
+ curve: curve,
+ size: size,
+ parts: [
+ {name: 'curve', data: Buffer.from(curve) },
+ {name: 'd', data: d },
+ {name: 'Q', data: Q }
+ ]
+ };
+ return (new PrivateKey(ecdsaKey));
+ }
+ throw (new Error('Unsupported algorithm: ' + supportedAlgosById[alg]));
+}
+
+function dnssecTimestamp(date) {
+ var year = date.getFullYear() + ''; //stringify
+ var month = (date.getMonth() + 1);
+ var timestampStr = year + month + date.getUTCDate();
+ timestampStr += '' + date.getUTCHours() + date.getUTCMinutes();
+ timestampStr += date.getUTCSeconds();
+ return (timestampStr);
+}
+
+function rsaAlgFromOptions(opts) {
+ if (!opts || !opts.hashAlgo || opts.hashAlgo === 'sha1')
+ return ('5 (RSASHA1)');
+ else if (opts.hashAlgo === 'sha256')
+ return ('8 (RSASHA256)');
+ else if (opts.hashAlgo === 'sha512')
+ return ('10 (RSASHA512)');
+ else
+ throw (new Error('Unknown or unsupported hash: ' +
+ opts.hashAlgo));
+}
+
+function writeRSA(key, options) {
+ // if we're missing parts, add them.
+ if (!key.part.dmodp || !key.part.dmodq) {
+ utils.addRSAMissing(key);
+ }
+
+ var out = '';
+ out += 'Private-key-format: v1.3\n';
+ out += 'Algorithm: ' + rsaAlgFromOptions(options) + '\n';
+ var n = utils.mpDenormalize(key.part['n'].data);
+ out += 'Modulus: ' + n.toString('base64') + '\n';
+ var e = utils.mpDenormalize(key.part['e'].data);
+ out += 'PublicExponent: ' + e.toString('base64') + '\n';
+ var d = utils.mpDenormalize(key.part['d'].data);
+ out += 'PrivateExponent: ' + d.toString('base64') + '\n';
+ var p = utils.mpDenormalize(key.part['p'].data);
+ out += 'Prime1: ' + p.toString('base64') + '\n';
+ var q = utils.mpDenormalize(key.part['q'].data);
+ out += 'Prime2: ' + q.toString('base64') + '\n';
+ var dmodp = utils.mpDenormalize(key.part['dmodp'].data);
+ out += 'Exponent1: ' + dmodp.toString('base64') + '\n';
+ var dmodq = utils.mpDenormalize(key.part['dmodq'].data);
+ out += 'Exponent2: ' + dmodq.toString('base64') + '\n';
+ var iqmp = utils.mpDenormalize(key.part['iqmp'].data);
+ out += 'Coefficient: ' + iqmp.toString('base64') + '\n';
+ // Assume that we're valid as-of now
+ var timestamp = new Date();
+ out += 'Created: ' + dnssecTimestamp(timestamp) + '\n';
+ out += 'Publish: ' + dnssecTimestamp(timestamp) + '\n';
+ out += 'Activate: ' + dnssecTimestamp(timestamp) + '\n';
+ return (Buffer.from(out, 'ascii'));
+}
+
+function writeECDSA(key, options) {
+ var out = '';
+ out += 'Private-key-format: v1.3\n';
+
+ if (key.curve === 'nistp256') {
+ out += 'Algorithm: 13 (ECDSAP256SHA256)\n';
+ } else if (key.curve === 'nistp384') {
+ out += 'Algorithm: 14 (ECDSAP384SHA384)\n';
+ } else {
+ throw (new Error('Unsupported curve'));
+ }
+ var base64Key = key.part['d'].data.toString('base64');
+ out += 'PrivateKey: ' + base64Key + '\n';
+
+ // Assume that we're valid as-of now
+ var timestamp = new Date();
+ out += 'Created: ' + dnssecTimestamp(timestamp) + '\n';
+ out += 'Publish: ' + dnssecTimestamp(timestamp) + '\n';
+ out += 'Activate: ' + dnssecTimestamp(timestamp) + '\n';
+
+ return (Buffer.from(out, 'ascii'));
+}
+
+function write(key, options) {
+ if (PrivateKey.isPrivateKey(key)) {
+ if (key.type === 'rsa') {
+ return (writeRSA(key, options));
+ } else if (key.type === 'ecdsa') {
+ return (writeECDSA(key, options));
+ } else {
+ throw (new Error('Unsupported algorithm: ' + key.type));
+ }
+ } else if (Key.isKey(key)) {
+ /*
+ * RFC3110 requires a keyname, and a keytype, which we
+ * don't really have a mechanism for specifying such
+ * additional metadata.
+ */
+ throw (new Error('Format "dnssec" only supports ' +
+ 'writing private keys'));
+ } else {
+ throw (new Error('key is not a Key or PrivateKey'));
+ }
+}
diff --git a/node_modules/sshpk/lib/formats/openssh-cert.js b/node_modules/sshpk/lib/formats/openssh-cert.js
new file mode 100644
index 0000000..766f3d3
--- /dev/null
+++ b/node_modules/sshpk/lib/formats/openssh-cert.js
@@ -0,0 +1,352 @@
+// Copyright 2017 Joyent, Inc.
+
+module.exports = {
+ read: read,
+ verify: verify,
+ sign: sign,
+ signAsync: signAsync,
+ write: write,
+
+ /* Internal private API */
+ fromBuffer: fromBuffer,
+ toBuffer: toBuffer
+};
+
+var assert = require('assert-plus');
+var SSHBuffer = require('../ssh-buffer');
+var crypto = require('crypto');
+var Buffer = require('safer-buffer').Buffer;
+var algs = require('../algs');
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+var Identity = require('../identity');
+var rfc4253 = require('./rfc4253');
+var Signature = require('../signature');
+var utils = require('../utils');
+var Certificate = require('../certificate');
+
+function verify(cert, key) {
+ /*
+ * We always give an issuerKey, so if our verify() is being called then
+ * there was no signature. Return false.
+ */
+ return (false);
+}
+
+var TYPES = {
+ 'user': 1,
+ 'host': 2
+};
+Object.keys(TYPES).forEach(function (k) { TYPES[TYPES[k]] = k; });
+
+var ECDSA_ALGO = /^ecdsa-sha2-([^@-]+)-cert-v01@openssh.com$/;
+
+function read(buf, options) {
+ if (Buffer.isBuffer(buf))
+ buf = buf.toString('ascii');
+ var parts = buf.trim().split(/[ \t\n]+/g);
+ if (parts.length < 2 || parts.length > 3)
+ throw (new Error('Not a valid SSH certificate line'));
+
+ var algo = parts[0];
+ var data = parts[1];
+
+ data = Buffer.from(data, 'base64');
+ return (fromBuffer(data, algo));
+}
+
+function fromBuffer(data, algo, partial) {
+ var sshbuf = new SSHBuffer({ buffer: data });
+ var innerAlgo = sshbuf.readString();
+ if (algo !== undefined && innerAlgo !== algo)
+ throw (new Error('SSH certificate algorithm mismatch'));
+ if (algo === undefined)
+ algo = innerAlgo;
+
+ var cert = {};
+ cert.signatures = {};
+ cert.signatures.openssh = {};
+
+ cert.signatures.openssh.nonce = sshbuf.readBuffer();
+
+ var key = {};
+ var parts = (key.parts = []);
+ key.type = getAlg(algo);
+
+ var partCount = algs.info[key.type].parts.length;
+ while (parts.length < partCount)
+ parts.push(sshbuf.readPart());
+ assert.ok(parts.length >= 1, 'key must have at least one part');
+
+ var algInfo = algs.info[key.type];
+ if (key.type === 'ecdsa') {
+ var res = ECDSA_ALGO.exec(algo);
+ assert.ok(res !== null);
+ assert.strictEqual(res[1], parts[0].data.toString());
+ }
+
+ for (var i = 0; i < algInfo.parts.length; ++i) {
+ parts[i].name = algInfo.parts[i];
+ if (parts[i].name !== 'curve' &&
+ algInfo.normalize !== false) {
+ var p = parts[i];
+ p.data = utils.mpNormalize(p.data);
+ }
+ }
+
+ cert.subjectKey = new Key(key);
+
+ cert.serial = sshbuf.readInt64();
+
+ var type = TYPES[sshbuf.readInt()];
+ assert.string(type, 'valid cert type');
+
+ cert.signatures.openssh.keyId = sshbuf.readString();
+
+ var principals = [];
+ var pbuf = sshbuf.readBuffer();
+ var psshbuf = new SSHBuffer({ buffer: pbuf });
+ while (!psshbuf.atEnd())
+ principals.push(psshbuf.readString());
+ if (principals.length === 0)
+ principals = ['*'];
+
+ cert.subjects = principals.map(function (pr) {
+ if (type === 'user')
+ return (Identity.forUser(pr));
+ else if (type === 'host')
+ return (Identity.forHost(pr));
+ throw (new Error('Unknown identity type ' + type));
+ });
+
+ cert.validFrom = int64ToDate(sshbuf.readInt64());
+ cert.validUntil = int64ToDate(sshbuf.readInt64());
+
+ var exts = [];
+ var extbuf = new SSHBuffer({ buffer: sshbuf.readBuffer() });
+ var ext;
+ while (!extbuf.atEnd()) {
+ ext = { critical: true };
+ ext.name = extbuf.readString();
+ ext.data = extbuf.readBuffer();
+ exts.push(ext);
+ }
+ extbuf = new SSHBuffer({ buffer: sshbuf.readBuffer() });
+ while (!extbuf.atEnd()) {
+ ext = { critical: false };
+ ext.name = extbuf.readString();
+ ext.data = extbuf.readBuffer();
+ exts.push(ext);
+ }
+ cert.signatures.openssh.exts = exts;
+
+ /* reserved */
+ sshbuf.readBuffer();
+
+ var signingKeyBuf = sshbuf.readBuffer();
+ cert.issuerKey = rfc4253.read(signingKeyBuf);
+
+ /*
+ * OpenSSH certs don't give the identity of the issuer, just their
+ * public key. So, we use an Identity that matches anything. The
+ * isSignedBy() function will later tell you if the key matches.
+ */
+ cert.issuer = Identity.forHost('**');
+
+ var sigBuf = sshbuf.readBuffer();
+ cert.signatures.openssh.signature =
+ Signature.parse(sigBuf, cert.issuerKey.type, 'ssh');
+
+ if (partial !== undefined) {
+ partial.remainder = sshbuf.remainder();
+ partial.consumed = sshbuf._offset;
+ }
+
+ return (new Certificate(cert));
+}
+
+function int64ToDate(buf) {
+ var i = buf.readUInt32BE(0) * 4294967296;
+ i += buf.readUInt32BE(4);
+ var d = new Date();
+ d.setTime(i * 1000);
+ d.sourceInt64 = buf;
+ return (d);
+}
+
+function dateToInt64(date) {
+ if (date.sourceInt64 !== undefined)
+ return (date.sourceInt64);
+ var i = Math.round(date.getTime() / 1000);
+ var upper = Math.floor(i / 4294967296);
+ var lower = Math.floor(i % 4294967296);
+ var buf = Buffer.alloc(8);
+ buf.writeUInt32BE(upper, 0);
+ buf.writeUInt32BE(lower, 4);
+ return (buf);
+}
+
+function sign(cert, key) {
+ if (cert.signatures.openssh === undefined)
+ cert.signatures.openssh = {};
+ try {
+ var blob = toBuffer(cert, true);
+ } catch (e) {
+ delete (cert.signatures.openssh);
+ return (false);
+ }
+ var sig = cert.signatures.openssh;
+ var hashAlgo = undefined;
+ if (key.type === 'rsa' || key.type === 'dsa')
+ hashAlgo = 'sha1';
+ var signer = key.createSign(hashAlgo);
+ signer.write(blob);
+ sig.signature = signer.sign();
+ return (true);
+}
+
+function signAsync(cert, signer, done) {
+ if (cert.signatures.openssh === undefined)
+ cert.signatures.openssh = {};
+ try {
+ var blob = toBuffer(cert, true);
+ } catch (e) {
+ delete (cert.signatures.openssh);
+ done(e);
+ return;
+ }
+ var sig = cert.signatures.openssh;
+
+ signer(blob, function (err, signature) {
+ if (err) {
+ done(err);
+ return;
+ }
+ try {
+ /*
+ * This will throw if the signature isn't of a
+ * type/algo that can be used for SSH.
+ */
+ signature.toBuffer('ssh');
+ } catch (e) {
+ done(e);
+ return;
+ }
+ sig.signature = signature;
+ done();
+ });
+}
+
+function write(cert, options) {
+ if (options === undefined)
+ options = {};
+
+ var blob = toBuffer(cert);
+ var out = getCertType(cert.subjectKey) + ' ' + blob.toString('base64');
+ if (options.comment)
+ out = out + ' ' + options.comment;
+ return (out);
+}
+
+
+function toBuffer(cert, noSig) {
+ assert.object(cert.signatures.openssh, 'signature for openssh format');
+ var sig = cert.signatures.openssh;
+
+ if (sig.nonce === undefined)
+ sig.nonce = crypto.randomBytes(16);
+ var buf = new SSHBuffer({});
+ buf.writeString(getCertType(cert.subjectKey));
+ buf.writeBuffer(sig.nonce);
+
+ var key = cert.subjectKey;
+ var algInfo = algs.info[key.type];
+ algInfo.parts.forEach(function (part) {
+ buf.writePart(key.part[part]);
+ });
+
+ buf.writeInt64(cert.serial);
+
+ var type = cert.subjects[0].type;
+ assert.notStrictEqual(type, 'unknown');
+ cert.subjects.forEach(function (id) {
+ assert.strictEqual(id.type, type);
+ });
+ type = TYPES[type];
+ buf.writeInt(type);
+
+ if (sig.keyId === undefined) {
+ sig.keyId = cert.subjects[0].type + '_' +
+ (cert.subjects[0].uid || cert.subjects[0].hostname);
+ }
+ buf.writeString(sig.keyId);
+
+ var sub = new SSHBuffer({});
+ cert.subjects.forEach(function (id) {
+ if (type === TYPES.host)
+ sub.writeString(id.hostname);
+ else if (type === TYPES.user)
+ sub.writeString(id.uid);
+ });
+ buf.writeBuffer(sub.toBuffer());
+
+ buf.writeInt64(dateToInt64(cert.validFrom));
+ buf.writeInt64(dateToInt64(cert.validUntil));
+
+ var exts = sig.exts;
+ if (exts === undefined)
+ exts = [];
+
+ var extbuf = new SSHBuffer({});
+ exts.forEach(function (ext) {
+ if (ext.critical !== true)
+ return;
+ extbuf.writeString(ext.name);
+ extbuf.writeBuffer(ext.data);
+ });
+ buf.writeBuffer(extbuf.toBuffer());
+
+ extbuf = new SSHBuffer({});
+ exts.forEach(function (ext) {
+ if (ext.critical === true)
+ return;
+ extbuf.writeString(ext.name);
+ extbuf.writeBuffer(ext.data);
+ });
+ buf.writeBuffer(extbuf.toBuffer());
+
+ /* reserved */
+ buf.writeBuffer(Buffer.alloc(0));
+
+ sub = rfc4253.write(cert.issuerKey);
+ buf.writeBuffer(sub);
+
+ if (!noSig)
+ buf.writeBuffer(sig.signature.toBuffer('ssh'));
+
+ return (buf.toBuffer());
+}
+
+function getAlg(certType) {
+ if (certType === 'ssh-rsa-cert-v01@openssh.com')
+ return ('rsa');
+ if (certType === 'ssh-dss-cert-v01@openssh.com')
+ return ('dsa');
+ if (certType.match(ECDSA_ALGO))
+ return ('ecdsa');
+ if (certType === 'ssh-ed25519-cert-v01@openssh.com')
+ return ('ed25519');
+ throw (new Error('Unsupported cert type ' + certType));
+}
+
+function getCertType(key) {
+ if (key.type === 'rsa')
+ return ('ssh-rsa-cert-v01@openssh.com');
+ if (key.type === 'dsa')
+ return ('ssh-dss-cert-v01@openssh.com');
+ if (key.type === 'ecdsa')
+ return ('ecdsa-sha2-' + key.curve + '-cert-v01@openssh.com');
+ if (key.type === 'ed25519')
+ return ('ssh-ed25519-cert-v01@openssh.com');
+ throw (new Error('Unsupported key type ' + key.type));
+}
diff --git a/node_modules/sshpk/lib/formats/pem.js b/node_modules/sshpk/lib/formats/pem.js
new file mode 100644
index 0000000..bbe78fc
--- /dev/null
+++ b/node_modules/sshpk/lib/formats/pem.js
@@ -0,0 +1,290 @@
+// Copyright 2018 Joyent, Inc.
+
+module.exports = {
+ read: read,
+ write: write
+};
+
+var assert = require('assert-plus');
+var asn1 = require('asn1');
+var crypto = require('crypto');
+var Buffer = require('safer-buffer').Buffer;
+var algs = require('../algs');
+var utils = require('../utils');
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+
+var pkcs1 = require('./pkcs1');
+var pkcs8 = require('./pkcs8');
+var sshpriv = require('./ssh-private');
+var rfc4253 = require('./rfc4253');
+
+var errors = require('../errors');
+
+var OID_PBES2 = '1.2.840.113549.1.5.13';
+var OID_PBKDF2 = '1.2.840.113549.1.5.12';
+
+var OID_TO_CIPHER = {
+ '1.2.840.113549.3.7': '3des-cbc',
+ '2.16.840.1.101.3.4.1.2': 'aes128-cbc',
+ '2.16.840.1.101.3.4.1.42': 'aes256-cbc'
+};
+var CIPHER_TO_OID = {};
+Object.keys(OID_TO_CIPHER).forEach(function (k) {
+ CIPHER_TO_OID[OID_TO_CIPHER[k]] = k;
+});
+
+var OID_TO_HASH = {
+ '1.2.840.113549.2.7': 'sha1',
+ '1.2.840.113549.2.9': 'sha256',
+ '1.2.840.113549.2.11': 'sha512'
+};
+var HASH_TO_OID = {};
+Object.keys(OID_TO_HASH).forEach(function (k) {
+ HASH_TO_OID[OID_TO_HASH[k]] = k;
+});
+
+/*
+ * For reading we support both PKCS#1 and PKCS#8. If we find a private key,
+ * we just take the public component of it and use that.
+ */
+function read(buf, options, forceType) {
+ var input = buf;
+ if (typeof (buf) !== 'string') {
+ assert.buffer(buf, 'buf');
+ buf = buf.toString('ascii');
+ }
+
+ var lines = buf.trim().split(/[\r\n]+/g);
+
+ var m;
+ var si = -1;
+ while (!m && si < lines.length) {
+ m = lines[++si].match(/*JSSTYLED*/
+ /[-]+[ ]*BEGIN ([A-Z0-9][A-Za-z0-9]+ )?(PUBLIC|PRIVATE) KEY[ ]*[-]+/);
+ }
+ assert.ok(m, 'invalid PEM header');
+
+ var m2;
+ var ei = lines.length;
+ while (!m2 && ei > 0) {
+ m2 = lines[--ei].match(/*JSSTYLED*/
+ /[-]+[ ]*END ([A-Z0-9][A-Za-z0-9]+ )?(PUBLIC|PRIVATE) KEY[ ]*[-]+/);
+ }
+ assert.ok(m2, 'invalid PEM footer');
+
+ /* Begin and end banners must match key type */
+ 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();
+ }
+
+ lines = lines.slice(si, ei + 1);
+
+ var headers = {};
+ while (true) {
+ lines = lines.slice(1);
+ m = lines[0].match(/*JSSTYLED*/
+ /^([A-Za-z0-9-]+): (.+)$/);
+ if (!m)
+ break;
+ headers[m[1].toLowerCase()] = m[2];
+ }
+
+ /* Chop off the first and last lines */
+ lines = lines.slice(0, -1).join('');
+ buf = Buffer.from(lines, 'base64');
+
+ var cipher, key, iv;
+ if (headers['proc-type']) {
+ var parts = headers['proc-type'].split(',');
+ if (parts[0] === '4' && parts[1] === 'ENCRYPTED') {
+ if (typeof (options.passphrase) === 'string') {
+ options.passphrase = Buffer.from(
+ options.passphrase, 'utf-8');
+ }
+ if (!Buffer.isBuffer(options.passphrase)) {
+ throw (new errors.KeyEncryptedError(
+ options.filename, 'PEM'));
+ } else {
+ parts = headers['dek-info'].split(',');
+ assert.ok(parts.length === 2);
+ cipher = parts[0].toLowerCase();
+ iv = Buffer.from(parts[1], 'hex');
+ key = utils.opensslKeyDeriv(cipher, iv,
+ options.passphrase, 1).key;
+ }
+ }
+ }
+
+ if (alg && alg.toLowerCase() === 'encrypted') {
+ var eder = new asn1.BerReader(buf);
+ var pbesEnd;
+ eder.readSequence();
+
+ eder.readSequence();
+ pbesEnd = eder.offset + eder.length;
+
+ var method = eder.readOID();
+ if (method !== OID_PBES2) {
+ throw (new Error('Unsupported PEM/PKCS8 encryption ' +
+ 'scheme: ' + method));
+ }
+
+ eder.readSequence(); /* PBES2-params */
+
+ eder.readSequence(); /* keyDerivationFunc */
+ var kdfEnd = eder.offset + eder.length;
+ var kdfOid = eder.readOID();
+ if (kdfOid !== OID_PBKDF2)
+ throw (new Error('Unsupported PBES2 KDF: ' + kdfOid));
+ eder.readSequence();
+ var salt = eder.readString(asn1.Ber.OctetString, true);
+ var iterations = eder.readInt();
+ var hashAlg = 'sha1';
+ if (eder.offset < kdfEnd) {
+ eder.readSequence();
+ var hashAlgOid = eder.readOID();
+ hashAlg = OID_TO_HASH[hashAlgOid];
+ if (hashAlg === undefined) {
+ throw (new Error('Unsupported PBKDF2 hash: ' +
+ hashAlgOid));
+ }
+ }
+ eder._offset = kdfEnd;
+
+ eder.readSequence(); /* encryptionScheme */
+ var cipherOid = eder.readOID();
+ cipher = OID_TO_CIPHER[cipherOid];
+ if (cipher === undefined) {
+ throw (new Error('Unsupported PBES2 cipher: ' +
+ cipherOid));
+ }
+ iv = eder.readString(asn1.Ber.OctetString, true);
+
+ eder._offset = pbesEnd;
+ buf = eder.readString(asn1.Ber.OctetString, true);
+
+ if (typeof (options.passphrase) === 'string') {
+ options.passphrase = Buffer.from(
+ options.passphrase, 'utf-8');
+ }
+ if (!Buffer.isBuffer(options.passphrase)) {
+ throw (new errors.KeyEncryptedError(
+ options.filename, 'PEM'));
+ }
+
+ var cinfo = utils.opensshCipherInfo(cipher);
+
+ cipher = cinfo.opensslName;
+ key = utils.pbkdf2(hashAlg, salt, iterations, cinfo.keySize,
+ options.passphrase);
+ alg = undefined;
+ }
+
+ if (cipher && key && iv) {
+ var cipherStream = crypto.createDecipheriv(cipher, key, iv);
+ var chunk, chunks = [];
+ cipherStream.once('error', function (e) {
+ if (e.toString().indexOf('bad decrypt') !== -1) {
+ throw (new Error('Incorrect passphrase ' +
+ 'supplied, could not decrypt key'));
+ }
+ throw (e);
+ });
+ cipherStream.write(buf);
+ cipherStream.end();
+ while ((chunk = cipherStream.read()) !== null)
+ chunks.push(chunk);
+ buf = Buffer.concat(chunks);
+ }
+
+ /* The new OpenSSH internal format abuses PEM headers */
+ if (alg && alg.toLowerCase() === 'openssh')
+ return (sshpriv.readSSHPrivate(type, buf, options));
+ if (alg && alg.toLowerCase() === 'ssh2')
+ return (rfc4253.readType(type, buf, options));
+
+ var der = new asn1.BerReader(buf);
+ der.originalInput = input;
+
+ /*
+ * All of the PEM file types start with a sequence tag, so chop it
+ * off here
+ */
+ der.readSequence();
+
+ /* PKCS#1 type keys name an algorithm in the banner explicitly */
+ if (alg) {
+ if (forceType)
+ assert.strictEqual(forceType, 'pkcs1');
+ return (pkcs1.readPkcs1(alg, type, der));
+ } else {
+ if (forceType)
+ assert.strictEqual(forceType, 'pkcs8');
+ return (pkcs8.readPkcs8(alg, type, der));
+ }
+}
+
+function write(key, options, type) {
+ assert.object(key);
+
+ var alg = {
+ 'ecdsa': 'EC',
+ 'rsa': 'RSA',
+ 'dsa': 'DSA',
+ 'ed25519': 'EdDSA'
+ }[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 = Buffer.alloc(len);
+ var o = 0;
+ o += buf.write('-----BEGIN ' + header + '-----\n', o);
+ for (var i = 0; i < tmp.length; ) {
+ var limit = i + 64;
+ if (limit > tmp.length)
+ limit = tmp.length;
+ o += buf.write(tmp.slice(i, limit), o);
+ buf[o++] = 10;
+ i = limit;
+ }
+ o += buf.write('-----END ' + header + '-----\n', o);
+
+ return (buf.slice(0, o));
+}
diff --git a/node_modules/sshpk/lib/formats/pkcs1.js b/node_modules/sshpk/lib/formats/pkcs1.js
new file mode 100644
index 0000000..bc48550
--- /dev/null
+++ b/node_modules/sshpk/lib/formats/pkcs1.js
@@ -0,0 +1,373 @@
+// Copyright 2015 Joyent, Inc.
+
+module.exports = {
+ read: read,
+ readPkcs1: readPkcs1,
+ write: write,
+ writePkcs1: writePkcs1
+};
+
+var assert = require('assert-plus');
+var asn1 = require('asn1');
+var Buffer = require('safer-buffer').Buffer;
+var algs = require('../algs');
+var utils = require('../utils');
+
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+var pem = require('./pem');
+
+var pkcs8 = require('./pkcs8');
+var readECDSACurve = pkcs8.readECDSACurve;
+
+function read(buf, options) {
+ return (pem.read(buf, options, 'pkcs1'));
+}
+
+function write(key, options) {
+ return (pem.write(key, options, 'pkcs1'));
+}
+
+/* Helper to read in a single mpint */
+function readMPInt(der, nm) {
+ assert.strictEqual(der.peek(), asn1.Ber.Integer,
+ nm + ' is not an Integer');
+ return (utils.mpNormalize(der.readString(asn1.Ber.Integer, true)));
+}
+
+function readPkcs1(alg, type, der) {
+ switch (alg) {
+ case 'RSA':
+ if (type === 'public')
+ return (readPkcs1RSAPublic(der));
+ else if (type === 'private')
+ return (readPkcs1RSAPrivate(der));
+ throw (new Error('Unknown key type: ' + type));
+ case 'DSA':
+ if (type === 'public')
+ return (readPkcs1DSAPublic(der));
+ else if (type === 'private')
+ return (readPkcs1DSAPrivate(der));
+ throw (new Error('Unknown key type: ' + type));
+ case 'EC':
+ case 'ECDSA':
+ if (type === 'private')
+ return (readPkcs1ECDSAPrivate(der));
+ else if (type === 'public')
+ return (readPkcs1ECDSAPublic(der));
+ throw (new Error('Unknown key type: ' + type));
+ case 'EDDSA':
+ case 'EdDSA':
+ if (type === 'private')
+ return (readPkcs1EdDSAPrivate(der));
+ throw (new Error(type + ' keys not supported with EdDSA'));
+ 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 readPkcs1EdDSAPrivate(der) {
+ var version = readMPInt(der, 'version');
+ assert.strictEqual(version.readUInt8(0), 1);
+
+ // private key
+ var k = der.readString(asn1.Ber.OctetString, true);
+
+ der.readSequence(0xa0);
+ var oid = der.readOID();
+ assert.strictEqual(oid, '1.3.101.112', 'the ed25519 curve identifier');
+
+ der.readSequence(0xa1);
+ var A = utils.readBitString(der);
+
+ var key = {
+ type: 'ed25519',
+ parts: [
+ { name: 'A', data: utils.zeroPadToLength(A, 32) },
+ { name: 'k', data: k }
+ ]
+ };
+
+ 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: Buffer.from(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: Buffer.from(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;
+ case 'ed25519':
+ if (PrivateKey.isPrivateKey(key))
+ writePkcs1EdDSAPrivate(der, key);
+ else
+ writePkcs1EdDSAPublic(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 = Buffer.from([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 = Buffer.from([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 = Buffer.from([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();
+}
+
+function writePkcs1EdDSAPrivate(der, key) {
+ var ver = Buffer.from([1]);
+ der.writeBuffer(ver, asn1.Ber.Integer);
+
+ der.writeBuffer(key.part.k.data, asn1.Ber.OctetString);
+
+ der.startSequence(0xa0);
+ der.writeOID('1.3.101.112');
+ der.endSequence();
+
+ der.startSequence(0xa1);
+ utils.writeBitString(der, key.part.A.data);
+ der.endSequence();
+}
+
+function writePkcs1EdDSAPublic(der, key) {
+ throw (new Error('Public keys are not supported for EdDSA PKCS#1'));
+}
diff --git a/node_modules/sshpk/lib/formats/pkcs8.js b/node_modules/sshpk/lib/formats/pkcs8.js
new file mode 100644
index 0000000..2ca3ca7
--- /dev/null
+++ b/node_modules/sshpk/lib/formats/pkcs8.js
@@ -0,0 +1,631 @@
+// Copyright 2018 Joyent, Inc.
+
+module.exports = {
+ read: read,
+ readPkcs8: readPkcs8,
+ write: write,
+ writePkcs8: writePkcs8,
+ pkcs8ToBuffer: pkcs8ToBuffer,
+
+ readECDSACurve: readECDSACurve,
+ writeECDSACurve: writeECDSACurve
+};
+
+var assert = require('assert-plus');
+var asn1 = require('asn1');
+var Buffer = require('safer-buffer').Buffer;
+var algs = require('../algs');
+var utils = require('../utils');
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+var pem = require('./pem');
+
+function read(buf, options) {
+ return (pem.read(buf, options, 'pkcs8'));
+}
+
+function write(key, options) {
+ return (pem.write(key, options, 'pkcs8'));
+}
+
+/* Helper to read in a single mpint */
+function readMPInt(der, nm) {
+ assert.strictEqual(der.peek(), asn1.Ber.Integer,
+ nm + ' is not an Integer');
+ return (utils.mpNormalize(der.readString(asn1.Ber.Integer, true)));
+}
+
+function readPkcs8(alg, type, der) {
+ /* Private keys in pkcs#8 format have a weird extra int */
+ if (der.peek() === asn1.Ber.Integer) {
+ assert.strictEqual(type, 'private',
+ 'unexpected Integer at start of public key');
+ der.readString(asn1.Ber.Integer, true);
+ }
+
+ der.readSequence();
+ var next = der.offset + der.length;
+
+ var oid = der.readOID();
+ switch (oid) {
+ case '1.2.840.113549.1.1.1':
+ der._offset = next;
+ if (type === 'public')
+ return (readPkcs8RSAPublic(der));
+ else
+ return (readPkcs8RSAPrivate(der));
+ case '1.2.840.10040.4.1':
+ if (type === 'public')
+ return (readPkcs8DSAPublic(der));
+ else
+ return (readPkcs8DSAPrivate(der));
+ case '1.2.840.10045.2.1':
+ if (type === 'public')
+ return (readPkcs8ECDSAPublic(der));
+ else
+ return (readPkcs8ECDSAPrivate(der));
+ case '1.3.101.112':
+ if (type === 'public') {
+ return (readPkcs8EdDSAPublic(der));
+ } else {
+ return (readPkcs8EdDSAPrivate(der));
+ }
+ case '1.3.101.110':
+ if (type === 'public') {
+ return (readPkcs8X25519Public(der));
+ } else {
+ return (readPkcs8X25519Private(der));
+ }
+ default:
+ throw (new Error('Unknown key type OID ' + oid));
+ }
+}
+
+function readPkcs8RSAPublic(der) {
+ // bit string sequence
+ der.readSequence(asn1.Ber.BitString);
+ der.readByte();
+ der.readSequence();
+
+ // modulus
+ var n = readMPInt(der, 'modulus');
+ var e = readMPInt(der, 'exponent');
+
+ // now, make the key
+ var key = {
+ type: 'rsa',
+ source: der.originalInput,
+ parts: [
+ { name: 'e', data: e },
+ { name: 'n', data: n }
+ ]
+ };
+
+ return (new Key(key));
+}
+
+function readPkcs8RSAPrivate(der) {
+ der.readSequence(asn1.Ber.OctetString);
+ der.readSequence();
+
+ var ver = readMPInt(der, 'version');
+ assert.equal(ver[0], 0x0, 'unknown RSA private key version');
+
+ // modulus then public exponent
+ var n = readMPInt(der, 'modulus');
+ var e = readMPInt(der, 'public exponent');
+ var d = readMPInt(der, 'private exponent');
+ var p = readMPInt(der, 'prime1');
+ var q = readMPInt(der, 'prime2');
+ var dmodp = readMPInt(der, 'exponent1');
+ var dmodq = readMPInt(der, 'exponent2');
+ var iqmp = readMPInt(der, 'iqmp');
+
+ // now, make the key
+ var key = {
+ type: 'rsa',
+ parts: [
+ { name: 'n', data: n },
+ { name: 'e', data: e },
+ { name: 'd', data: d },
+ { name: 'iqmp', data: iqmp },
+ { name: 'p', data: p },
+ { name: 'q', data: q },
+ { name: 'dmodp', data: dmodp },
+ { name: 'dmodq', data: dmodq }
+ ]
+ };
+
+ return (new PrivateKey(key));
+}
+
+function readPkcs8DSAPublic(der) {
+ der.readSequence();
+
+ var p = readMPInt(der, 'p');
+ var q = readMPInt(der, 'q');
+ var g = readMPInt(der, 'g');
+
+ // bit string sequence
+ der.readSequence(asn1.Ber.BitString);
+ der.readByte();
+
+ var y = readMPInt(der, 'y');
+
+ // now, make the key
+ var key = {
+ type: 'dsa',
+ parts: [
+ { name: 'p', data: p },
+ { name: 'q', data: q },
+ { name: 'g', data: g },
+ { name: 'y', data: y }
+ ]
+ };
+
+ return (new Key(key));
+}
+
+function readPkcs8DSAPrivate(der) {
+ der.readSequence();
+
+ var p = readMPInt(der, 'p');
+ var q = readMPInt(der, 'q');
+ var g = readMPInt(der, 'g');
+
+ der.readSequence(asn1.Ber.OctetString);
+ var x = readMPInt(der, 'x');
+
+ /* The pkcs#8 format does not include the public key */
+ var y = utils.calculateDSAPublic(g, p, x);
+
+ var key = {
+ type: 'dsa',
+ parts: [
+ { name: 'p', data: p },
+ { name: 'q', data: q },
+ { name: 'g', data: g },
+ { name: 'y', data: y },
+ { name: 'x', data: x }
+ ]
+ };
+
+ return (new PrivateKey(key));
+}
+
+function readECDSACurve(der) {
+ var curveName, curveNames;
+ var j, c, cd;
+
+ if (der.peek() === asn1.Ber.OID) {
+ var oid = der.readOID();
+
+ curveNames = Object.keys(algs.curves);
+ for (j = 0; j < curveNames.length; ++j) {
+ c = curveNames[j];
+ cd = algs.curves[c];
+ if (cd.pkcs8oid === oid) {
+ curveName = c;
+ break;
+ }
+ }
+
+ } else {
+ // ECParameters sequence
+ der.readSequence();
+ var version = der.readString(asn1.Ber.Integer, true);
+ assert.strictEqual(version[0], 1, 'ECDSA key not version 1');
+
+ var curve = {};
+
+ // FieldID sequence
+ der.readSequence();
+ var fieldTypeOid = der.readOID();
+ assert.strictEqual(fieldTypeOid, '1.2.840.10045.1.1',
+ 'ECDSA key is not from a prime-field');
+ var p = curve.p = utils.mpNormalize(
+ der.readString(asn1.Ber.Integer, true));
+ /*
+ * p always starts with a 1 bit, so count the zeros to get its
+ * real size.
+ */
+ curve.size = p.length * 8 - utils.countZeros(p);
+
+ // Curve sequence
+ der.readSequence();
+ curve.a = utils.mpNormalize(
+ der.readString(asn1.Ber.OctetString, true));
+ curve.b = utils.mpNormalize(
+ der.readString(asn1.Ber.OctetString, true));
+ if (der.peek() === asn1.Ber.BitString)
+ curve.s = der.readString(asn1.Ber.BitString, true);
+
+ // Combined Gx and Gy
+ curve.G = der.readString(asn1.Ber.OctetString, true);
+ assert.strictEqual(curve.G[0], 0x4,
+ 'uncompressed G is required');
+
+ curve.n = utils.mpNormalize(
+ der.readString(asn1.Ber.Integer, true));
+ curve.h = utils.mpNormalize(
+ der.readString(asn1.Ber.Integer, true));
+ assert.strictEqual(curve.h[0], 0x1, 'a cofactor=1 curve is ' +
+ 'required');
+
+ curveNames = Object.keys(algs.curves);
+ var ks = Object.keys(curve);
+ for (j = 0; j < curveNames.length; ++j) {
+ c = curveNames[j];
+ cd = algs.curves[c];
+ var equal = true;
+ for (var i = 0; i < ks.length; ++i) {
+ var k = ks[i];
+ if (cd[k] === undefined)
+ continue;
+ if (typeof (cd[k]) === 'object' &&
+ cd[k].equals !== undefined) {
+ if (!cd[k].equals(curve[k])) {
+ equal = false;
+ break;
+ }
+ } else if (Buffer.isBuffer(cd[k])) {
+ if (cd[k].toString('binary')
+ !== curve[k].toString('binary')) {
+ equal = false;
+ break;
+ }
+ } else {
+ if (cd[k] !== curve[k]) {
+ equal = false;
+ break;
+ }
+ }
+ }
+ if (equal) {
+ curveName = c;
+ break;
+ }
+ }
+ }
+ return (curveName);
+}
+
+function readPkcs8ECDSAPrivate(der) {
+ var curveName = readECDSACurve(der);
+ assert.string(curveName, 'a known elliptic curve');
+
+ der.readSequence(asn1.Ber.OctetString);
+ der.readSequence();
+
+ var version = readMPInt(der, 'version');
+ assert.equal(version[0], 1, 'unknown version of ECDSA key');
+
+ var d = der.readString(asn1.Ber.OctetString, true);
+ var Q;
+
+ if (der.peek() == 0xa0) {
+ der.readSequence(0xa0);
+ der._offset += der.length;
+ }
+ if (der.peek() == 0xa1) {
+ der.readSequence(0xa1);
+ Q = der.readString(asn1.Ber.BitString, true);
+ Q = utils.ecNormalize(Q);
+ }
+
+ if (Q === undefined) {
+ var pub = utils.publicFromPrivateECDSA(curveName, d);
+ Q = pub.part.Q.data;
+ }
+
+ var key = {
+ type: 'ecdsa',
+ parts: [
+ { name: 'curve', data: Buffer.from(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: Buffer.from(curveName) },
+ { name: 'Q', data: Q }
+ ]
+ };
+
+ return (new Key(key));
+}
+
+function readPkcs8EdDSAPublic(der) {
+ if (der.peek() === 0x00)
+ der.readByte();
+
+ var A = utils.readBitString(der);
+
+ var key = {
+ type: 'ed25519',
+ parts: [
+ { name: 'A', data: utils.zeroPadToLength(A, 32) }
+ ]
+ };
+
+ return (new Key(key));
+}
+
+function readPkcs8X25519Public(der) {
+ var A = utils.readBitString(der);
+
+ var key = {
+ type: 'curve25519',
+ parts: [
+ { name: 'A', data: utils.zeroPadToLength(A, 32) }
+ ]
+ };
+
+ return (new Key(key));
+}
+
+function readPkcs8EdDSAPrivate(der) {
+ if (der.peek() === 0x00)
+ der.readByte();
+
+ der.readSequence(asn1.Ber.OctetString);
+ var k = der.readString(asn1.Ber.OctetString, true);
+ k = utils.zeroPadToLength(k, 32);
+
+ var A;
+ if (der.peek() === asn1.Ber.BitString) {
+ A = utils.readBitString(der);
+ A = utils.zeroPadToLength(A, 32);
+ } else {
+ A = utils.calculateED25519Public(k);
+ }
+
+ var key = {
+ type: 'ed25519',
+ parts: [
+ { name: 'A', data: utils.zeroPadToLength(A, 32) },
+ { name: 'k', data: utils.zeroPadToLength(k, 32) }
+ ]
+ };
+
+ return (new PrivateKey(key));
+}
+
+function readPkcs8X25519Private(der) {
+ if (der.peek() === 0x00)
+ der.readByte();
+
+ der.readSequence(asn1.Ber.OctetString);
+ var k = der.readString(asn1.Ber.OctetString, true);
+ k = utils.zeroPadToLength(k, 32);
+
+ var A = utils.calculateX25519Public(k);
+
+ var key = {
+ type: 'curve25519',
+ parts: [
+ { name: 'A', data: utils.zeroPadToLength(A, 32) },
+ { name: 'k', data: utils.zeroPadToLength(k, 32) }
+ ]
+ };
+
+ return (new PrivateKey(key));
+}
+
+function pkcs8ToBuffer(key) {
+ var der = new asn1.BerWriter();
+ writePkcs8(der, key);
+ return (der.buffer);
+}
+
+function writePkcs8(der, key) {
+ der.startSequence();
+
+ if (PrivateKey.isPrivateKey(key)) {
+ var sillyInt = Buffer.from([0]);
+ 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;
+ case 'ed25519':
+ der.writeOID('1.3.101.112');
+ if (PrivateKey.isPrivateKey(key))
+ throw (new Error('Ed25519 private keys in pkcs8 ' +
+ 'format are not supported'));
+ writePkcs8EdDSAPublic(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 = Buffer.from([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 = Buffer.from([1]);
+ 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 = Buffer.from([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 = Buffer.from([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();
+}
+
+function writePkcs8EdDSAPublic(key, der) {
+ der.endSequence();
+
+ utils.writeBitString(der, key.part.A.data);
+}
+
+function writePkcs8EdDSAPrivate(key, der) {
+ der.endSequence();
+
+ var k = utils.mpNormalize(key.part.k.data, true);
+ der.startSequence(asn1.Ber.OctetString);
+ der.writeBuffer(k, asn1.Ber.OctetString);
+ der.endSequence();
+}
diff --git a/node_modules/sshpk/lib/formats/putty.js b/node_modules/sshpk/lib/formats/putty.js
new file mode 100644
index 0000000..344419f
--- /dev/null
+++ b/node_modules/sshpk/lib/formats/putty.js
@@ -0,0 +1,99 @@
+// Copyright 2018 Joyent, Inc.
+
+module.exports = {
+ read: read,
+ write: write
+};
+
+var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
+var rfc4253 = require('./rfc4253');
+var Key = require('../key');
+
+var errors = require('../errors');
+
+function read(buf, options) {
+ var lines = buf.toString('ascii').split(/[\r\n]+/);
+ var found = false;
+ var parts;
+ var si = 0;
+ while (si < lines.length) {
+ parts = splitHeader(lines[si++]);
+ if (parts &&
+ parts[0].toLowerCase() === 'putty-user-key-file-2') {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ throw (new Error('No PuTTY format first line found'));
+ }
+ var alg = parts[1];
+
+ parts = splitHeader(lines[si++]);
+ assert.equal(parts[0].toLowerCase(), 'encryption');
+
+ parts = splitHeader(lines[si++]);
+ assert.equal(parts[0].toLowerCase(), 'comment');
+ var comment = parts[1];
+
+ parts = splitHeader(lines[si++]);
+ assert.equal(parts[0].toLowerCase(), 'public-lines');
+ var publicLines = parseInt(parts[1], 10);
+ if (!isFinite(publicLines) || publicLines < 0 ||
+ publicLines > lines.length) {
+ throw (new Error('Invalid public-lines count'));
+ }
+
+ var publicBuf = Buffer.from(
+ lines.slice(si, si + publicLines).join(''), 'base64');
+ var keyType = rfc4253.algToKeyType(alg);
+ var key = rfc4253.read(publicBuf);
+ if (key.type !== keyType) {
+ throw (new Error('Outer key algorithm mismatch'));
+ }
+ key.comment = comment;
+ return (key);
+}
+
+function splitHeader(line) {
+ var idx = line.indexOf(':');
+ if (idx === -1)
+ return (null);
+ var header = line.slice(0, idx);
+ ++idx;
+ while (line[idx] === ' ')
+ ++idx;
+ var rest = line.slice(idx);
+ return ([header, rest]);
+}
+
+function write(key, options) {
+ assert.object(key);
+ if (!Key.isKey(key))
+ throw (new Error('Must be a public key'));
+
+ var alg = rfc4253.keyTypeToAlg(key);
+ var buf = rfc4253.write(key);
+ var comment = key.comment || '';
+
+ var b64 = buf.toString('base64');
+ var lines = wrap(b64, 64);
+
+ lines.unshift('Public-Lines: ' + lines.length);
+ lines.unshift('Comment: ' + comment);
+ lines.unshift('Encryption: none');
+ lines.unshift('PuTTY-User-Key-File-2: ' + alg);
+
+ return (Buffer.from(lines.join('\n') + '\n'));
+}
+
+function wrap(txt, len) {
+ var lines = [];
+ var pos = 0;
+ while (pos < txt.length) {
+ lines.push(txt.slice(pos, pos + 64));
+ pos += 64;
+ }
+ return (lines);
+}
diff --git a/node_modules/sshpk/lib/formats/rfc4253.js b/node_modules/sshpk/lib/formats/rfc4253.js
new file mode 100644
index 0000000..52fddcb
--- /dev/null
+++ b/node_modules/sshpk/lib/formats/rfc4253.js
@@ -0,0 +1,166 @@
+// 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 Buffer = require('safer-buffer').Buffer;
+var algs = require('../algs');
+var utils = require('../utils');
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+var SSHBuffer = require('../ssh-buffer');
+
+function algToKeyType(alg) {
+ assert.string(alg);
+ if (alg === 'ssh-dss')
+ return ('dsa');
+ else if (alg === 'ssh-rsa')
+ return ('rsa');
+ else if (alg === 'ssh-ed25519')
+ return ('ed25519');
+ else if (alg === 'ssh-curve25519')
+ return ('curve25519');
+ else if (alg.match(/^ecdsa-sha2-/))
+ return ('ecdsa');
+ else
+ throw (new Error('Unknown algorithm ' + alg));
+}
+
+function keyTypeToAlg(key) {
+ assert.object(key);
+ if (key.type === 'dsa')
+ return ('ssh-dss');
+ else if (key.type === 'rsa')
+ return ('ssh-rsa');
+ else if (key.type === 'ed25519')
+ return ('ssh-ed25519');
+ else if (key.type === 'curve25519')
+ return ('ssh-curve25519');
+ else if (key.type === 'ecdsa')
+ return ('ecdsa-sha2-' + key.part.curve.data.toString());
+ else
+ throw (new Error('Unknown key type ' + key.type));
+}
+
+function read(partial, type, buf, options) {
+ if (typeof (buf) === 'string')
+ buf = Buffer.from(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) {
+ var p = parts[i];
+ p.name = algInfo.parts[i];
+ /*
+ * OpenSSH stores ed25519 "private" keys as seed + public key
+ * concat'd together (k followed by A). We want to keep them
+ * separate for other formats that don't do this.
+ */
+ if (key.type === 'ed25519' && p.name === 'k')
+ p.data = p.data.slice(0, 32);
+
+ if (p.name !== 'curve' && algInfo.normalize !== false) {
+ var nd;
+ if (key.type === 'ed25519') {
+ nd = utils.zeroPadToLength(p.data, 32);
+ } else {
+ nd = utils.mpNormalize(p.data);
+ }
+ if (nd.toString('binary') !==
+ p.data.toString('binary')) {
+ p.data = nd;
+ normalized = false;
+ }
+ }
+ }
+
+ if (normalized)
+ key._rfc4253Cache = sshbuf.toBuffer();
+
+ if (partial && typeof (partial) === 'object') {
+ partial.remainder = sshbuf.remainder();
+ partial.consumed = sshbuf._offset;
+ }
+
+ return (new Constructor(key));
+}
+
+function write(key, options) {
+ assert.object(key);
+
+ var alg = keyTypeToAlg(key);
+ var i;
+
+ var algInfo = algs.info[key.type];
+ if (PrivateKey.isPrivateKey(key))
+ algInfo = algs.privInfo[key.type];
+ var parts = algInfo.parts;
+
+ var buf = new SSHBuffer({});
+
+ buf.writeString(alg);
+
+ for (i = 0; i < parts.length; ++i) {
+ var data = key.part[parts[i]].data;
+ if (algInfo.normalize !== false) {
+ if (key.type === 'ed25519')
+ data = utils.zeroPadToLength(data, 32);
+ else
+ data = utils.mpNormalize(data);
+ }
+ if (key.type === 'ed25519' && parts[i] === 'k')
+ data = Buffer.concat([data, key.part.A.data]);
+ buf.writeBuffer(data);
+ }
+
+ return (buf.toBuffer());
+}
diff --git a/node_modules/sshpk/lib/formats/ssh-private.js b/node_modules/sshpk/lib/formats/ssh-private.js
new file mode 100644
index 0000000..5e7eed8
--- /dev/null
+++ b/node_modules/sshpk/lib/formats/ssh-private.js
@@ -0,0 +1,262 @@
+// Copyright 2015 Joyent, Inc.
+
+module.exports = {
+ read: read,
+ readSSHPrivate: readSSHPrivate,
+ write: write
+};
+
+var assert = require('assert-plus');
+var asn1 = require('asn1');
+var Buffer = require('safer-buffer').Buffer;
+var algs = require('../algs');
+var utils = require('../utils');
+var crypto = require('crypto');
+
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+var pem = require('./pem');
+var rfc4253 = require('./rfc4253');
+var SSHBuffer = require('../ssh-buffer');
+var errors = require('../errors');
+
+var bcrypt;
+
+function read(buf, options) {
+ return (pem.read(buf, options));
+}
+
+var MAGIC = 'openssh-key-v1';
+
+function readSSHPrivate(type, buf, options) {
+ buf = new SSHBuffer({buffer: buf});
+
+ var magic = buf.readCString();
+ assert.strictEqual(magic, MAGIC, 'bad magic string');
+
+ var cipher = buf.readString();
+ var kdf = buf.readString();
+ var kdfOpts = buf.readBuffer();
+
+ var nkeys = buf.readInt();
+ if (nkeys !== 1) {
+ throw (new Error('OpenSSH-format key file contains ' +
+ 'multiple keys: this is unsupported.'));
+ }
+
+ var pubKey = buf.readBuffer();
+
+ if (type === 'public') {
+ assert.ok(buf.atEnd(), 'excess bytes left after key');
+ return (rfc4253.read(pubKey));
+ }
+
+ var privKeyBlob = buf.readBuffer();
+ assert.ok(buf.atEnd(), 'excess bytes left after key');
+
+ var kdfOptsBuf = new SSHBuffer({ buffer: kdfOpts });
+ switch (kdf) {
+ case 'none':
+ if (cipher !== 'none') {
+ throw (new Error('OpenSSH-format key uses KDF "none" ' +
+ 'but specifies a cipher other than "none"'));
+ }
+ break;
+ case 'bcrypt':
+ var salt = kdfOptsBuf.readBuffer();
+ var rounds = kdfOptsBuf.readInt();
+ var cinf = utils.opensshCipherInfo(cipher);
+ if (bcrypt === undefined) {
+ bcrypt = require('bcrypt-pbkdf');
+ }
+
+ if (typeof (options.passphrase) === 'string') {
+ options.passphrase = Buffer.from(options.passphrase,
+ 'utf-8');
+ }
+ if (!Buffer.isBuffer(options.passphrase)) {
+ throw (new errors.KeyEncryptedError(
+ options.filename, 'OpenSSH'));
+ }
+
+ var pass = new Uint8Array(options.passphrase);
+ var salti = new Uint8Array(salt);
+ /* Use the pbkdf to derive both the key and the IV. */
+ var out = new Uint8Array(cinf.keySize + cinf.blockSize);
+ var res = bcrypt.pbkdf(pass, pass.length, salti, salti.length,
+ out, out.length, rounds);
+ if (res !== 0) {
+ throw (new Error('bcrypt_pbkdf function returned ' +
+ 'failure, parameters invalid'));
+ }
+ out = Buffer.from(out);
+ var ckey = out.slice(0, cinf.keySize);
+ var iv = out.slice(cinf.keySize, cinf.keySize + cinf.blockSize);
+ var cipherStream = crypto.createDecipheriv(cinf.opensslName,
+ ckey, iv);
+ cipherStream.setAutoPadding(false);
+ var chunk, chunks = [];
+ cipherStream.once('error', function (e) {
+ if (e.toString().indexOf('bad decrypt') !== -1) {
+ throw (new Error('Incorrect passphrase ' +
+ 'supplied, could not decrypt key'));
+ }
+ throw (e);
+ });
+ cipherStream.write(privKeyBlob);
+ cipherStream.end();
+ while ((chunk = cipherStream.read()) !== null)
+ chunks.push(chunk);
+ privKeyBlob = Buffer.concat(chunks);
+ break;
+ default:
+ throw (new Error(
+ 'OpenSSH-format key uses unknown KDF "' + kdf + '"'));
+ }
+
+ buf = new SSHBuffer({buffer: privKeyBlob});
+
+ var checkInt1 = buf.readInt();
+ var checkInt2 = buf.readInt();
+ if (checkInt1 !== checkInt2) {
+ throw (new Error('Incorrect passphrase supplied, could not ' +
+ 'decrypt key'));
+ }
+
+ var ret = {};
+ var key = rfc4253.readInternal(ret, 'private', buf.remainder());
+
+ buf.skip(ret.consumed);
+
+ var comment = buf.readString();
+ key.comment = comment;
+
+ return (key);
+}
+
+function write(key, options) {
+ var pubKey;
+ if (PrivateKey.isPrivateKey(key))
+ pubKey = key.toPublic();
+ else
+ pubKey = key;
+
+ var cipher = 'none';
+ var kdf = 'none';
+ var kdfopts = Buffer.alloc(0);
+ var cinf = { blockSize: 8 };
+ var passphrase;
+ if (options !== undefined) {
+ passphrase = options.passphrase;
+ if (typeof (passphrase) === 'string')
+ passphrase = Buffer.from(passphrase, 'utf-8');
+ if (passphrase !== undefined) {
+ assert.buffer(passphrase, 'options.passphrase');
+ assert.optionalString(options.cipher, 'options.cipher');
+ cipher = options.cipher;
+ if (cipher === undefined)
+ cipher = 'aes128-ctr';
+ cinf = utils.opensshCipherInfo(cipher);
+ kdf = 'bcrypt';
+ }
+ }
+
+ var privBuf;
+ if (PrivateKey.isPrivateKey(key)) {
+ privBuf = new SSHBuffer({});
+ var checkInt = crypto.randomBytes(4).readUInt32BE(0);
+ privBuf.writeInt(checkInt);
+ privBuf.writeInt(checkInt);
+ privBuf.write(key.toBuffer('rfc4253'));
+ privBuf.writeString(key.comment || '');
+
+ var n = 1;
+ while (privBuf._offset % cinf.blockSize !== 0)
+ privBuf.writeChar(n++);
+ privBuf = privBuf.toBuffer();
+ }
+
+ switch (kdf) {
+ case 'none':
+ break;
+ case 'bcrypt':
+ var salt = crypto.randomBytes(16);
+ var rounds = 16;
+ var kdfssh = new SSHBuffer({});
+ kdfssh.writeBuffer(salt);
+ kdfssh.writeInt(rounds);
+ kdfopts = kdfssh.toBuffer();
+
+ if (bcrypt === undefined) {
+ bcrypt = require('bcrypt-pbkdf');
+ }
+ var pass = new Uint8Array(passphrase);
+ var salti = new Uint8Array(salt);
+ /* Use the pbkdf to derive both the key and the IV. */
+ var out = new Uint8Array(cinf.keySize + cinf.blockSize);
+ var res = bcrypt.pbkdf(pass, pass.length, salti, salti.length,
+ out, out.length, rounds);
+ if (res !== 0) {
+ throw (new Error('bcrypt_pbkdf function returned ' +
+ 'failure, parameters invalid'));
+ }
+ out = Buffer.from(out);
+ var ckey = out.slice(0, cinf.keySize);
+ var iv = out.slice(cinf.keySize, cinf.keySize + cinf.blockSize);
+
+ var cipherStream = crypto.createCipheriv(cinf.opensslName,
+ ckey, iv);
+ cipherStream.setAutoPadding(false);
+ var chunk, chunks = [];
+ cipherStream.once('error', function (e) {
+ throw (e);
+ });
+ cipherStream.write(privBuf);
+ cipherStream.end();
+ while ((chunk = cipherStream.read()) !== null)
+ chunks.push(chunk);
+ privBuf = Buffer.concat(chunks);
+ break;
+ default:
+ throw (new Error('Unsupported kdf ' + kdf));
+ }
+
+ var buf = new SSHBuffer({});
+
+ buf.writeCString(MAGIC);
+ buf.writeString(cipher); /* cipher */
+ buf.writeString(kdf); /* kdf */
+ buf.writeBuffer(kdfopts); /* kdfoptions */
+
+ buf.writeInt(1); /* nkeys */
+ buf.writeBuffer(pubKey.toBuffer('rfc4253'));
+
+ if (privBuf)
+ buf.writeBuffer(privBuf);
+
+ buf = buf.toBuffer();
+
+ var header;
+ if (PrivateKey.isPrivateKey(key))
+ header = 'OPENSSH PRIVATE KEY';
+ else
+ header = 'OPENSSH PUBLIC KEY';
+
+ var tmp = buf.toString('base64');
+ var len = tmp.length + (tmp.length / 70) +
+ 18 + 16 + header.length*2 + 10;
+ buf = Buffer.alloc(len);
+ var o = 0;
+ o += buf.write('-----BEGIN ' + header + '-----\n', o);
+ for (var i = 0; i < tmp.length; ) {
+ var limit = i + 70;
+ if (limit > tmp.length)
+ limit = tmp.length;
+ o += buf.write(tmp.slice(i, limit), o);
+ buf[o++] = 10;
+ i = limit;
+ }
+ o += buf.write('-----END ' + header + '-----\n', o);
+
+ return (buf.slice(0, o));
+}
diff --git a/node_modules/sshpk/lib/formats/ssh.js b/node_modules/sshpk/lib/formats/ssh.js
new file mode 100644
index 0000000..c8e9c93
--- /dev/null
+++ b/node_modules/sshpk/lib/formats/ssh.js
@@ -0,0 +1,115 @@
+// Copyright 2015 Joyent, Inc.
+
+module.exports = {
+ read: read,
+ write: write
+};
+
+var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
+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+\/]+[=]*)([ \t]+([^ \t][^\n]*[\n]*)?)?$/;
+/*JSSTYLED*/
+var SSHKEY_RE2 = /^([a-z0-9-]+)[ \t\n]+([a-zA-Z0-9+\/][a-zA-Z0-9+\/ \t\n=]*)([^a-zA-Z0-9+\/ \t\n=].*)?$/;
+
+function read(buf, options) {
+ if (typeof (buf) !== 'string') {
+ assert.buffer(buf, 'buf');
+ buf = buf.toString('ascii');
+ }
+
+ var trimmed = buf.trim().replace(/[\\\r]/g, '');
+ var m = trimmed.match(SSHKEY_RE);
+ if (!m)
+ m = trimmed.match(SSHKEY_RE2);
+ assert.ok(m, 'key must match regex');
+
+ var type = rfc4253.algToKeyType(m[1]);
+ var kbuf = Buffer.from(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 = Buffer.from(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] ? m[3] : '');
+ var realOffset = Math.ceil(ret.consumed / 3) * 4;
+ data = data.slice(0, realOffset - 2). /*JSSTYLED*/
+ replace(/[^a-zA-Z0-9+\/=]/g, '') +
+ data.slice(realOffset - 2);
+
+ var padding = ret.consumed % 3;
+ if (padding > 0 &&
+ data.slice(realOffset - 1, realOffset) !== '=')
+ realOffset--;
+ while (data.slice(realOffset, realOffset + 1) === '=')
+ realOffset++;
+
+ /* Finally, grab what we think is the comment & clean it up. */
+ var trailer = data.slice(realOffset);
+ trailer = trailer.replace(/[\r\n]/g, ' ').
+ replace(/^\s+/, '');
+ if (trailer.match(/^[a-zA-Z0-9]/))
+ key.comment = trailer;
+ }
+
+ return (key);
+}
+
+function write(key, options) {
+ assert.object(key);
+ if (!Key.isKey(key))
+ throw (new Error('Must be a public key'));
+
+ var parts = [];
+ var alg = rfc4253.keyTypeToAlg(key);
+ parts.push(alg);
+
+ var buf = rfc4253.write(key);
+ parts.push(buf.toString('base64'));
+
+ if (key.comment)
+ parts.push(key.comment);
+
+ return (Buffer.from(parts.join(' ')));
+}
diff --git a/node_modules/sshpk/lib/formats/x509-pem.js b/node_modules/sshpk/lib/formats/x509-pem.js
new file mode 100644
index 0000000..3155ef0
--- /dev/null
+++ b/node_modules/sshpk/lib/formats/x509-pem.js
@@ -0,0 +1,88 @@
+// Copyright 2016 Joyent, Inc.
+
+var x509 = require('./x509');
+
+module.exports = {
+ read: read,
+ verify: x509.verify,
+ sign: x509.sign,
+ write: write
+};
+
+var assert = require('assert-plus');
+var asn1 = require('asn1');
+var Buffer = require('safer-buffer').Buffer;
+var algs = require('../algs');
+var utils = require('../utils');
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+var pem = require('./pem');
+var Identity = require('../identity');
+var Signature = require('../signature');
+var Certificate = require('../certificate');
+
+function read(buf, options) {
+ if (typeof (buf) !== 'string') {
+ assert.buffer(buf, 'buf');
+ buf = buf.toString('ascii');
+ }
+
+ var lines = buf.trim().split(/[\r\n]+/g);
+
+ var m;
+ var si = -1;
+ while (!m && si < lines.length) {
+ m = lines[++si].match(/*JSSTYLED*/
+ /[-]+[ ]*BEGIN CERTIFICATE[ ]*[-]+/);
+ }
+ assert.ok(m, 'invalid PEM header');
+
+ var m2;
+ var ei = lines.length;
+ while (!m2 && ei > 0) {
+ m2 = lines[--ei].match(/*JSSTYLED*/
+ /[-]+[ ]*END CERTIFICATE[ ]*[-]+/);
+ }
+ assert.ok(m2, 'invalid PEM footer');
+
+ lines = lines.slice(si, ei + 1);
+
+ var headers = {};
+ while (true) {
+ lines = lines.slice(1);
+ m = lines[0].match(/*JSSTYLED*/
+ /^([A-Za-z0-9-]+): (.+)$/);
+ if (!m)
+ break;
+ headers[m[1].toLowerCase()] = m[2];
+ }
+
+ /* Chop off the first and last lines */
+ lines = lines.slice(0, -1).join('');
+ buf = Buffer.from(lines, 'base64');
+
+ return (x509.read(buf, options));
+}
+
+function write(cert, options) {
+ var dbuf = x509.write(cert, options);
+
+ var header = 'CERTIFICATE';
+ var tmp = dbuf.toString('base64');
+ var len = tmp.length + (tmp.length / 64) +
+ 18 + 16 + header.length*2 + 10;
+ var buf = Buffer.alloc(len);
+ var o = 0;
+ o += buf.write('-----BEGIN ' + header + '-----\n', o);
+ for (var i = 0; i < tmp.length; ) {
+ var limit = i + 64;
+ if (limit > tmp.length)
+ limit = tmp.length;
+ o += buf.write(tmp.slice(i, limit), o);
+ buf[o++] = 10;
+ i = limit;
+ }
+ o += buf.write('-----END ' + header + '-----\n', o);
+
+ return (buf.slice(0, o));
+}
diff --git a/node_modules/sshpk/lib/formats/x509.js b/node_modules/sshpk/lib/formats/x509.js
new file mode 100644
index 0000000..0144c44
--- /dev/null
+++ b/node_modules/sshpk/lib/formats/x509.js
@@ -0,0 +1,752 @@
+// Copyright 2017 Joyent, Inc.
+
+module.exports = {
+ read: read,
+ verify: verify,
+ sign: sign,
+ signAsync: signAsync,
+ write: write
+};
+
+var assert = require('assert-plus');
+var asn1 = require('asn1');
+var Buffer = require('safer-buffer').Buffer;
+var algs = require('../algs');
+var utils = require('../utils');
+var Key = require('../key');
+var PrivateKey = require('../private-key');
+var pem = require('./pem');
+var Identity = require('../identity');
+var Signature = require('../signature');
+var Certificate = require('../certificate');
+var pkcs8 = require('./pkcs8');
+
+/*
+ * This file is based on RFC5280 (X.509).
+ */
+
+/* Helper to read in a single mpint */
+function readMPInt(der, nm) {
+ assert.strictEqual(der.peek(), asn1.Ber.Integer,
+ nm + ' is not an Integer');
+ return (utils.mpNormalize(der.readString(asn1.Ber.Integer, true)));
+}
+
+function verify(cert, key) {
+ var sig = cert.signatures.x509;
+ assert.object(sig, 'x509 signature');
+
+ var algParts = sig.algo.split('-');
+ if (algParts[0] !== key.type)
+ return (false);
+
+ var blob = sig.cache;
+ if (blob === undefined) {
+ var der = new asn1.BerWriter();
+ writeTBSCert(cert, der);
+ blob = der.buffer;
+ }
+
+ var verifier = key.createVerify(algParts[1]);
+ verifier.write(blob);
+ return (verifier.verify(sig.signature));
+}
+
+function Local(i) {
+ return (asn1.Ber.Context | asn1.Ber.Constructor | i);
+}
+
+function Context(i) {
+ return (asn1.Ber.Context | i);
+}
+
+var SIGN_ALGS = {
+ 'rsa-md5': '1.2.840.113549.1.1.4',
+ 'rsa-sha1': '1.2.840.113549.1.1.5',
+ 'rsa-sha256': '1.2.840.113549.1.1.11',
+ 'rsa-sha384': '1.2.840.113549.1.1.12',
+ 'rsa-sha512': '1.2.840.113549.1.1.13',
+ 'dsa-sha1': '1.2.840.10040.4.3',
+ 'dsa-sha256': '2.16.840.1.101.3.4.3.2',
+ 'ecdsa-sha1': '1.2.840.10045.4.1',
+ 'ecdsa-sha256': '1.2.840.10045.4.3.2',
+ 'ecdsa-sha384': '1.2.840.10045.4.3.3',
+ 'ecdsa-sha512': '1.2.840.10045.4.3.4',
+ 'ed25519-sha512': '1.3.101.112'
+};
+Object.keys(SIGN_ALGS).forEach(function (k) {
+ SIGN_ALGS[SIGN_ALGS[k]] = k;
+});
+SIGN_ALGS['1.3.14.3.2.3'] = 'rsa-md5';
+SIGN_ALGS['1.3.14.3.2.29'] = 'rsa-sha1';
+
+var EXTS = {
+ 'issuerKeyId': '2.5.29.35',
+ 'altName': '2.5.29.17',
+ 'basicConstraints': '2.5.29.19',
+ 'keyUsage': '2.5.29.15',
+ 'extKeyUsage': '2.5.29.37'
+};
+
+function read(buf, options) {
+ if (typeof (buf) === 'string') {
+ buf = Buffer.from(buf, 'binary');
+ }
+ assert.buffer(buf, 'buf');
+
+ var der = new asn1.BerReader(buf);
+
+ der.readSequence();
+ if (Math.abs(der.length - der.remain) > 1) {
+ throw (new Error('DER sequence does not contain whole byte ' +
+ 'stream'));
+ }
+
+ var tbsStart = der.offset;
+ der.readSequence();
+ var sigOffset = der.offset + der.length;
+ var tbsEnd = sigOffset;
+
+ if (der.peek() === Local(0)) {
+ der.readSequence(Local(0));
+ var version = der.readInt();
+ assert.ok(version <= 3,
+ 'only x.509 versions up to v3 supported');
+ }
+
+ var cert = {};
+ cert.signatures = {};
+ var sig = (cert.signatures.x509 = {});
+ sig.extras = {};
+
+ cert.serial = readMPInt(der, 'serial');
+
+ der.readSequence();
+ var after = der.offset + der.length;
+ var certAlgOid = der.readOID();
+ var certAlg = SIGN_ALGS[certAlgOid];
+ if (certAlg === undefined)
+ throw (new Error('unknown signature algorithm ' + certAlgOid));
+
+ der._offset = after;
+ cert.issuer = Identity.parseAsn1(der);
+
+ der.readSequence();
+ cert.validFrom = readDate(der);
+ cert.validUntil = readDate(der);
+
+ cert.subjects = [Identity.parseAsn1(der)];
+
+ der.readSequence();
+ after = der.offset + der.length;
+ cert.subjectKey = pkcs8.readPkcs8(undefined, 'public', der);
+ der._offset = after;
+
+ /* issuerUniqueID */
+ if (der.peek() === Local(1)) {
+ der.readSequence(Local(1));
+ sig.extras.issuerUniqueID =
+ buf.slice(der.offset, der.offset + der.length);
+ der._offset += der.length;
+ }
+
+ /* subjectUniqueID */
+ if (der.peek() === Local(2)) {
+ der.readSequence(Local(2));
+ sig.extras.subjectUniqueID =
+ buf.slice(der.offset, der.offset + der.length);
+ der._offset += der.length;
+ }
+
+ /* extensions */
+ if (der.peek() === Local(3)) {
+ der.readSequence(Local(3));
+ var extEnd = der.offset + der.length;
+ der.readSequence();
+
+ while (der.offset < extEnd)
+ readExtension(cert, buf, der);
+
+ assert.strictEqual(der.offset, extEnd);
+ }
+
+ assert.strictEqual(der.offset, sigOffset);
+
+ der.readSequence();
+ after = der.offset + der.length;
+ var sigAlgOid = der.readOID();
+ var sigAlg = SIGN_ALGS[sigAlgOid];
+ if (sigAlg === undefined)
+ throw (new Error('unknown signature algorithm ' + sigAlgOid));
+ der._offset = after;
+
+ var sigData = der.readString(asn1.Ber.BitString, true);
+ if (sigData[0] === 0)
+ sigData = sigData.slice(1);
+ var algParts = sigAlg.split('-');
+
+ sig.signature = Signature.parse(sigData, algParts[0], 'asn1');
+ sig.signature.hashAlgorithm = algParts[1];
+ sig.algo = sigAlg;
+ sig.cache = buf.slice(tbsStart, tbsEnd);
+
+ return (new Certificate(cert));
+}
+
+function readDate(der) {
+ if (der.peek() === asn1.Ber.UTCTime) {
+ return (utcTimeToDate(der.readString(asn1.Ber.UTCTime)));
+ } else if (der.peek() === asn1.Ber.GeneralizedTime) {
+ return (gTimeToDate(der.readString(asn1.Ber.GeneralizedTime)));
+ } else {
+ throw (new Error('Unsupported date format'));
+ }
+}
+
+function writeDate(der, date) {
+ if (date.getUTCFullYear() >= 2050 || date.getUTCFullYear() < 1950) {
+ der.writeString(dateToGTime(date), asn1.Ber.GeneralizedTime);
+ } else {
+ der.writeString(dateToUTCTime(date), asn1.Ber.UTCTime);
+ }
+}
+
+/* RFC5280, section 4.2.1.6 (GeneralName type) */
+var ALTNAME = {
+ OtherName: Local(0),
+ RFC822Name: Context(1),
+ DNSName: Context(2),
+ X400Address: Local(3),
+ DirectoryName: Local(4),
+ EDIPartyName: Local(5),
+ URI: Context(6),
+ IPAddress: Context(7),
+ OID: Context(8)
+};
+
+/* RFC5280, section 4.2.1.12 (KeyPurposeId) */
+var EXTPURPOSE = {
+ 'serverAuth': '1.3.6.1.5.5.7.3.1',
+ 'clientAuth': '1.3.6.1.5.5.7.3.2',
+ 'codeSigning': '1.3.6.1.5.5.7.3.3',
+
+ /* See https://github.com/joyent/oid-docs/blob/master/root.md */
+ 'joyentDocker': '1.3.6.1.4.1.38678.1.4.1',
+ 'joyentCmon': '1.3.6.1.4.1.38678.1.4.2'
+};
+var EXTPURPOSE_REV = {};
+Object.keys(EXTPURPOSE).forEach(function (k) {
+ EXTPURPOSE_REV[EXTPURPOSE[k]] = k;
+});
+
+var KEYUSEBITS = [
+ 'signature', 'identity', 'keyEncryption',
+ 'encryption', 'keyAgreement', 'ca', 'crl'
+];
+
+function readExtension(cert, buf, der) {
+ der.readSequence();
+ var after = der.offset + der.length;
+ var extId = der.readOID();
+ var id;
+ var sig = cert.signatures.x509;
+ if (!sig.extras.exts)
+ sig.extras.exts = [];
+
+ var critical;
+ if (der.peek() === asn1.Ber.Boolean)
+ critical = der.readBoolean();
+
+ switch (extId) {
+ case (EXTS.basicConstraints):
+ der.readSequence(asn1.Ber.OctetString);
+ der.readSequence();
+ var bcEnd = der.offset + der.length;
+ var ca = false;
+ if (der.peek() === asn1.Ber.Boolean)
+ ca = der.readBoolean();
+ if (cert.purposes === undefined)
+ cert.purposes = [];
+ if (ca === true)
+ cert.purposes.push('ca');
+ var bc = { oid: extId, critical: critical };
+ if (der.offset < bcEnd && der.peek() === asn1.Ber.Integer)
+ bc.pathLen = der.readInt();
+ sig.extras.exts.push(bc);
+ break;
+ case (EXTS.extKeyUsage):
+ der.readSequence(asn1.Ber.OctetString);
+ der.readSequence();
+ if (cert.purposes === undefined)
+ cert.purposes = [];
+ var ekEnd = der.offset + der.length;
+ while (der.offset < ekEnd) {
+ var oid = der.readOID();
+ cert.purposes.push(EXTPURPOSE_REV[oid] || oid);
+ }
+ /*
+ * This is a bit of a hack: in the case where we have a cert
+ * that's only allowed to do serverAuth or clientAuth (and not
+ * the other), we want to make sure all our Subjects are of
+ * the right type. But we already parsed our Subjects and
+ * decided if they were hosts or users earlier (since it appears
+ * first in the cert).
+ *
+ * So we go through and mutate them into the right kind here if
+ * it doesn't match. This might not be hugely beneficial, as it
+ * seems that single-purpose certs are not often seen in the
+ * wild.
+ */
+ if (cert.purposes.indexOf('serverAuth') !== -1 &&
+ cert.purposes.indexOf('clientAuth') === -1) {
+ cert.subjects.forEach(function (ide) {
+ if (ide.type !== 'host') {
+ ide.type = 'host';
+ ide.hostname = ide.uid ||
+ ide.email ||
+ ide.components[0].value;
+ }
+ });
+ } else if (cert.purposes.indexOf('clientAuth') !== -1 &&
+ cert.purposes.indexOf('serverAuth') === -1) {
+ cert.subjects.forEach(function (ide) {
+ if (ide.type !== 'user') {
+ ide.type = 'user';
+ ide.uid = ide.hostname ||
+ ide.email ||
+ ide.components[0].value;
+ }
+ });
+ }
+ sig.extras.exts.push({ oid: extId, critical: critical });
+ break;
+ case (EXTS.keyUsage):
+ der.readSequence(asn1.Ber.OctetString);
+ var bits = der.readString(asn1.Ber.BitString, true);
+ var setBits = readBitField(bits, KEYUSEBITS);
+ setBits.forEach(function (bit) {
+ if (cert.purposes === undefined)
+ cert.purposes = [];
+ if (cert.purposes.indexOf(bit) === -1)
+ cert.purposes.push(bit);
+ });
+ sig.extras.exts.push({ oid: extId, critical: critical,
+ bits: bits });
+ break;
+ case (EXTS.altName):
+ der.readSequence(asn1.Ber.OctetString);
+ der.readSequence();
+ var aeEnd = der.offset + der.length;
+ while (der.offset < aeEnd) {
+ switch (der.peek()) {
+ case ALTNAME.OtherName:
+ case ALTNAME.EDIPartyName:
+ der.readSequence();
+ der._offset += der.length;
+ break;
+ case ALTNAME.OID:
+ der.readOID(ALTNAME.OID);
+ break;
+ case ALTNAME.RFC822Name:
+ /* RFC822 specifies email addresses */
+ var email = der.readString(ALTNAME.RFC822Name);
+ id = Identity.forEmail(email);
+ if (!cert.subjects[0].equals(id))
+ cert.subjects.push(id);
+ break;
+ case ALTNAME.DirectoryName:
+ der.readSequence(ALTNAME.DirectoryName);
+ id = Identity.parseAsn1(der);
+ if (!cert.subjects[0].equals(id))
+ cert.subjects.push(id);
+ break;
+ case ALTNAME.DNSName:
+ var host = der.readString(
+ ALTNAME.DNSName);
+ id = Identity.forHost(host);
+ if (!cert.subjects[0].equals(id))
+ cert.subjects.push(id);
+ break;
+ default:
+ der.readString(der.peek());
+ break;
+ }
+ }
+ sig.extras.exts.push({ oid: extId, critical: critical });
+ break;
+ default:
+ sig.extras.exts.push({
+ oid: extId,
+ critical: critical,
+ data: der.readString(asn1.Ber.OctetString, true)
+ });
+ break;
+ }
+
+ der._offset = after;
+}
+
+var UTCTIME_RE =
+ /^([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})?Z$/;
+function utcTimeToDate(t) {
+ var m = t.match(UTCTIME_RE);
+ assert.ok(m, 'timestamps must be in UTC');
+ var d = new Date();
+
+ var thisYear = d.getUTCFullYear();
+ var century = Math.floor(thisYear / 100) * 100;
+
+ var year = parseInt(m[1], 10);
+ if (thisYear % 100 < 50 && year >= 60)
+ year += (century - 1);
+ else
+ year += century;
+ d.setUTCFullYear(year, parseInt(m[2], 10) - 1, parseInt(m[3], 10));
+ d.setUTCHours(parseInt(m[4], 10), parseInt(m[5], 10));
+ if (m[6] && m[6].length > 0)
+ d.setUTCSeconds(parseInt(m[6], 10));
+ return (d);
+}
+
+var GTIME_RE =
+ /^([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})?Z$/;
+function gTimeToDate(t) {
+ var m = t.match(GTIME_RE);
+ assert.ok(m);
+ var d = new Date();
+
+ d.setUTCFullYear(parseInt(m[1], 10), parseInt(m[2], 10) - 1,
+ parseInt(m[3], 10));
+ d.setUTCHours(parseInt(m[4], 10), parseInt(m[5], 10));
+ if (m[6] && m[6].length > 0)
+ d.setUTCSeconds(parseInt(m[6], 10));
+ return (d);
+}
+
+function zeroPad(n, m) {
+ if (m === undefined)
+ m = 2;
+ var s = '' + n;
+ while (s.length < m)
+ s = '0' + s;
+ return (s);
+}
+
+function dateToUTCTime(d) {
+ var s = '';
+ s += zeroPad(d.getUTCFullYear() % 100);
+ s += zeroPad(d.getUTCMonth() + 1);
+ s += zeroPad(d.getUTCDate());
+ s += zeroPad(d.getUTCHours());
+ s += zeroPad(d.getUTCMinutes());
+ s += zeroPad(d.getUTCSeconds());
+ s += 'Z';
+ return (s);
+}
+
+function dateToGTime(d) {
+ var s = '';
+ s += zeroPad(d.getUTCFullYear(), 4);
+ s += zeroPad(d.getUTCMonth() + 1);
+ s += zeroPad(d.getUTCDate());
+ s += zeroPad(d.getUTCHours());
+ s += zeroPad(d.getUTCMinutes());
+ s += zeroPad(d.getUTCSeconds());
+ s += 'Z';
+ return (s);
+}
+
+function sign(cert, key) {
+ if (cert.signatures.x509 === undefined)
+ cert.signatures.x509 = {};
+ var sig = cert.signatures.x509;
+
+ sig.algo = key.type + '-' + key.defaultHashAlgorithm();
+ if (SIGN_ALGS[sig.algo] === undefined)
+ return (false);
+
+ var der = new asn1.BerWriter();
+ writeTBSCert(cert, der);
+ var blob = der.buffer;
+ sig.cache = blob;
+
+ var signer = key.createSign();
+ signer.write(blob);
+ cert.signatures.x509.signature = signer.sign();
+
+ return (true);
+}
+
+function signAsync(cert, signer, done) {
+ if (cert.signatures.x509 === undefined)
+ cert.signatures.x509 = {};
+ var sig = cert.signatures.x509;
+
+ var der = new asn1.BerWriter();
+ writeTBSCert(cert, der);
+ var blob = der.buffer;
+ sig.cache = blob;
+
+ signer(blob, function (err, signature) {
+ if (err) {
+ done(err);
+ return;
+ }
+ sig.algo = signature.type + '-' + signature.hashAlgorithm;
+ if (SIGN_ALGS[sig.algo] === undefined) {
+ done(new Error('Invalid signing algorithm "' +
+ sig.algo + '"'));
+ return;
+ }
+ sig.signature = signature;
+ done();
+ });
+}
+
+function write(cert, options) {
+ var sig = cert.signatures.x509;
+ assert.object(sig, 'x509 signature');
+
+ var der = new asn1.BerWriter();
+ der.startSequence();
+ if (sig.cache) {
+ der._ensure(sig.cache.length);
+ sig.cache.copy(der._buf, der._offset);
+ der._offset += sig.cache.length;
+ } else {
+ writeTBSCert(cert, der);
+ }
+
+ der.startSequence();
+ der.writeOID(SIGN_ALGS[sig.algo]);
+ if (sig.algo.match(/^rsa-/))
+ der.writeNull();
+ der.endSequence();
+
+ var sigData = sig.signature.toBuffer('asn1');
+ var data = Buffer.alloc(sigData.length + 1);
+ data[0] = 0;
+ sigData.copy(data, 1);
+ der.writeBuffer(data, asn1.Ber.BitString);
+ der.endSequence();
+
+ return (der.buffer);
+}
+
+function writeTBSCert(cert, der) {
+ var sig = cert.signatures.x509;
+ assert.object(sig, 'x509 signature');
+
+ der.startSequence();
+
+ der.startSequence(Local(0));
+ der.writeInt(2);
+ der.endSequence();
+
+ der.writeBuffer(utils.mpNormalize(cert.serial), asn1.Ber.Integer);
+
+ der.startSequence();
+ der.writeOID(SIGN_ALGS[sig.algo]);
+ if (sig.algo.match(/^rsa-/))
+ der.writeNull();
+ der.endSequence();
+
+ cert.issuer.toAsn1(der);
+
+ der.startSequence();
+ writeDate(der, cert.validFrom);
+ writeDate(der, cert.validUntil);
+ der.endSequence();
+
+ var subject = cert.subjects[0];
+ var altNames = cert.subjects.slice(1);
+ subject.toAsn1(der);
+
+ pkcs8.writePkcs8(der, cert.subjectKey);
+
+ if (sig.extras && sig.extras.issuerUniqueID) {
+ der.writeBuffer(sig.extras.issuerUniqueID, Local(1));
+ }
+
+ if (sig.extras && sig.extras.subjectUniqueID) {
+ der.writeBuffer(sig.extras.subjectUniqueID, Local(2));
+ }
+
+ if (altNames.length > 0 || subject.type === 'host' ||
+ (cert.purposes !== undefined && cert.purposes.length > 0) ||
+ (sig.extras && sig.extras.exts)) {
+ der.startSequence(Local(3));
+ der.startSequence();
+
+ var exts = [];
+ if (cert.purposes !== undefined && cert.purposes.length > 0) {
+ exts.push({
+ oid: EXTS.basicConstraints,
+ critical: true
+ });
+ exts.push({
+ oid: EXTS.keyUsage,
+ critical: true
+ });
+ exts.push({
+ oid: EXTS.extKeyUsage,
+ critical: true
+ });
+ }
+ exts.push({ oid: EXTS.altName });
+ if (sig.extras && sig.extras.exts)
+ exts = sig.extras.exts;
+
+ for (var i = 0; i < exts.length; ++i) {
+ der.startSequence();
+ der.writeOID(exts[i].oid);
+
+ if (exts[i].critical !== undefined)
+ der.writeBoolean(exts[i].critical);
+
+ if (exts[i].oid === EXTS.altName) {
+ der.startSequence(asn1.Ber.OctetString);
+ der.startSequence();
+ if (subject.type === 'host') {
+ der.writeString(subject.hostname,
+ Context(2));
+ }
+ for (var j = 0; j < altNames.length; ++j) {
+ if (altNames[j].type === 'host') {
+ der.writeString(
+ altNames[j].hostname,
+ ALTNAME.DNSName);
+ } else if (altNames[j].type ===
+ 'email') {
+ der.writeString(
+ altNames[j].email,
+ ALTNAME.RFC822Name);
+ } else {
+ /*
+ * Encode anything else as a
+ * DN style name for now.
+ */
+ der.startSequence(
+ ALTNAME.DirectoryName);
+ altNames[j].toAsn1(der);
+ der.endSequence();
+ }
+ }
+ der.endSequence();
+ der.endSequence();
+ } else if (exts[i].oid === EXTS.basicConstraints) {
+ der.startSequence(asn1.Ber.OctetString);
+ der.startSequence();
+ var ca = (cert.purposes.indexOf('ca') !== -1);
+ var pathLen = exts[i].pathLen;
+ der.writeBoolean(ca);
+ if (pathLen !== undefined)
+ der.writeInt(pathLen);
+ der.endSequence();
+ der.endSequence();
+ } else if (exts[i].oid === EXTS.extKeyUsage) {
+ der.startSequence(asn1.Ber.OctetString);
+ der.startSequence();
+ cert.purposes.forEach(function (purpose) {
+ if (purpose === 'ca')
+ return;
+ if (KEYUSEBITS.indexOf(purpose) !== -1)
+ return;
+ var oid = purpose;
+ if (EXTPURPOSE[purpose] !== undefined)
+ oid = EXTPURPOSE[purpose];
+ der.writeOID(oid);
+ });
+ der.endSequence();
+ der.endSequence();
+ } else if (exts[i].oid === EXTS.keyUsage) {
+ der.startSequence(asn1.Ber.OctetString);
+ /*
+ * If we parsed this certificate from a byte
+ * stream (i.e. we didn't generate it in sshpk)
+ * then we'll have a ".bits" property on the
+ * ext with the original raw byte contents.
+ *
+ * If we have this, use it here instead of
+ * regenerating it. This guarantees we output
+ * the same data we parsed, so signatures still
+ * validate.
+ */
+ if (exts[i].bits !== undefined) {
+ der.writeBuffer(exts[i].bits,
+ asn1.Ber.BitString);
+ } else {
+ var bits = writeBitField(cert.purposes,
+ KEYUSEBITS);
+ der.writeBuffer(bits,
+ asn1.Ber.BitString);
+ }
+ der.endSequence();
+ } else {
+ der.writeBuffer(exts[i].data,
+ asn1.Ber.OctetString);
+ }
+
+ der.endSequence();
+ }
+
+ der.endSequence();
+ der.endSequence();
+ }
+
+ der.endSequence();
+}
+
+/*
+ * Reads an ASN.1 BER bitfield out of the Buffer produced by doing
+ * `BerReader#readString(asn1.Ber.BitString)`. That function gives us the raw
+ * contents of the BitString tag, which is a count of unused bits followed by
+ * the bits as a right-padded byte string.
+ *
+ * `bits` is the Buffer, `bitIndex` should contain an array of string names
+ * for the bits in the string, ordered starting with bit #0 in the ASN.1 spec.
+ *
+ * Returns an array of Strings, the names of the bits that were set to 1.
+ */
+function readBitField(bits, bitIndex) {
+ var bitLen = 8 * (bits.length - 1) - bits[0];
+ var setBits = {};
+ for (var i = 0; i < bitLen; ++i) {
+ var byteN = 1 + Math.floor(i / 8);
+ var bit = 7 - (i % 8);
+ var mask = 1 << bit;
+ var bitVal = ((bits[byteN] & mask) !== 0);
+ var name = bitIndex[i];
+ if (bitVal && typeof (name) === 'string') {
+ setBits[name] = true;
+ }
+ }
+ return (Object.keys(setBits));
+}
+
+/*
+ * `setBits` is an array of strings, containing the names for each bit that
+ * sould be set to 1. `bitIndex` is same as in `readBitField()`.
+ *
+ * Returns a Buffer, ready to be written out with `BerWriter#writeString()`.
+ */
+function writeBitField(setBits, bitIndex) {
+ var bitLen = bitIndex.length;
+ var blen = Math.ceil(bitLen / 8);
+ var unused = blen * 8 - bitLen;
+ var bits = Buffer.alloc(1 + blen); // zero-filled
+ bits[0] = unused;
+ for (var i = 0; i < bitLen; ++i) {
+ var byteN = 1 + Math.floor(i / 8);
+ var bit = 7 - (i % 8);
+ var mask = 1 << bit;
+ var name = bitIndex[i];
+ if (name === undefined)
+ continue;
+ var bitVal = (setBits.indexOf(name) !== -1);
+ if (bitVal) {
+ bits[byteN] |= mask;
+ }
+ }
+ return (bits);
+}
diff --git a/node_modules/sshpk/lib/identity.js b/node_modules/sshpk/lib/identity.js
new file mode 100644
index 0000000..7d75b66
--- /dev/null
+++ b/node_modules/sshpk/lib/identity.js
@@ -0,0 +1,373 @@
+// Copyright 2017 Joyent, Inc.
+
+module.exports = Identity;
+
+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 asn1 = require('asn1');
+var Buffer = require('safer-buffer').Buffer;
+
+/*JSSTYLED*/
+var DNS_NAME_RE = /^([*]|[a-z0-9][a-z0-9\-]{0,62})(?:\.([*]|[a-z0-9][a-z0-9\-]{0,62}))*$/i;
+
+var oids = {};
+oids.cn = '2.5.4.3';
+oids.o = '2.5.4.10';
+oids.ou = '2.5.4.11';
+oids.l = '2.5.4.7';
+oids.s = '2.5.4.8';
+oids.c = '2.5.4.6';
+oids.sn = '2.5.4.4';
+oids.postalCode = '2.5.4.17';
+oids.serialNumber = '2.5.4.5';
+oids.street = '2.5.4.9';
+oids.x500UniqueIdentifier = '2.5.4.45';
+oids.role = '2.5.4.72';
+oids.telephoneNumber = '2.5.4.20';
+oids.description = '2.5.4.13';
+oids.dc = '0.9.2342.19200300.100.1.25';
+oids.uid = '0.9.2342.19200300.100.1.1';
+oids.mail = '0.9.2342.19200300.100.1.3';
+oids.title = '2.5.4.12';
+oids.gn = '2.5.4.42';
+oids.initials = '2.5.4.43';
+oids.pseudonym = '2.5.4.65';
+oids.emailAddress = '1.2.840.113549.1.9.1';
+
+var unoids = {};
+Object.keys(oids).forEach(function (k) {
+ unoids[oids[k]] = k;
+});
+
+function Identity(opts) {
+ var self = this;
+ assert.object(opts, 'options');
+ assert.arrayOfObject(opts.components, 'options.components');
+ this.components = opts.components;
+ this.componentLookup = {};
+ this.components.forEach(function (c) {
+ if (c.name && !c.oid)
+ c.oid = oids[c.name];
+ if (c.oid && !c.name)
+ c.name = unoids[c.oid];
+ if (self.componentLookup[c.name] === undefined)
+ self.componentLookup[c.name] = [];
+ self.componentLookup[c.name].push(c);
+ });
+ if (this.componentLookup.cn && this.componentLookup.cn.length > 0) {
+ this.cn = this.componentLookup.cn[0].value;
+ }
+ assert.optionalString(opts.type, 'options.type');
+ if (opts.type === undefined) {
+ if (this.components.length === 1 &&
+ this.componentLookup.cn &&
+ this.componentLookup.cn.length === 1 &&
+ this.componentLookup.cn[0].value.match(DNS_NAME_RE)) {
+ this.type = 'host';
+ this.hostname = this.componentLookup.cn[0].value;
+
+ } else if (this.componentLookup.dc &&
+ this.components.length === this.componentLookup.dc.length) {
+ this.type = 'host';
+ this.hostname = this.componentLookup.dc.map(
+ function (c) {
+ return (c.value);
+ }).join('.');
+
+ } else if (this.componentLookup.uid &&
+ this.components.length ===
+ this.componentLookup.uid.length) {
+ this.type = 'user';
+ this.uid = this.componentLookup.uid[0].value;
+
+ } else if (this.componentLookup.cn &&
+ this.componentLookup.cn.length === 1 &&
+ this.componentLookup.cn[0].value.match(DNS_NAME_RE)) {
+ this.type = 'host';
+ this.hostname = this.componentLookup.cn[0].value;
+
+ } else if (this.componentLookup.uid &&
+ this.componentLookup.uid.length === 1) {
+ this.type = 'user';
+ this.uid = this.componentLookup.uid[0].value;
+
+ } else if (this.componentLookup.mail &&
+ this.componentLookup.mail.length === 1) {
+ this.type = 'email';
+ this.email = this.componentLookup.mail[0].value;
+
+ } else if (this.componentLookup.cn &&
+ this.componentLookup.cn.length === 1) {
+ this.type = 'user';
+ this.uid = this.componentLookup.cn[0].value;
+
+ } else {
+ this.type = 'unknown';
+ }
+ } else {
+ this.type = opts.type;
+ if (this.type === 'host')
+ this.hostname = opts.hostname;
+ else if (this.type === 'user')
+ this.uid = opts.uid;
+ else if (this.type === 'email')
+ this.email = opts.email;
+ else
+ throw (new Error('Unknown type ' + this.type));
+ }
+}
+
+Identity.prototype.toString = function () {
+ return (this.components.map(function (c) {
+ var n = c.name.toUpperCase();
+ /*JSSTYLED*/
+ n = n.replace(/=/g, '\\=');
+ var v = c.value;
+ /*JSSTYLED*/
+ v = v.replace(/,/g, '\\,');
+ return (n + '=' + v);
+ }).join(', '));
+};
+
+Identity.prototype.get = function (name, asArray) {
+ assert.string(name, 'name');
+ var arr = this.componentLookup[name];
+ if (arr === undefined || arr.length === 0)
+ return (undefined);
+ if (!asArray && arr.length > 1)
+ throw (new Error('Multiple values for attribute ' + name));
+ if (!asArray)
+ return (arr[0].value);
+ return (arr.map(function (c) {
+ return (c.value);
+ }));
+};
+
+Identity.prototype.toArray = function (idx) {
+ return (this.components.map(function (c) {
+ return ({
+ name: c.name,
+ value: c.value
+ });
+ }));
+};
+
+/*
+ * These are from X.680 -- PrintableString allowed chars are in section 37.4
+ * table 8. Spec for IA5Strings is "1,6 + SPACE + DEL" where 1 refers to
+ * ISO IR #001 (standard ASCII control characters) and 6 refers to ISO IR #006
+ * (the basic ASCII character set).
+ */
+/* JSSTYLED */
+var NOT_PRINTABLE = /[^a-zA-Z0-9 '(),+.\/:=?-]/;
+/* JSSTYLED */
+var NOT_IA5 = /[^\x00-\x7f]/;
+
+Identity.prototype.toAsn1 = function (der, tag) {
+ der.startSequence(tag);
+ this.components.forEach(function (c) {
+ der.startSequence(asn1.Ber.Constructor | asn1.Ber.Set);
+ der.startSequence();
+ der.writeOID(c.oid);
+ /*
+ * If we fit in a PrintableString, use that. Otherwise use an
+ * IA5String or UTF8String.
+ *
+ * If this identity was parsed from a DN, use the ASN.1 types
+ * from the original representation (otherwise this might not
+ * be a full match for the original in some validators).
+ */
+ if (c.asn1type === asn1.Ber.Utf8String ||
+ c.value.match(NOT_IA5)) {
+ var v = Buffer.from(c.value, 'utf8');
+ der.writeBuffer(v, asn1.Ber.Utf8String);
+
+ } else if (c.asn1type === asn1.Ber.IA5String ||
+ c.value.match(NOT_PRINTABLE)) {
+ der.writeString(c.value, asn1.Ber.IA5String);
+
+ } else {
+ var type = asn1.Ber.PrintableString;
+ if (c.asn1type !== undefined)
+ type = c.asn1type;
+ der.writeString(c.value, type);
+ }
+ der.endSequence();
+ der.endSequence();
+ });
+ der.endSequence();
+};
+
+function globMatch(a, b) {
+ if (a === '**' || b === '**')
+ return (true);
+ var aParts = a.split('.');
+ var bParts = b.split('.');
+ if (aParts.length !== bParts.length)
+ return (false);
+ for (var i = 0; i < aParts.length; ++i) {
+ if (aParts[i] === '*' || bParts[i] === '*')
+ continue;
+ if (aParts[i] !== bParts[i])
+ return (false);
+ }
+ return (true);
+}
+
+Identity.prototype.equals = function (other) {
+ if (!Identity.isIdentity(other, [1, 0]))
+ return (false);
+ if (other.components.length !== this.components.length)
+ return (false);
+ for (var i = 0; i < this.components.length; ++i) {
+ if (this.components[i].oid !== other.components[i].oid)
+ return (false);
+ if (!globMatch(this.components[i].value,
+ other.components[i].value)) {
+ return (false);
+ }
+ }
+ return (true);
+};
+
+Identity.forHost = function (hostname) {
+ assert.string(hostname, 'hostname');
+ return (new Identity({
+ type: 'host',
+ hostname: hostname,
+ components: [ { name: 'cn', value: hostname } ]
+ }));
+};
+
+Identity.forUser = function (uid) {
+ assert.string(uid, 'uid');
+ return (new Identity({
+ type: 'user',
+ uid: uid,
+ components: [ { name: 'uid', value: uid } ]
+ }));
+};
+
+Identity.forEmail = function (email) {
+ assert.string(email, 'email');
+ return (new Identity({
+ type: 'email',
+ email: email,
+ components: [ { name: 'mail', value: email } ]
+ }));
+};
+
+Identity.parseDN = function (dn) {
+ assert.string(dn, 'dn');
+ var parts = [''];
+ var idx = 0;
+ var rem = dn;
+ while (rem.length > 0) {
+ var m;
+ /*JSSTYLED*/
+ if ((m = /^,/.exec(rem)) !== null) {
+ parts[++idx] = '';
+ rem = rem.slice(m[0].length);
+ /*JSSTYLED*/
+ } else if ((m = /^\\,/.exec(rem)) !== null) {
+ parts[idx] += ',';
+ rem = rem.slice(m[0].length);
+ /*JSSTYLED*/
+ } else if ((m = /^\\./.exec(rem)) !== null) {
+ parts[idx] += m[0];
+ rem = rem.slice(m[0].length);
+ /*JSSTYLED*/
+ } else if ((m = /^[^\\,]+/.exec(rem)) !== null) {
+ parts[idx] += m[0];
+ rem = rem.slice(m[0].length);
+ } else {
+ throw (new Error('Failed to parse DN'));
+ }
+ }
+ var cmps = parts.map(function (c) {
+ c = c.trim();
+ var eqPos = c.indexOf('=');
+ while (eqPos > 0 && c.charAt(eqPos - 1) === '\\')
+ eqPos = c.indexOf('=', eqPos + 1);
+ if (eqPos === -1) {
+ throw (new Error('Failed to parse DN'));
+ }
+ /*JSSTYLED*/
+ var name = c.slice(0, eqPos).toLowerCase().replace(/\\=/g, '=');
+ var value = c.slice(eqPos + 1);
+ return ({ name: name, value: value });
+ });
+ return (new Identity({ components: cmps }));
+};
+
+Identity.fromArray = function (components) {
+ assert.arrayOfObject(components, 'components');
+ components.forEach(function (cmp) {
+ assert.object(cmp, 'component');
+ assert.string(cmp.name, 'component.name');
+ if (!Buffer.isBuffer(cmp.value) &&
+ !(typeof (cmp.value) === 'string')) {
+ throw (new Error('Invalid component value'));
+ }
+ });
+ return (new Identity({ components: components }));
+};
+
+Identity.parseAsn1 = function (der, top) {
+ var components = [];
+ der.readSequence(top);
+ var end = der.offset + der.length;
+ while (der.offset < end) {
+ der.readSequence(asn1.Ber.Constructor | asn1.Ber.Set);
+ var after = der.offset + der.length;
+ der.readSequence();
+ var oid = der.readOID();
+ var type = der.peek();
+ var value;
+ switch (type) {
+ case asn1.Ber.PrintableString:
+ case asn1.Ber.IA5String:
+ case asn1.Ber.OctetString:
+ case asn1.Ber.T61String:
+ value = der.readString(type);
+ break;
+ case asn1.Ber.Utf8String:
+ value = der.readString(type, true);
+ value = value.toString('utf8');
+ break;
+ case asn1.Ber.CharacterString:
+ case asn1.Ber.BMPString:
+ value = der.readString(type, true);
+ value = value.toString('utf16le');
+ break;
+ default:
+ throw (new Error('Unknown asn1 type ' + type));
+ }
+ components.push({ oid: oid, asn1type: type, value: value });
+ der._offset = after;
+ }
+ der._offset = end;
+ return (new Identity({
+ components: components
+ }));
+};
+
+Identity.isIdentity = function (obj, ver) {
+ return (utils.isCompatible(obj, Identity, ver));
+};
+
+/*
+ * API versions for Identity:
+ * [1,0] -- initial ver
+ */
+Identity.prototype._sshpkApiVersion = [1, 0];
+
+Identity._oldVersionDetect = function (obj) {
+ return ([1, 0]);
+};
diff --git a/node_modules/sshpk/lib/index.js b/node_modules/sshpk/lib/index.js
new file mode 100644
index 0000000..f76db79
--- /dev/null
+++ b/node_modules/sshpk/lib/index.js
@@ -0,0 +1,40 @@
+// Copyright 2015 Joyent, Inc.
+
+var Key = require('./key');
+var Fingerprint = require('./fingerprint');
+var Signature = require('./signature');
+var PrivateKey = require('./private-key');
+var Certificate = require('./certificate');
+var Identity = require('./identity');
+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,
+ generatePrivateKey: PrivateKey.generate,
+ Certificate: Certificate,
+ parseCertificate: Certificate.parse,
+ createSelfSignedCertificate: Certificate.createSelfSigned,
+ createCertificate: Certificate.create,
+ Identity: Identity,
+ identityFromDN: Identity.parseDN,
+ identityForHost: Identity.forHost,
+ identityForUser: Identity.forUser,
+ identityForEmail: Identity.forEmail,
+ identityFromArray: Identity.fromArray,
+
+ /* errors */
+ FingerprintFormatError: errs.FingerprintFormatError,
+ InvalidAlgorithmError: errs.InvalidAlgorithmError,
+ KeyParseError: errs.KeyParseError,
+ SignatureParseError: errs.SignatureParseError,
+ KeyEncryptedError: errs.KeyEncryptedError,
+ CertificateParseError: errs.CertificateParseError
+};
diff --git a/node_modules/sshpk/lib/key.js b/node_modules/sshpk/lib/key.js
new file mode 100644
index 0000000..706f834
--- /dev/null
+++ b/node_modules/sshpk/lib/key.js
@@ -0,0 +1,294 @@
+// Copyright 2018 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').DiffieHellman;
+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'];
+formats['dnssec'] = require('./formats/dnssec');
+formats['putty'] = require('./formats/putty');
+formats['ppk'] = formats['putty'];
+
+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' || this.type === 'curve25519') {
+ 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, options) {
+ if (format === undefined)
+ format = 'ssh';
+ assert.string(format, 'format');
+ assert.object(formats[format], 'formats[format]');
+ assert.optionalObject(options, 'options');
+
+ if (format === 'rfc4253') {
+ if (this._rfc4253Cache === undefined)
+ this._rfc4253Cache = formats['rfc4253'].write(this);
+ return (this._rfc4253Cache);
+ }
+
+ return (formats[format].write(this, options));
+};
+
+Key.prototype.toString = function (format, options) {
+ return (this.toBuffer(format, options).toString());
+};
+
+Key.prototype.hash = function (algo, type) {
+ assert.string(algo, 'algorithm');
+ assert.optionalString(type, 'type');
+ if (type === undefined)
+ type = 'ssh';
+ algo = algo.toLowerCase();
+ if (algs.hashAlgs[algo] === undefined)
+ throw (new InvalidAlgorithmError(algo));
+
+ var cacheKey = algo + '||' + type;
+ if (this._hashCache[cacheKey])
+ return (this._hashCache[cacheKey]);
+
+ var buf;
+ if (type === 'ssh') {
+ buf = this.toBuffer('rfc4253');
+ } else if (type === 'spki') {
+ buf = formats.pkcs8.pkcs8ToBuffer(this);
+ } else {
+ throw (new Error('Hash type ' + type + ' not supported'));
+ }
+ var hash = crypto.createHash(algo).update(buf).digest();
+ this._hashCache[cacheKey] = hash;
+ return (hash);
+};
+
+Key.prototype.fingerprint = function (algo, type) {
+ if (algo === undefined)
+ algo = 'sha256';
+ if (type === undefined)
+ type = 'ssh';
+ assert.string(algo, 'algorithm');
+ assert.string(type, 'type');
+ var opts = {
+ type: 'key',
+ hash: this.hash(algo, type),
+ algorithm: algo,
+ hashType: type
+ };
+ 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 = 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');
+ var curve = this.curve;
+ var self = this;
+ v.verify = function (signature, fmt) {
+ if (Signature.isSignature(signature, [2, 0])) {
+ if (signature.type !== self.type)
+ return (false);
+ if (signature.hashAlgorithm &&
+ signature.hashAlgorithm !== hashAlgo)
+ return (false);
+ if (signature.curve && self.type === 'ecdsa' &&
+ signature.curve !== curve)
+ return (false);
+ return (oldVerify(key, signature.toBuffer('asn1')));
+
+ } else if (typeof (signature) === 'string' ||
+ 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, options) {
+ if (typeof (data) !== 'string')
+ assert.buffer(data, 'data');
+ if (format === undefined)
+ format = 'auto';
+ assert.string(format, 'format');
+ if (typeof (options) === 'string')
+ options = { filename: options };
+ assert.optionalObject(options, 'options');
+ if (options === undefined)
+ options = {};
+ assert.optionalString(options.filename, 'options.filename');
+ if (options.filename === undefined)
+ options.filename = '(unnamed)';
+
+ assert.object(formats[format], 'formats[format]');
+
+ try {
+ var k = formats[format].read(data, options);
+ if (k instanceof PrivateKey)
+ k = k.toPublic();
+ if (!k.comment)
+ k.comment = options.filename;
+ return (k);
+ } catch (e) {
+ if (e.name === 'KeyEncryptedError')
+ throw (e);
+ throw (new KeyParseError(options.filename, 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
+ * [1,6] -- changed ed25519 part names
+ * [1,7] -- spki hash types
+ */
+Key.prototype._sshpkApiVersion = [1, 7];
+
+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]);
+};
diff --git a/node_modules/sshpk/lib/private-key.js b/node_modules/sshpk/lib/private-key.js
new file mode 100644
index 0000000..5600838
--- /dev/null
+++ b/node_modules/sshpk/lib/private-key.js
@@ -0,0 +1,246 @@
+// Copyright 2017 Joyent, Inc.
+
+module.exports = PrivateKey;
+
+var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
+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 dhe = require('./dhe');
+var generateECDSA = dhe.generateECDSA;
+var generateED25519 = dhe.generateED25519;
+var edCompat = require('./ed-compat');
+var nacl = require('tweetnacl');
+
+var Key = require('./key');
+
+var InvalidAlgorithmError = errs.InvalidAlgorithmError;
+var KeyParseError = errs.KeyParseError;
+var KeyEncryptedError = errs.KeyEncryptedError;
+
+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'];
+formats['dnssec'] = require('./formats/dnssec');
+
+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, options) {
+ if (format === undefined)
+ format = 'pkcs1';
+ assert.string(format, 'format');
+ assert.object(formats[format], 'formats[format]');
+ assert.optionalObject(options, 'options');
+
+ return (formats[format].write(this, options));
+};
+
+PrivateKey.prototype.hash = function (algo, type) {
+ return (this.toPublic().hash(algo, type));
+};
+
+PrivateKey.prototype.fingerprint = function (algo, type) {
+ return (this.toPublic().fingerprint(algo, type));
+};
+
+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) {
+ assert.string(newType, 'type');
+ var priv, pub, pair;
+
+ if (this.type === 'ed25519' && newType === 'curve25519') {
+ priv = this.part.k.data;
+ if (priv[0] === 0x00)
+ priv = priv.slice(1);
+
+ pair = nacl.box.keyPair.fromSecretKey(new Uint8Array(priv));
+ pub = Buffer.from(pair.publicKey);
+
+ return (new PrivateKey({
+ type: 'curve25519',
+ parts: [
+ { name: 'A', data: utils.mpNormalize(pub) },
+ { name: 'k', data: utils.mpNormalize(priv) }
+ ]
+ }));
+ } else if (this.type === 'curve25519' && newType === 'ed25519') {
+ priv = this.part.k.data;
+ if (priv[0] === 0x00)
+ priv = priv.slice(1);
+
+ pair = nacl.sign.keyPair.fromSeed(new Uint8Array(priv));
+ pub = Buffer.from(pair.publicKey);
+
+ return (new PrivateKey({
+ type: 'ed25519',
+ parts: [
+ { name: 'A', data: utils.mpNormalize(pub) },
+ { name: 'k', data: utils.mpNormalize(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 = 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;
+ var curve = this.curve;
+ v.sign = function () {
+ var sig = oldSign(key);
+ if (typeof (sig) === 'string')
+ sig = Buffer.from(sig, 'binary');
+ sig = Signature.parse(sig, type, 'asn1');
+ sig.hashAlgorithm = hashAlgo;
+ sig.curve = curve;
+ return (sig);
+ };
+ return (v);
+};
+
+PrivateKey.parse = function (data, format, options) {
+ if (typeof (data) !== 'string')
+ assert.buffer(data, 'data');
+ if (format === undefined)
+ format = 'auto';
+ assert.string(format, 'format');
+ if (typeof (options) === 'string')
+ options = { filename: options };
+ assert.optionalObject(options, 'options');
+ if (options === undefined)
+ options = {};
+ assert.optionalString(options.filename, 'options.filename');
+ if (options.filename === undefined)
+ options.filename = '(unnamed)';
+
+ assert.object(formats[format], 'formats[format]');
+
+ try {
+ var k = formats[format].read(data, options);
+ assert.ok(k instanceof PrivateKey, 'key is not a private key');
+ if (!k.comment)
+ k.comment = options.filename;
+ return (k);
+ } catch (e) {
+ if (e.name === 'KeyEncryptedError')
+ throw (e);
+ throw (new KeyParseError(options.filename, format, e));
+ }
+};
+
+PrivateKey.isPrivateKey = function (obj, ver) {
+ return (utils.isCompatible(obj, PrivateKey, ver));
+};
+
+PrivateKey.generate = function (type, options) {
+ if (options === undefined)
+ options = {};
+ assert.object(options, 'options');
+
+ switch (type) {
+ case 'ecdsa':
+ if (options.curve === undefined)
+ options.curve = 'nistp256';
+ assert.string(options.curve, 'options.curve');
+ return (generateECDSA(options.curve));
+ case 'ed25519':
+ return (generateED25519());
+ default:
+ throw (new Error('Key generation not supported with key ' +
+ 'type "' + type + '"'));
+ }
+};
+
+/*
+ * API versions for PrivateKey:
+ * [1,0] -- initial ver
+ * [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
+ * [1,5] -- changed ed25519 part names and format
+ * [1,6] -- type arguments for hash() and fingerprint()
+ */
+PrivateKey.prototype._sshpkApiVersion = [1, 6];
+
+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]);
+};
diff --git a/node_modules/sshpk/lib/signature.js b/node_modules/sshpk/lib/signature.js
new file mode 100644
index 0000000..aa8fdbb
--- /dev/null
+++ b/node_modules/sshpk/lib/signature.js
@@ -0,0 +1,314 @@
+// Copyright 2015 Joyent, Inc.
+
+module.exports = Signature;
+
+var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
+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.curve = opts.curve;
+ this.parts = opts.parts;
+ this.part = partLookup;
+}
+
+Signature.prototype.toBuffer = function (format) {
+ if (format === undefined)
+ format = 'asn1';
+ assert.string(format, 'format');
+
+ var buf;
+ var stype = 'ssh-' + this.type;
+
+ switch (this.type) {
+ case 'rsa':
+ switch (this.hashAlgorithm) {
+ case 'sha256':
+ stype = 'rsa-sha2-256';
+ break;
+ case 'sha512':
+ stype = 'rsa-sha2-512';
+ break;
+ case 'sha1':
+ case undefined:
+ break;
+ default:
+ throw (new Error('SSH signature ' +
+ 'format does not support hash ' +
+ 'algorithm ' + this.hashAlgorithm));
+ }
+ if (format === 'ssh') {
+ buf = new SSHBuffer({});
+ buf.writeString(stype);
+ buf.writePart(this.part.sig);
+ return (buf.toBuffer());
+ } else {
+ return (this.part.sig.data);
+ }
+ break;
+
+ case 'ed25519':
+ if (format === 'ssh') {
+ buf = new SSHBuffer({});
+ buf.writeString(stype);
+ buf.writePart(this.part.sig);
+ return (buf.toBuffer());
+ } else {
+ return (this.part.sig.data);
+ }
+ break;
+
+ 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.length > 20 && r[0] === 0x00)
+ r = r.slice(1);
+ s = this.part.s.data;
+ if (s.length > 20 && s[0] === 0x00)
+ s = s.slice(1);
+ if ((this.hashAlgorithm &&
+ this.hashAlgorithm !== 'sha1') ||
+ r.length + s.length !== 40) {
+ throw (new Error('OpenSSH only supports ' +
+ 'DSA signatures with SHA1 hash'));
+ }
+ buf.writeBuffer(Buffer.concat([r, s]));
+ return (buf.toBuffer());
+ } else if (format === 'ssh' && this.type === 'ecdsa') {
+ var inner = new SSHBuffer({});
+ r = this.part.r.data;
+ inner.writeBuffer(r);
+ inner.writePart(this.part.s);
+
+ buf = new SSHBuffer({});
+ /* XXX: find a more proper way to do this? */
+ var curve;
+ if (r[0] === 0x00)
+ r = r.slice(1);
+ var sz = r.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 = Buffer.from(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));
+ case 'ed25519':
+ return (parseOneNum(data, type, format, opts));
+
+ 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) {
+ if (format === 'ssh') {
+ try {
+ var buf = new SSHBuffer({buffer: data});
+ var head = buf.readString();
+ } catch (e) {
+ /* fall through */
+ }
+ if (buf !== undefined) {
+ var msg = 'SSH signature does not match expected ' +
+ 'type (expected ' + type + ', got ' + head + ')';
+ switch (head) {
+ case 'ssh-rsa':
+ assert.strictEqual(type, 'rsa', msg);
+ opts.hashAlgo = 'sha1';
+ break;
+ case 'rsa-sha2-256':
+ assert.strictEqual(type, 'rsa', msg);
+ opts.hashAlgo = 'sha256';
+ break;
+ case 'rsa-sha2-512':
+ assert.strictEqual(type, 'rsa', msg);
+ opts.hashAlgo = 'sha512';
+ break;
+ case 'ssh-ed25519':
+ assert.strictEqual(type, 'ed25519', msg);
+ opts.hashAlgo = 'sha512';
+ break;
+ default:
+ throw (new Error('Unknown SSH signature ' +
+ 'type: ' + head));
+ }
+ var sig = buf.readPart();
+ assert.ok(buf.atEnd(), 'extra trailing bytes');
+ sig.name = 'sig';
+ 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();
+ var stype = inner.toString('ascii');
+ if (stype.slice(0, 6) === 'ecdsa-') {
+ var parts = stype.split('-');
+ assert.strictEqual(parts[0], 'ecdsa');
+ assert.strictEqual(parts[1], 'sha2');
+ opts.curve = parts[2];
+ switch (opts.curve) {
+ case 'nistp256':
+ opts.hashAlgo = 'sha256';
+ break;
+ case 'nistp384':
+ opts.hashAlgo = 'sha384';
+ break;
+ case 'nistp521':
+ opts.hashAlgo = 'sha512';
+ break;
+ default:
+ throw (new Error('Unsupported ECDSA curve: ' +
+ opts.curve));
+ }
+ inner = buf.readBuffer();
+ assert.ok(buf.atEnd(), 'extra trailing bytes on outer');
+ buf = new SSHBuffer({buffer: inner});
+ 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]);
+};
diff --git a/node_modules/sshpk/lib/ssh-buffer.js b/node_modules/sshpk/lib/ssh-buffer.js
new file mode 100644
index 0000000..1dd286c
--- /dev/null
+++ b/node_modules/sshpk/lib/ssh-buffer.js
@@ -0,0 +1,149 @@
+// Copyright 2015 Joyent, Inc.
+
+module.exports = SSHBuffer;
+
+var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
+
+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 || Buffer.alloc(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 = Buffer.alloc(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) +
+ ' (data truncated?)');
+ 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.readInt64 = function () {
+ assert.ok(this._offset + 8 < this._buffer.length,
+ 'buffer not long enough to read Int64');
+ var v = this._buffer.slice(this._offset, this._offset + 8);
+ this._offset += 8;
+ 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(Buffer.from(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.writeInt64 = function (v) {
+ assert.buffer(v, 'value');
+ if (v.length > 8) {
+ var lead = v.slice(0, v.length - 8);
+ for (var i = 0; i < lead.length; ++i) {
+ assert.strictEqual(lead[i], 0,
+ 'must fit in 64 bits of precision');
+ }
+ v = v.slice(v.length - 8, v.length);
+ }
+ while (this._offset + 8 > this._size)
+ this.expand();
+ v.copy(this._buffer, this._offset);
+ this._offset += 8;
+};
+
+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;
+};
diff --git a/node_modules/sshpk/lib/utils.js b/node_modules/sshpk/lib/utils.js
new file mode 100644
index 0000000..6b83a32
--- /dev/null
+++ b/node_modules/sshpk/lib/utils.js
@@ -0,0 +1,404 @@
+// Copyright 2015 Joyent, Inc.
+
+module.exports = {
+ bufferSplit: bufferSplit,
+ addRSAMissing: addRSAMissing,
+ calculateDSAPublic: calculateDSAPublic,
+ calculateED25519Public: calculateED25519Public,
+ calculateX25519Public: calculateX25519Public,
+ mpNormalize: mpNormalize,
+ mpDenormalize: mpDenormalize,
+ ecNormalize: ecNormalize,
+ countZeros: countZeros,
+ assertCompatible: assertCompatible,
+ isCompatible: isCompatible,
+ opensslKeyDeriv: opensslKeyDeriv,
+ opensshCipherInfo: opensshCipherInfo,
+ publicFromPrivateECDSA: publicFromPrivateECDSA,
+ zeroPadToLength: zeroPadToLength,
+ writeBitString: writeBitString,
+ readBitString: readBitString,
+ pbkdf2: pbkdf2
+};
+
+var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
+var PrivateKey = require('./private-key');
+var Key = require('./key');
+var crypto = require('crypto');
+var algs = require('./algs');
+var asn1 = require('asn1');
+
+var ec = require('ecc-jsbn/lib/ec');
+var jsbn = require('jsbn').BigInteger;
+var nacl = require('tweetnacl');
+
+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]);
+}
+
+var CIPHER_LEN = {
+ 'des-ede3-cbc': { key: 24, iv: 8 },
+ 'aes-128-cbc': { key: 16, iv: 16 },
+ 'aes-256-cbc': { key: 32, iv: 16 }
+};
+var PKCS5_SALT_LEN = 8;
+
+function opensslKeyDeriv(cipher, salt, passphrase, count) {
+ assert.buffer(salt, 'salt');
+ assert.buffer(passphrase, 'passphrase');
+ assert.number(count, 'iteration count');
+
+ var clen = CIPHER_LEN[cipher];
+ assert.object(clen, 'supported cipher');
+
+ salt = salt.slice(0, PKCS5_SALT_LEN);
+
+ var D, D_prev, bufs;
+ var material = Buffer.alloc(0);
+ while (material.length < clen.key + clen.iv) {
+ bufs = [];
+ if (D_prev)
+ bufs.push(D_prev);
+ bufs.push(passphrase);
+ bufs.push(salt);
+ D = Buffer.concat(bufs);
+ for (var j = 0; j < count; ++j)
+ D = crypto.createHash('md5').update(D).digest();
+ material = Buffer.concat([material, D]);
+ D_prev = D;
+ }
+
+ return ({
+ key: material.slice(0, clen.key),
+ iv: material.slice(clen.key, clen.key + clen.iv)
+ });
+}
+
+/* See: RFC2898 */
+function pbkdf2(hashAlg, salt, iterations, size, passphrase) {
+ var hkey = Buffer.alloc(salt.length + 4);
+ salt.copy(hkey);
+
+ var gen = 0, ts = [];
+ var i = 1;
+ while (gen < size) {
+ var t = T(i++);
+ gen += t.length;
+ ts.push(t);
+ }
+ return (Buffer.concat(ts).slice(0, size));
+
+ function T(I) {
+ hkey.writeUInt32BE(I, hkey.length - 4);
+
+ var hmac = crypto.createHmac(hashAlg, passphrase);
+ hmac.update(hkey);
+
+ var Ti = hmac.digest();
+ var Uc = Ti;
+ var c = 1;
+ while (c++ < iterations) {
+ hmac = crypto.createHmac(hashAlg, passphrase);
+ hmac.update(Uc);
+ Uc = hmac.digest();
+ for (var x = 0; x < Ti.length; ++x)
+ Ti[x] ^= Uc[x];
+ }
+ return (Ti);
+ }
+}
+
+/* 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 = Buffer.alloc(buf.length + 1);
+ b[0] = 0x0;
+ buf.copy(b, 1);
+ return (b);
+}
+
+function readBitString(der, tag) {
+ if (tag === undefined)
+ tag = asn1.Ber.BitString;
+ var buf = der.readString(tag, true);
+ assert.strictEqual(buf[0], 0x00, 'bit strings with unused bits are ' +
+ 'not supported (0x' + buf[0].toString(16) + ')');
+ return (buf.slice(1));
+}
+
+function writeBitString(der, buf, tag) {
+ if (tag === undefined)
+ tag = asn1.Ber.BitString;
+ var b = Buffer.alloc(buf.length + 1);
+ b[0] = 0x00;
+ buf.copy(b, 1);
+ der.writeBuffer(b, tag);
+}
+
+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 = Buffer.alloc(buf.length + 1);
+ b[0] = 0x00;
+ buf.copy(b, 1);
+ buf = b;
+ }
+ return (buf);
+}
+
+function mpDenormalize(buf) {
+ assert.buffer(buf);
+ while (buf.length > 1 && buf[0] === 0x00)
+ buf = buf.slice(1);
+ return (buf);
+}
+
+function zeroPadToLength(buf, len) {
+ assert.buffer(buf);
+ assert.number(len);
+ while (buf.length > len) {
+ assert.equal(buf[0], 0x00);
+ buf = buf.slice(1);
+ }
+ while (buf.length < len) {
+ var b = Buffer.alloc(buf.length + 1);
+ b[0] = 0x00;
+ buf.copy(b, 1);
+ buf = b;
+ }
+ return (buf);
+}
+
+function bigintToMpBuf(bigint) {
+ var buf = Buffer.from(bigint.toByteArray());
+ buf = mpNormalize(buf);
+ return (buf);
+}
+
+function calculateDSAPublic(g, p, x) {
+ assert.buffer(g);
+ assert.buffer(p);
+ assert.buffer(x);
+ g = new jsbn(g);
+ p = new jsbn(p);
+ x = new jsbn(x);
+ var y = g.modPow(x, p);
+ var ybuf = bigintToMpBuf(y);
+ return (ybuf);
+}
+
+function calculateED25519Public(k) {
+ assert.buffer(k);
+
+ var kp = nacl.sign.keyPair.fromSeed(new Uint8Array(k));
+ return (Buffer.from(kp.publicKey));
+}
+
+function calculateX25519Public(k) {
+ assert.buffer(k);
+
+ var kp = nacl.box.keyPair.fromSeed(new Uint8Array(k));
+ return (Buffer.from(kp.publicKey));
+}
+
+function addRSAMissing(key) {
+ assert.object(key);
+ assertCompatible(key, PrivateKey, [1, 1]);
+
+ var d = new jsbn(key.part.d.data);
+ var buf;
+
+ if (!key.part.dmodp) {
+ var p = new jsbn(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 jsbn(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);
+ }
+}
+
+function publicFromPrivateECDSA(curveName, priv) {
+ assert.string(curveName, 'curveName');
+ assert.buffer(priv);
+ var params = algs.curves[curveName];
+ var p = new jsbn(params.p);
+ var a = new jsbn(params.a);
+ var b = new jsbn(params.b);
+ var curve = new ec.ECCurveFp(p, a, b);
+ var G = curve.decodePointHex(params.G.toString('hex'));
+
+ var d = new jsbn(mpNormalize(priv));
+ var pub = G.multiply(d);
+ pub = Buffer.from(curve.encodePointHex(pub), 'hex');
+
+ var parts = [];
+ parts.push({name: 'curve', data: Buffer.from(curveName)});
+ parts.push({name: 'Q', data: pub});
+
+ var key = new Key({type: 'ecdsa', curve: curve, parts: parts});
+ return (key);
+}
+
+function opensshCipherInfo(cipher) {
+ var inf = {};
+ switch (cipher) {
+ case '3des-cbc':
+ inf.keySize = 24;
+ inf.blockSize = 8;
+ inf.opensslName = 'des-ede3-cbc';
+ break;
+ case 'blowfish-cbc':
+ inf.keySize = 16;
+ inf.blockSize = 8;
+ inf.opensslName = 'bf-cbc';
+ break;
+ case 'aes128-cbc':
+ case 'aes128-ctr':
+ case 'aes128-gcm@openssh.com':
+ inf.keySize = 16;
+ inf.blockSize = 16;
+ inf.opensslName = 'aes-128-' + cipher.slice(7, 10);
+ break;
+ case 'aes192-cbc':
+ case 'aes192-ctr':
+ case 'aes192-gcm@openssh.com':
+ inf.keySize = 24;
+ inf.blockSize = 16;
+ inf.opensslName = 'aes-192-' + cipher.slice(7, 10);
+ break;
+ case 'aes256-cbc':
+ case 'aes256-ctr':
+ case 'aes256-gcm@openssh.com':
+ inf.keySize = 32;
+ inf.blockSize = 16;
+ inf.opensslName = 'aes-256-' + cipher.slice(7, 10);
+ break;
+ default:
+ throw (new Error(
+ 'Unsupported openssl cipher "' + cipher + '"'));
+ }
+ return (inf);
+}
diff --git a/node_modules/sshpk/man/man1/sshpk-conv.1 b/node_modules/sshpk/man/man1/sshpk-conv.1
new file mode 100644
index 0000000..0887dce
--- /dev/null
+++ b/node_modules/sshpk/man/man1/sshpk-conv.1
@@ -0,0 +1,135 @@
+.TH sshpk\-conv 1 "Jan 2016" sshpk "sshpk Commands"
+.SH NAME
+.PP
+sshpk\-conv \- convert between key formats
+.SH SYNOPSYS
+.PP
+\fB\fCsshpk\-conv\fR \-t FORMAT [FILENAME] [OPTIONS...]
+.PP
+\fB\fCsshpk\-conv\fR \-i [FILENAME] [OPTIONS...]
+.SH DESCRIPTION
+.PP
+Reads in a public or private key and converts it between different formats,
+particularly formats used in the SSH protocol and the well\-known PEM PKCS#1/7
+formats.
+.PP
+In the second form, with the \fB\fC\-i\fR option given, identifies a key and prints to
+stderr information about its nature, size and fingerprint.
+.SH EXAMPLES
+.PP
+Assume the following SSH\-format public key in \fB\fCid_ecdsa.pub\fR:
+.PP
+.RS
+.nf
+ecdsa\-sha2\-nistp256 AAAAE2VjZHNhLXNoYTI...9M/4c4= user@host
+.fi
+.RE
+.PP
+Identify it with \fB\fC\-i\fR:
+.PP
+.RS
+.nf
+$ sshpk\-conv \-i id_ecdsa.pub
+id_ecdsa: a 256 bit ECDSA public key
+ECDSA curve: nistp256
+Comment: user@host
+Fingerprint:
+ SHA256:vCNX7eUkdvqqW0m4PoxQAZRv+CM4P4fS8+CbliAvS4k
+ 81:ad:d5:57:e5:6f:7d:a2:93:79:56:af:d7:c0:38:51
+.fi
+.RE
+.PP
+Convert it to \fB\fCpkcs8\fR format, for use with e.g. OpenSSL:
+.PP
+.RS
+.nf
+$ sshpk\-conv \-t pkcs8 id_ecdsa
+\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAsA4R6N6AS3gzaPBeLjG2ObSgUsR
+zOt+kWJoijLnw3ZMYUKmAx+lD0I5XUxdrPcs1vH5f3cn9TvRvO9L0z/hzg==
+\-\-\-\-\-END PUBLIC KEY\-\-\-\-\-
+.fi
+.RE
+.PP
+Retrieve the public half of a private key:
+.PP
+.RS
+.nf
+$ openssl genrsa 2048 | sshpk\-conv \-t ssh \-c foo@bar
+ssh\-rsa AAAAB3NzaC1yc2EAAA...koK7 foo@bar
+.fi
+.RE
+.PP
+Convert a private key to PKCS#1 (OpenSSL) format from a new\-style OpenSSH key
+format (the \fB\fCssh\-keygen \-o\fR format):
+.PP
+.RS
+.nf
+$ ssh\-keygen \-o \-f foobar
+\&...
+$ sshpk\-conv \-p \-t pkcs1 foobar
+\-\-\-\-\-BEGIN RSA PRIVATE KEY\-\-\-\-\-
+MIIDpAIBAAKCAQEA6T/GYJndb1TRH3+NL....
+\-\-\-\-\-END RSA PRIVATE KEY\-\-\-\-\-
+.fi
+.RE
+.SH OPTIONS
+.TP
+\fB\fC\-i, \-\-identify\fR
+Instead of converting the key, output identifying information about it to
+stderr, including its type, size and fingerprints.
+.TP
+\fB\fC\-p, \-\-private\fR
+Treat the key as a private key instead of a public key (the default). If you
+supply \fB\fCsshpk\-conv\fR with a private key and do not give this option, it will
+extract only the public half of the key from it and work with that.
+.TP
+\fB\fC\-f PATH, \-\-file=PATH\fR
+Input file to take the key from instead of stdin. If a filename is supplied
+as a positional argument, it is equivalent to using this option.
+.TP
+\fB\fC\-o PATH, \-\-out=PATH\fR
+Output file name to use instead of stdout.
+.PP
+\fB\fC\-T FORMAT, \-\-informat=FORMAT\fR
+.TP
+\fB\fC\-t FORMAT, \-\-outformat=FORMAT\fR
+Selects the input and output formats to be used (see FORMATS, below).
+.TP
+\fB\fC\-c TEXT, \-\-comment=TEXT\fR
+Sets the key comment for the output file, if supported.
+.SH FORMATS
+.PP
+Currently supported formats:
+.TP
+\fB\fCpem, pkcs1\fR
+The standard PEM format used by older OpenSSH and most TLS libraries such as
+OpenSSL. The classic \fB\fCid_rsa\fR file is usually in this format. It is an ASN.1
+encoded structure, base64\-encoded and placed between PEM headers.
+.TP
+\fB\fCssh\fR
+The SSH public key text format (the format of an \fB\fCid_rsa.pub\fR file). A single
+line, containing 3 space separated parts: the key type, key body and optional
+key comment.
+.TP
+\fB\fCpkcs8\fR
+A newer PEM format, usually used only for public keys by TLS libraries such
+as OpenSSL. The ASN.1 structure is more generic than that of \fB\fCpkcs1\fR\&.
+.TP
+\fB\fCopenssh\fR
+The new \fB\fCssh\-keygen \-o\fR format from OpenSSH. This can be mistaken for a PEM
+encoding but is actually an OpenSSH internal format.
+.TP
+\fB\fCrfc4253\fR
+The internal binary format of keys when sent over the wire in the SSH
+protocol. This is also the format that the \fB\fCssh\-agent\fR uses in its protocol.
+.SH SEE ALSO
+.PP
+.BR ssh-keygen (1),
+.BR openssl (1)
+.SH BUGS
+.PP
+Encrypted (password\-protected) keys are not supported.
+.PP
+Report bugs at Github
+\[la]https://github.com/arekinath/node-sshpk/issues\[ra]
diff --git a/node_modules/sshpk/man/man1/sshpk-sign.1 b/node_modules/sshpk/man/man1/sshpk-sign.1
new file mode 100644
index 0000000..749916b
--- /dev/null
+++ b/node_modules/sshpk/man/man1/sshpk-sign.1
@@ -0,0 +1,81 @@
+.TH sshpk\-sign 1 "Jan 2016" sshpk "sshpk Commands"
+.SH NAME
+.PP
+sshpk\-sign \- sign data using an SSH key
+.SH SYNOPSYS
+.PP
+\fB\fCsshpk\-sign\fR \-i KEYPATH [OPTION...]
+.SH DESCRIPTION
+.PP
+Takes in arbitrary bytes, and signs them using an SSH private key. The key can
+be of any type or format supported by the \fB\fCsshpk\fR library, including the
+standard OpenSSH formats, as well as PEM PKCS#1 and PKCS#8.
+.PP
+The signature is printed out in Base64 encoding, unless the \fB\fC\-\-binary\fR or \fB\fC\-b\fR
+option is given.
+.SH EXAMPLES
+.PP
+Signing with default settings:
+.PP
+.RS
+.nf
+$ printf 'foo' | sshpk\-sign \-i ~/.ssh/id_ecdsa
+MEUCIAMdLS/vXrrtWFepwe...
+.fi
+.RE
+.PP
+Signing in SSH (RFC 4253) format (rather than the default ASN.1):
+.PP
+.RS
+.nf
+$ printf 'foo' | sshpk\-sign \-i ~/.ssh/id_ecdsa \-t ssh
+AAAAFGVjZHNhLXNoYTIt...
+.fi
+.RE
+.PP
+Saving the binary signature to a file:
+.PP
+.RS
+.nf
+$ printf 'foo' | sshpk\-sign \-i ~/.ssh/id_ecdsa \\
+ \-o signature.bin \-b
+$ cat signature.bin | base64
+MEUCIAMdLS/vXrrtWFepwe...
+.fi
+.RE
+.SH OPTIONS
+.TP
+\fB\fC\-v, \-\-verbose\fR
+Print extra information about the key and signature to stderr when signing.
+.TP
+\fB\fC\-b, \-\-binary\fR
+Don't base64\-encode the signature before outputting it.
+.TP
+\fB\fC\-i KEY, \-\-identity=KEY\fR
+Select the key to be used for signing. \fB\fCKEY\fR must be a relative or absolute
+filesystem path to the key file. Any format supported by the \fB\fCsshpk\fR library
+is supported, including OpenSSH formats and standard PEM PKCS.
+.TP
+\fB\fC\-f PATH, \-\-file=PATH\fR
+Input file to sign instead of stdin.
+.TP
+\fB\fC\-o PATH, \-\-out=PATH\fR
+Output file to save signature in instead of stdout.
+.TP
+\fB\fC\-H HASH, \-\-hash=HASH\fR
+Set the hash algorithm to be used for signing. This should be one of \fB\fCsha1\fR,
+\fB\fCsha256\fR or \fB\fCsha512\fR\&. Some key types may place restrictions on which hash
+algorithms may be used (e.g. ED25519 keys can only use SHA\-512).
+.TP
+\fB\fC\-t FORMAT, \-\-format=FORMAT\fR
+Choose the signature format to use, from \fB\fCasn1\fR, \fB\fCssh\fR or \fB\fCraw\fR (only for
+ED25519 signatures). The \fB\fCasn1\fR format is the default, as it is the format
+used with TLS and typically the standard in most non\-SSH libraries (e.g.
+OpenSSL). The \fB\fCssh\fR format is used in the SSH protocol and by the ssh\-agent.
+.SH SEE ALSO
+.PP
+.BR sshpk-verify (1)
+.SH BUGS
+.PP
+Report bugs at Github
+\[la]https://github.com/arekinath/node-sshpk/issues\[ra]
diff --git a/node_modules/sshpk/man/man1/sshpk-verify.1 b/node_modules/sshpk/man/man1/sshpk-verify.1
new file mode 100644
index 0000000..f79169d
--- /dev/null
+++ b/node_modules/sshpk/man/man1/sshpk-verify.1
@@ -0,0 +1,68 @@
+.TH sshpk\-verify 1 "Jan 2016" sshpk "sshpk Commands"
+.SH NAME
+.PP
+sshpk\-verify \- verify a signature on data using an SSH key
+.SH SYNOPSYS
+.PP
+\fB\fCsshpk\-verify\fR \-i KEYPATH \-s SIGNATURE [OPTION...]
+.SH DESCRIPTION
+.PP
+Takes in arbitrary bytes and a Base64\-encoded signature, and verifies that the
+signature was produced by the private half of the given SSH public key.
+.SH EXAMPLES
+.PP
+.RS
+.nf
+$ printf 'foo' | sshpk\-verify \-i ~/.ssh/id_ecdsa \-s MEUCIQCYp...
+OK
+$ printf 'foo' | sshpk\-verify \-i ~/.ssh/id_ecdsa \-s GARBAGE...
+NOT OK
+.fi
+.RE
+.SH EXIT STATUS
+.TP
+\fB\fC0\fR
+Signature validates and matches the key.
+.TP
+\fB\fC1\fR
+Signature is parseable and the correct length but does not match the key or
+otherwise is invalid.
+.TP
+\fB\fC2\fR
+The signature or key could not be parsed.
+.TP
+\fB\fC3\fR
+Invalid commandline options were supplied.
+.SH OPTIONS
+.TP
+\fB\fC\-v, \-\-verbose\fR
+Print extra information about the key and signature to stderr when verifying.
+.TP
+\fB\fC\-i KEY, \-\-identity=KEY\fR
+Select the key to be used for verification. \fB\fCKEY\fR must be a relative or
+absolute filesystem path to the key file. Any format supported by the \fB\fCsshpk\fR
+library is supported, including OpenSSH formats and standard PEM PKCS.
+.TP
+\fB\fC\-s BASE64, \-\-signature=BASE64\fR
+Supplies the base64\-encoded signature to be verified.
+.TP
+\fB\fC\-f PATH, \-\-file=PATH\fR
+Input file to verify instead of stdin.
+.TP
+\fB\fC\-H HASH, \-\-hash=HASH\fR
+Set the hash algorithm to be used for signing. This should be one of \fB\fCsha1\fR,
+\fB\fCsha256\fR or \fB\fCsha512\fR\&. Some key types may place restrictions on which hash
+algorithms may be used (e.g. ED25519 keys can only use SHA\-512).
+.TP
+\fB\fC\-t FORMAT, \-\-format=FORMAT\fR
+Choose the signature format to use, from \fB\fCasn1\fR, \fB\fCssh\fR or \fB\fCraw\fR (only for
+ED25519 signatures). The \fB\fCasn1\fR format is the default, as it is the format
+used with TLS and typically the standard in most non\-SSH libraries (e.g.
+OpenSSL). The \fB\fCssh\fR format is used in the SSH protocol and by the ssh\-agent.
+.SH SEE ALSO
+.PP
+.BR sshpk-sign (1)
+.SH BUGS
+.PP
+Report bugs at Github
+\[la]https://github.com/arekinath/node-sshpk/issues\[ra]
diff --git a/node_modules/sshpk/package.json b/node_modules/sshpk/package.json
new file mode 100644
index 0000000..cc78787
--- /dev/null
+++ b/node_modules/sshpk/package.json
@@ -0,0 +1,60 @@
+{
+ "name": "sshpk",
+ "version": "1.16.1",
+ "description": "A library for finding and using SSH public keys",
+ "main": "lib/index.js",
+ "scripts": {
+ "test": "tape test/*.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/joyent/node-sshpk.git"
+ },
+ "author": "Joyent, Inc",
+ "contributors": [
+ {
+ "name": "Dave Eddy",
+ "email": "dave@daveeddy.com"
+ },
+ {
+ "name": "Mark Cavage",
+ "email": "mcavage@gmail.com"
+ },
+ {
+ "name": "Alex Wilson",
+ "email": "alex@cooperi.net"
+ }
+ ],
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/arekinath/node-sshpk/issues"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "directories": {
+ "bin": "./bin",
+ "lib": "./lib",
+ "man": "./man/man1"
+ },
+ "homepage": "https://github.com/arekinath/node-sshpk#readme",
+ "dependencies": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "getpass": "^0.1.1",
+ "safer-buffer": "^2.0.2",
+ "jsbn": "~0.1.0",
+ "tweetnacl": "~0.14.0",
+ "ecc-jsbn": "~0.1.1",
+ "bcrypt-pbkdf": "^1.0.0"
+ },
+ "optionalDependencies": {
+ },
+ "devDependencies": {
+ "tape": "^3.5.0",
+ "benchmark": "^1.0.0",
+ "sinon": "^1.17.2",
+ "temp": "^0.8.2"
+ }
+}