This commit is contained in:
eric sciple 2020-01-24 12:20:19 -05:00
parent beb1329f9f
commit 2b95e76931
7736 changed files with 1874747 additions and 51184 deletions

9
node_modules/sshpk/.npmignore generated vendored Normal file
View file

@ -0,0 +1,9 @@
.gitmodules
deps
docs
Makefile
node_modules
test
tools
coverage
man/src

11
node_modules/sshpk/.travis.yml generated vendored Normal file
View file

@ -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'

18
node_modules/sshpk/LICENSE generated vendored Normal file
View file

@ -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.

804
node_modules/sshpk/README.md generated vendored Normal file
View file

@ -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`

243
node_modules/sshpk/bin/sshpk-conv generated vendored Executable file
View file

@ -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);
}

191
node_modules/sshpk/bin/sshpk-sign generated vendored Executable file
View file

@ -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);
});
});
}

167
node_modules/sshpk/bin/sshpk-verify generated vendored Executable file
View file

@ -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);
});
}

168
node_modules/sshpk/lib/algs.js generated vendored Normal file
View file

@ -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
};

410
node_modules/sshpk/lib/certificate.js generated vendored Normal file
View file

@ -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]);
};

397
node_modules/sshpk/lib/dhe.js generated vendored Normal file
View file

@ -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);
}
}

92
node_modules/sshpk/lib/ed-compat.js generated vendored Normal file
View file

@ -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);
};

84
node_modules/sshpk/lib/errors.js generated vendored Normal file
View file

@ -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
};

220
node_modules/sshpk/lib/fingerprint.js generated vendored Normal file
View file

@ -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]);
};

124
node_modules/sshpk/lib/formats/auto.js generated vendored Normal file
View file

@ -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'));
}

287
node_modules/sshpk/lib/formats/dnssec.js generated vendored Normal file
View file

@ -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'));
}
}

352
node_modules/sshpk/lib/formats/openssh-cert.js generated vendored Normal file
View file

@ -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));
}

290
node_modules/sshpk/lib/formats/pem.js generated vendored Normal file
View file

@ -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));
}

373
node_modules/sshpk/lib/formats/pkcs1.js generated vendored Normal file
View file

@ -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'));
}

631
node_modules/sshpk/lib/formats/pkcs8.js generated vendored Normal file
View file

@ -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();
}

99
node_modules/sshpk/lib/formats/putty.js generated vendored Normal file
View file

@ -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);
}

166
node_modules/sshpk/lib/formats/rfc4253.js generated vendored Normal file
View file

@ -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());
}

262
node_modules/sshpk/lib/formats/ssh-private.js generated vendored Normal file
View file

@ -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));
}

115
node_modules/sshpk/lib/formats/ssh.js generated vendored Normal file
View file

@ -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(' ')));
}

88
node_modules/sshpk/lib/formats/x509-pem.js generated vendored Normal file
View file

@ -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));
}

752
node_modules/sshpk/lib/formats/x509.js generated vendored Normal file
View file

@ -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);
}

373
node_modules/sshpk/lib/identity.js generated vendored Normal file
View file

@ -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]);
};

40
node_modules/sshpk/lib/index.js generated vendored Normal file
View file

@ -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
};

294
node_modules/sshpk/lib/key.js generated vendored Normal file
View file

@ -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]);
};

246
node_modules/sshpk/lib/private-key.js generated vendored Normal file
View file

@ -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]);
};

314
node_modules/sshpk/lib/signature.js generated vendored Normal file
View file

@ -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]);
};

149
node_modules/sshpk/lib/ssh-buffer.js generated vendored Normal file
View file

@ -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;
};

404
node_modules/sshpk/lib/utils.js generated vendored Normal file
View file

@ -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);
}

135
node_modules/sshpk/man/man1/sshpk-conv.1 generated vendored Normal file
View file

@ -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]

81
node_modules/sshpk/man/man1/sshpk-sign.1 generated vendored Normal file
View file

@ -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]

68
node_modules/sshpk/man/man1/sshpk-verify.1 generated vendored Normal file
View file

@ -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]

100
node_modules/sshpk/package.json generated vendored Normal file
View file

@ -0,0 +1,100 @@
{
"_args": [
[
"sshpk@1.16.1",
"/Users/eric/repos/actions/setup-node"
]
],
"_development": true,
"_from": "sshpk@1.16.1",
"_id": "sshpk@1.16.1",
"_inBundle": false,
"_integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
"_location": "/sshpk",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "sshpk@1.16.1",
"name": "sshpk",
"escapedName": "sshpk",
"rawSpec": "1.16.1",
"saveSpec": null,
"fetchSpec": "1.16.1"
},
"_requiredBy": [
"/http-signature"
],
"_resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
"_spec": "1.16.1",
"_where": "/Users/eric/repos/actions/setup-node",
"author": {
"name": "Joyent, Inc"
},
"bin": {
"sshpk-conv": "bin/sshpk-conv",
"sshpk-sign": "bin/sshpk-sign",
"sshpk-verify": "bin/sshpk-verify"
},
"bugs": {
"url": "https://github.com/arekinath/node-sshpk/issues"
},
"contributors": [
{
"name": "Dave Eddy",
"email": "dave@daveeddy.com"
},
{
"name": "Mark Cavage",
"email": "mcavage@gmail.com"
},
{
"name": "Alex Wilson",
"email": "alex@cooperi.net"
}
],
"dependencies": {
"asn1": "~0.2.3",
"assert-plus": "^1.0.0",
"bcrypt-pbkdf": "^1.0.0",
"dashdash": "^1.12.0",
"ecc-jsbn": "~0.1.1",
"getpass": "^0.1.1",
"jsbn": "~0.1.0",
"safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0"
},
"description": "A library for finding and using SSH public keys",
"devDependencies": {
"benchmark": "^1.0.0",
"sinon": "^1.17.2",
"tape": "^3.5.0",
"temp": "^0.8.2"
},
"directories": {
"bin": "./bin",
"lib": "./lib",
"man": "./man/man1"
},
"engines": {
"node": ">=0.10.0"
},
"homepage": "https://github.com/arekinath/node-sshpk#readme",
"license": "MIT",
"main": "lib/index.js",
"man": [
"/Users/eric/repos/actions/setup-node/node_modules/sshpk/man/man1/sshpk-conv.1",
"/Users/eric/repos/actions/setup-node/node_modules/sshpk/man/man1/sshpk-sign.1",
"/Users/eric/repos/actions/setup-node/node_modules/sshpk/man/man1/sshpk-verify.1"
],
"name": "sshpk",
"optionalDependencies": {},
"repository": {
"type": "git",
"url": "git+https://github.com/joyent/node-sshpk.git"
},
"scripts": {
"test": "tape test/*.js"
},
"version": "1.16.1"
}