first commit

This commit is contained in:
Raven Scott
2026-04-08 18:36:00 -04:00
commit 458e9268dc
151 changed files with 29182 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
node_modules/
npm-debug.log*
.DS_Store
coverage/
.nyc_output/
lib/protocol/crypto/build/
*.node
scripts/openssh-test-server/runtime/
+1
View File
@@ -0,0 +1 @@
"prettier-config-holepunch"
+19
View File
@@ -0,0 +1,19 @@
Copyright Brian White. 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.
+5
View File
@@ -0,0 +1,5 @@
bare-ssh2 is a Bare-native packaging of the ssh2 library by Brian White (mscdex),
originally published at https://github.com/mscdex/ssh2 under the MIT license.
The Bare port is maintained by Holepunch. Node.js compatibility shims are provided
via the bare-node-* packages from https://github.com/holepunchto/bare-node .
+100
View File
@@ -0,0 +1,100 @@
# bare-ssh2
This is a **Bare-native port** of the excellent [ssh2](https://github.com/mscdex/ssh2) library by Brian White (mscdex). It exposes the same public API (`Client`, `Server`, agents, `utils`, SFTP helpers, etc.) so code written for `ssh2` can switch the import to `bare-ssh2` and run on the [Bare](https://github.com/holepunchto/bare) / Pear runtime.
On **Node.js**, builtin modules are still used (via the `default` branch of this packages `imports` map), so the same package can be tried on Node for comparison; primary support targets **Bare**.
## Installation
```bash
npm install bare-ssh2
```
## Drop-in usage
Replace `ssh2` with `bare-ssh2`:
```js
const { readFileSync } = require('fs')
const { Client } = require('bare-ssh2')
const conn = new Client()
conn
.on('ready', () => {
conn.exec('uptime', (err, stream) => {
if (err) throw err
stream
.on('close', (code, signal) => {
console.log('close', code, signal)
conn.end()
})
.on('data', (data) => console.log('STDOUT:', data.toString()))
stream.stderr.on('data', (data) => console.log('STDERR:', data.toString()))
})
})
.connect({
host: 'example.com',
port: 22,
username: 'you',
privateKey: readFileSync('/path/to/key')
})
```
ESM interop follows your bundler/runtime rules for loading this **CommonJS** package.
## How it maps Node builtins on Bare
Inside this package, `require('net')`, `require('dns')`, and other Node core names are resolved using `package.json` **`imports`** with the **`bare`** condition to [bare-node-\*](https://github.com/holepunchto/bare-node) wrappers. You do not need to change those specifiers in application code that only imports `bare-ssh2`.
**`crypto`:** Bares module resolver does not apply this packages `imports` map to dependencies such as `tweetnacl` (used by `bcrypt-pbkdf`). This package therefore depends on a small local **[`shims/crypto`](shims/crypto/)** package (published as the `crypto` dependency) built on **`bare-crypto`**, with **`getCiphers()`** / **`getHashes()`** lists implemented in [`shims/crypto/lists.js`](shims/crypto/lists.js). The **`bare`** `imports` entry for `crypto` points at the same shim so library code and transitive deps share one implementation.
**`assert` / `buffer`:** Declared as **`npm:bare-node-*`** aliases so `asn1` and `safer-buffer` resolve them on Bare.
**Buffer:** [`lib/buffer-polyfill.js`](lib/buffer-polyfill.js) adds Nodes `utf8Write` / `latin1Write` / `*Slice` helpers when missing (loaded from `lib/index.js`, `client.js`, `server.js`, `keygen.js`, and `protocol/keyParser.js`).
The optional **ssh2** native crypto binding and **`cpu-features`** optional dependency from upstream are **not** used here. For **ChaCha20** packet encryption without OpenSSL, the **`chacha20`** npm package is used when `createCipheriv('chacha20', …)` is unsupported.
## API documentation
See the upstream [ssh2 README](https://github.com/mscdex/ssh2/blob/master/README.md) for the full API (client/server events, SFTP, forwarding, HTTP(S) agents, key utilities).
## Testing
From this package directory after `npm install`:
```bash
npm test
```
This runs **Prettier**, then **`bare test/test-protocol-crypto.js`**, then **`node test/test-protocol-keyparser.js`** (key parser sign/verify checks currently match Nodes OpenSSL more closely than Bares crypto for some ECDSA/OpenSSH fixtures).
Other useful commands:
```bash
bare test/test-protocol-crypto.js
npm run test:all
```
`npm run test:all` runs Prettier and **`bare test/test.js`**, which spawns every `test-*.js` (needs OpenSSH, keys, etc. where applicable).
```bash
npm run test:node
```
runs the same driver under Node.
### Known gaps on Bare
- **RC4 (`arcfour`)** and some legacy ciphers are not implemented in **bare-crypto**; they are omitted from negotiation when unsupported.
- **ECDSA signing** for some OpenSSH private key paths may differ between Bare and Node; report issues with minimal key fixtures if you hit this in production.
- Tests that shell out to **OpenSSH** or need a full **worker_threads** stack may fail unless the matching **bare-node-\*** test dependencies are installed.
- Default cipher/MAC lists follow **`getCiphers()`** / **`getHashes()`** from the crypto shim (subset of OpenSSLs names).
- **SSH agent** helpers that use **`child_process`** depend on **bare-subprocess**; Windows-specific paths (Pageant, Cygwin) may differ from Node.
## TypeScript
Upstream `ssh2` does not ship types. You can use **`@types/ssh2`** for typings against this API.
## License
**MIT** — same as the original ssh2 code. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
+244
View File
@@ -0,0 +1,244 @@
// **BEFORE RUNNING THIS SCRIPT:**
// 1. The server portion is best run on non-Windows systems because they have
// terminfo databases which are needed to properly work with different
// terminal types of client connections
// 2. Install `blessed`: `npm install blessed`
// 3. Create a server host key in this same directory and name it `host.key`
'use strict'
const { readFileSync } = require('fs')
const blessed = require('blessed')
const { Server } = require('bare-ssh2')
const RE_SPECIAL =
// eslint-disable-next-line no-control-regex
/[\x00-\x1F\x7F]+|(?:\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K])/g
const MAX_MSG_LEN = 128
const MAX_NAME_LEN = 10
const PROMPT_NAME = `Enter a nickname to use (max ${MAX_NAME_LEN} chars): `
const users = []
function formatMessage(msg, output) {
output.parseTags = true
msg = output._parseTags(msg)
output.parseTags = false
return msg
}
function userBroadcast(msg, source) {
const sourceMsg = `> ${msg}`
const name = `{cyan-fg}{bold}${source.name}{/}`
msg = `: ${msg}`
for (const user of users) {
const output = user.output
if (source === user) output.add(sourceMsg)
else output.add(formatMessage(name, output) + msg)
}
}
function localMessage(msg, source) {
const output = source.output
output.add(formatMessage(msg, output))
}
function noop(v) {}
new Server(
{
hostKeys: [readFileSync('host.key')]
},
(client) => {
let stream
let name
client
.on('authentication', (ctx) => {
let nick = ctx.username
let prompt = PROMPT_NAME
let lowered
// Try to use username as nickname
if (nick.length > 0 && nick.length <= MAX_NAME_LEN) {
lowered = nick.toLowerCase()
let ok = true
for (const user of users) {
if (user.name.toLowerCase() === lowered) {
ok = false
prompt = `That nickname is already in use.\n${PROMPT_NAME}`
break
}
}
if (ok) {
name = nick
return ctx.accept()
}
} else if (nick.length === 0) {
prompt = 'A nickname is required.\n' + PROMPT_NAME
} else {
prompt = 'That nickname is too long.\n' + PROMPT_NAME
}
if (ctx.method !== 'keyboard-interactive') return ctx.reject(['keyboard-interactive'])
ctx.prompt(prompt, function retryPrompt(answers) {
if (answers.length === 0) return ctx.reject(['keyboard-interactive'])
nick = answers[0]
if (nick.length > MAX_NAME_LEN) {
return ctx.prompt(`That nickname is too long.\n${PROMPT_NAME}`, retryPrompt)
} else if (nick.length === 0) {
return ctx.prompt(`A nickname is required.\n${PROMPT_NAME}`, retryPrompt)
}
lowered = nick.toLowerCase()
for (const user of users) {
if (user.name.toLowerCase() === lowered) {
return ctx.prompt(`That nickname is already in use.\n${PROMPT_NAME}`, retryPrompt)
}
}
name = nick
ctx.accept()
})
})
.on('ready', () => {
let rows
let cols
let term
client.once('session', (accept, reject) => {
accept()
.once('pty', (accept, reject, info) => {
rows = info.rows
cols = info.cols
term = info.term
accept && accept()
})
.on('window-change', (accept, reject, info) => {
rows = info.rows
cols = info.cols
if (stream) {
stream.rows = rows
stream.columns = cols
stream.emit('resize')
}
accept && accept()
})
.once('shell', (accept, reject) => {
stream = accept()
users.push(stream)
stream.name = name
stream.rows = rows || 24
stream.columns = cols || 80
stream.isTTY = true
stream.setRawMode = noop
stream.on('error', noop)
const screen = new blessed.screen({
autoPadding: true,
smartCSR: true,
program: new blessed.program({
input: stream,
output: stream
}),
terminal: term || 'ansi'
})
screen.title = 'SSH Chatting as ' + name
// Disable local echo
screen.program.attr('invisible', true)
const output = (stream.output = new blessed.log({
screen: screen,
top: 0,
left: 0,
width: '100%',
bottom: 2,
scrollOnInput: true
}))
screen.append(output)
screen.append(
new blessed.box({
screen: screen,
height: 1,
bottom: 1,
left: 0,
width: '100%',
type: 'line',
ch: '='
})
)
const input = new blessed.textbox({
screen: screen,
bottom: 0,
height: 1,
width: '100%',
inputOnFocus: true
})
screen.append(input)
input.focus()
// Local greetings
localMessage(
'{blue-bg}{white-fg}{bold}Welcome to SSH Chat!{/}\n' +
'There are {bold}' +
(users.length - 1) +
'{/} other user(s) connected.\n' +
'Type /quit or /exit to exit the chat.',
stream
)
// Let everyone else know that this user just joined
for (const user of users) {
const output = user.output
if (user === stream) continue
output.add(
formatMessage('{green-fg}*** {bold}', output) +
name +
formatMessage('{/bold} has joined the chat{/}', output)
)
}
screen.render()
// XXX This fake resize event is needed for some terminals in order to
// have everything display correctly
screen.program.emit('resize')
// Read a line of input from the user
input.on('submit', (line) => {
input.clearValue()
screen.render()
if (!input.focused) input.focus()
line = line.replace(RE_SPECIAL, '').trim()
if (line.length > MAX_MSG_LEN) line = line.substring(0, MAX_MSG_LEN)
if (line.length > 0) {
if (line === '/quit' || line === '/exit') stream.end()
else userBroadcast(line, stream)
}
})
})
})
})
.on('close', () => {
if (stream !== undefined) {
users.splice(users.indexOf(stream), 1)
// Let everyone else know that this user just left
for (const user of users) {
const output = user.output
output.add(
formatMessage('{magenta-fg}*** {bold}', output) +
name +
formatMessage('{/bold} has left the chat{/}', output)
)
}
}
})
.on('error', (err) => {
// Ignore errors
})
}
).listen(0, function () {
console.log('Listening on port ' + this.address().port)
})
+141
View File
@@ -0,0 +1,141 @@
'use strict'
const { timingSafeEqual } = require('crypto')
const { constants, readFileSync } = require('fs')
const {
Server,
sftp: { OPEN_MODE, STATUS_CODE }
} = require('bare-ssh2')
const allowedUser = Buffer.from('foo')
const allowedPassword = Buffer.from('bar')
function checkValue(input, allowed) {
const autoReject = input.length !== allowed.length
if (autoReject) {
// Prevent leaking length information by always making a comparison with the
// same input when lengths don't match what we expect ...
allowed = input
}
const isMatch = timingSafeEqual(input, allowed)
return !autoReject && isMatch
}
new Server(
{
hostKeys: [readFileSync('host.key')]
},
(client) => {
console.log('Client connected!')
client
.on('authentication', (ctx) => {
let allowed = true
if (!checkValue(Buffer.from(ctx.username), allowedUser)) allowed = false
switch (ctx.method) {
case 'password':
if (!checkValue(Buffer.from(ctx.password), allowedPassword)) return ctx.reject()
break
default:
return ctx.reject()
}
if (allowed) ctx.accept()
else ctx.reject()
})
.on('ready', () => {
console.log('Client authenticated!')
client.on('session', (accept, reject) => {
const session = accept()
session.on('sftp', (accept, reject) => {
console.log('Client SFTP session')
const openFiles = new Map()
let handleCount = 0
const sftp = accept()
sftp
.on('OPEN', (reqid, filename, flags, attrs) => {
// Only allow opening /tmp/foo.txt for writing
if (filename !== '/tmp/foo.txt' || !(flags & OPEN_MODE.READ))
return sftp.status(reqid, STATUS_CODE.FAILURE)
// Create a fake handle to return to the client, this could easily
// be a real file descriptor number for example if actually opening
// the file on the disk
const handle = Buffer.alloc(4)
openFiles.set(handleCount, { read: false })
handle.writeUInt32BE(handleCount++, 0, true)
console.log('Opening file for read')
sftp.handle(reqid, handle)
})
.on('READ', (reqid, handle, offset, length) => {
let fnum
if (handle.length !== 4 || !openFiles.has((fnum = handle.readUInt32BE(0, true)))) {
return sftp.status(reqid, STATUS_CODE.FAILURE)
}
// Fake the read
const state = openFiles.get(fnum)
if (state.read) {
sftp.status(reqid, STATUS_CODE.EOF)
} else {
state.read = true
console.log('Read from file at offset %d, length %d', offset, length)
sftp.data(reqid, 'bar')
}
})
.on('CLOSE', (reqid, handle) => {
let fnum
if (handle.length !== 4 || !openFiles.has((fnum = handle.readUInt32BE(0)))) {
return sftp.status(reqid, STATUS_CODE.FAILURE)
}
openFiles.delete(fnum)
console.log('Closing file')
sftp.status(reqid, STATUS_CODE.OK)
})
.on('REALPATH', function (reqid, path) {
const name = [
{
filename: '/tmp/foo.txt',
longname: '-rwxrwxrwx 1 foo foo 3 Dec 8 2009 foo.txt',
attrs: {}
}
]
sftp.name(reqid, name)
})
.on('STAT', onSTAT)
.on('LSTAT', onSTAT)
function onSTAT(reqid, path) {
if (path !== '/tmp/foo.txt') return sftp.status(reqid, STATUS_CODE.FAILURE)
let mode = constants.S_IFREG // Regular file
mode |= constants.S_IRWXU // Read, write, execute for user
mode |= constants.S_IRWXG // Read, write, execute for group
mode |= constants.S_IRWXO // Read, write, execute for other
sftp.attrs(reqid, {
mode: mode,
uid: 0,
gid: 0,
size: 3,
atime: Date.now(),
mtime: Date.now()
})
}
})
})
})
.on('close', () => {
console.log('Client disconnected')
})
}
).listen(0, '127.0.0.1', function () {
console.log(`Listening on port ${this.address().port}`)
})
+258
View File
@@ -0,0 +1,258 @@
'use strict'
const {
Duplex: DuplexStream,
Readable: ReadableStream,
Writable: WritableStream
} = require('stream')
const {
CHANNEL_EXTENDED_DATATYPE: { STDERR }
} = require('./protocol/constants.js')
const { bufferSlice } = require('./protocol/utils.js')
const PACKET_SIZE = 32 * 1024
const MAX_WINDOW = 2 * 1024 * 1024
const WINDOW_THRESHOLD = MAX_WINDOW / 2
class ClientStderr extends ReadableStream {
constructor(channel, streamOpts) {
super(streamOpts)
this._channel = channel
}
_read(n) {
if (this._channel._waitChanDrain) {
this._channel._waitChanDrain = false
if (this._channel.incoming.window <= WINDOW_THRESHOLD) windowAdjust(this._channel)
}
}
}
class ServerStderr extends WritableStream {
constructor(channel) {
super({ highWaterMark: MAX_WINDOW })
this._channel = channel
}
_write(data, encoding, cb) {
const channel = this._channel
const protocol = channel._client._protocol
const outgoing = channel.outgoing
const packetSize = outgoing.packetSize
const id = outgoing.id
let window = outgoing.window
const len = data.length
let p = 0
if (outgoing.state !== 'open') return
while (len - p > 0 && window > 0) {
let sliceLen = len - p
if (sliceLen > window) sliceLen = window
if (sliceLen > packetSize) sliceLen = packetSize
if (p === 0 && sliceLen === len) protocol.channelExtData(id, data, STDERR)
else protocol.channelExtData(id, bufferSlice(data, p, p + sliceLen), STDERR)
p += sliceLen
window -= sliceLen
}
outgoing.window = window
if (len - p > 0) {
if (window === 0) channel._waitWindow = true
if (p > 0) channel._chunkErr = bufferSlice(data, p, len)
else channel._chunkErr = data
channel._chunkcbErr = cb
return
}
cb()
}
}
class Channel extends DuplexStream {
constructor(client, info, opts) {
const streamOpts = {
highWaterMark: MAX_WINDOW,
allowHalfOpen: !opts || (opts && opts.allowHalfOpen !== false),
emitClose: false
}
super(streamOpts)
this.allowHalfOpen = streamOpts.allowHalfOpen
const server = !!(opts && opts.server)
this.server = server
this.type = info.type
this.subtype = undefined
/*
incoming and outgoing contain these properties:
{
id: undefined,
window: undefined,
packetSize: undefined,
state: 'closed'
}
*/
this.incoming = info.incoming
this.outgoing = info.outgoing
this._callbacks = []
this._client = client
this._hasX11 = false
this._exit = {
code: undefined,
signal: undefined,
dump: undefined,
desc: undefined
}
this.stdin = this.stdout = this
if (server) this.stderr = new ServerStderr(this)
else this.stderr = new ClientStderr(this, streamOpts)
// Outgoing data
this._waitWindow = false // SSH-level backpressure
// Incoming data
this._waitChanDrain = false // Channel Readable side backpressure
this._chunk = undefined
this._chunkcb = undefined
this._chunkErr = undefined
this._chunkcbErr = undefined
this.on('finish', onFinish).on('prefinish', onFinish) // For node v0.11+
this.on('end', onEnd).on('close', onEnd)
}
_read(n) {
if (this._waitChanDrain) {
this._waitChanDrain = false
if (this.incoming.window <= WINDOW_THRESHOLD) windowAdjust(this)
}
}
_write(data, encoding, cb) {
const protocol = this._client._protocol
const outgoing = this.outgoing
const packetSize = outgoing.packetSize
const id = outgoing.id
let window = outgoing.window
const len = data.length
let p = 0
if (outgoing.state !== 'open') return
while (len - p > 0 && window > 0) {
let sliceLen = len - p
if (sliceLen > window) sliceLen = window
if (sliceLen > packetSize) sliceLen = packetSize
if (p === 0 && sliceLen === len) protocol.channelData(id, data)
else protocol.channelData(id, bufferSlice(data, p, p + sliceLen))
p += sliceLen
window -= sliceLen
}
outgoing.window = window
if (len - p > 0) {
if (window === 0) this._waitWindow = true
if (p > 0) this._chunk = bufferSlice(data, p, len)
else this._chunk = data
this._chunkcb = cb
return
}
cb()
}
eof() {
if (this.outgoing.state === 'open') {
this.outgoing.state = 'eof'
this._client._protocol.channelEOF(this.outgoing.id)
}
}
close() {
if (this.outgoing.state === 'open' || this.outgoing.state === 'eof') {
this.outgoing.state = 'closing'
this._client._protocol.channelClose(this.outgoing.id)
}
}
destroy() {
this.end()
this.close()
return this
}
// Session type-specific methods =============================================
setWindow(rows, cols, height, width) {
if (this.server) throw new Error('Client-only method called in server mode')
if (
this.type === 'session' &&
(this.subtype === 'shell' || this.subtype === 'exec') &&
this.writable &&
this.outgoing.state === 'open'
) {
this._client._protocol.windowChange(this.outgoing.id, rows, cols, height, width)
}
}
signal(signalName) {
if (this.server) throw new Error('Client-only method called in server mode')
if (this.type === 'session' && this.writable && this.outgoing.state === 'open') {
this._client._protocol.signal(this.outgoing.id, signalName)
}
}
exit(statusOrSignal, coreDumped, msg) {
if (!this.server) throw new Error('Server-only method called in client mode')
if (this.type === 'session' && this.writable && this.outgoing.state === 'open') {
if (typeof statusOrSignal === 'number') {
this._client._protocol.exitStatus(this.outgoing.id, statusOrSignal)
} else {
this._client._protocol.exitSignal(this.outgoing.id, statusOrSignal, coreDumped, msg)
}
}
}
}
function onFinish() {
this.eof()
if (this.server || !this.allowHalfOpen) this.close()
this.writable = false
}
function onEnd() {
this.readable = false
}
function windowAdjust(self) {
if (self.outgoing.state === 'closed') return
const amt = MAX_WINDOW - self.incoming.window
if (amt <= 0) return
self.incoming.window += amt
self._client._protocol.channelWindowAdjust(self.outgoing.id, amt)
}
module.exports = {
Channel,
MAX_WINDOW,
PACKET_SIZE,
windowAdjust,
WINDOW_THRESHOLD
}
+1058
View File
File diff suppressed because it is too large Load Diff
+33
View File
@@ -0,0 +1,33 @@
'use strict'
const B = Buffer
if (typeof B.prototype.utf8Write !== 'function') {
B.prototype.utf8Write = function utf8Write(string, offset, length) {
return this.write(string, offset, length, 'utf8')
}
}
if (typeof B.prototype.latin1Write !== 'function') {
B.prototype.latin1Write = function latin1Write(string, offset, length) {
return this.write(string, offset, length, 'latin1')
}
}
if (typeof B.prototype.base64Slice !== 'function') {
B.prototype.base64Slice = function base64Slice(start, end) {
return this.toString('base64', start, end)
}
}
if (typeof B.prototype.utf8Slice !== 'function') {
B.prototype.utf8Slice = function utf8Slice(start, end) {
return this.toString('utf8', start, end)
}
}
if (typeof B.prototype.latin1Slice !== 'function') {
B.prototype.latin1Slice = function latin1Slice(start, end) {
return this.toString('latin1', start, end)
}
}
+1963
View File
File diff suppressed because it is too large Load Diff
+84
View File
@@ -0,0 +1,84 @@
'use strict'
const { Agent: HttpAgent } = require('http')
const { Agent: HttpsAgent } = require('https')
const { connect: tlsConnect } = require('tls')
let Client
for (const ctor of [HttpAgent, HttpsAgent]) {
class SSHAgent extends ctor {
constructor(connectCfg, agentOptions) {
super(agentOptions)
this._connectCfg = connectCfg
this._defaultSrcIP = (agentOptions && agentOptions.srcIP) || 'localhost'
}
createConnection(options, cb) {
const srcIP = (options && options.localAddress) || this._defaultSrcIP
const srcPort = (options && options.localPort) || 0
const dstIP = options.host
const dstPort = options.port
if (Client === undefined) Client = require('./client.js')
const client = new Client()
let triedForward = false
client
.on('ready', () => {
client.forwardOut(srcIP, srcPort, dstIP, dstPort, (err, stream) => {
triedForward = true
if (err) {
client.end()
return cb(err)
}
stream.once('close', () => client.end())
cb(null, decorateStream(stream, ctor, options))
})
})
.on('error', cb)
.on('close', () => {
if (!triedForward) cb(new Error('Unexpected connection close'))
})
.connect(this._connectCfg)
}
}
exports[ctor === HttpAgent ? 'SSHTTPAgent' : 'SSHTTPSAgent'] = SSHAgent
}
function noop() {}
function decorateStream(stream, ctor, options) {
if (ctor === HttpAgent) {
// HTTP
stream.setKeepAlive = noop
stream.setNoDelay = noop
stream.setTimeout = noop
stream.ref = noop
stream.unref = noop
stream.destroySoon = stream.destroy
return stream
}
// HTTPS
options.socket = stream
const wrapped = tlsConnect(options)
// This is a workaround for a regression in node v12.16.3+
// https://github.com/nodejs/node/issues/35904
const onClose = (() => {
let called = false
return () => {
if (called) return
called = true
if (stream.isPaused()) stream.resume()
}
})()
// 'end' listener is needed because 'close' is not emitted in some scenarios
// in node v12.x for some unknown reason
wrapped.on('end', onClose).on('close', onClose)
return wrapped
}
+38
View File
@@ -0,0 +1,38 @@
'use strict'
require('./buffer-polyfill.js')
const {
AgentProtocol,
BaseAgent,
createAgent,
CygwinAgent,
OpenSSHAgent,
PageantAgent
} = require('./agent.js')
const { SSHTTPAgent: HTTPAgent, SSHTTPSAgent: HTTPSAgent } = require('./http-agents.js')
const { parseKey } = require('./protocol/keyParser.js')
const { flagsToString, OPEN_MODE, STATUS_CODE, stringToFlags } = require('./protocol/SFTP.js')
module.exports = {
AgentProtocol,
BaseAgent,
createAgent,
Client: require('./client.js'),
CygwinAgent,
HTTPAgent,
HTTPSAgent,
OpenSSHAgent,
PageantAgent,
Server: require('./server.js'),
utils: {
parseKey,
...require('./keygen.js'),
sftp: {
flagsToString,
OPEN_MODE,
STATUS_CODE,
stringToFlags
}
}
}
+542
View File
@@ -0,0 +1,542 @@
'use strict'
require('./buffer-polyfill.js')
const {
createCipheriv,
generateKeyPair: generateKeyPair_,
generateKeyPairSync: generateKeyPairSync_,
getCurves,
randomBytes
} = require('crypto')
const { Ber } = require('asn1')
const bcrypt_pbkdf = require('bcrypt-pbkdf').pbkdf
const { CIPHER_INFO } = require('./protocol/crypto.js')
const SALT_LEN = 16
const DEFAULT_ROUNDS = 16
const curves = getCurves()
const ciphers = new Map(Object.entries(CIPHER_INFO))
function makeArgs(type, opts) {
if (typeof type !== 'string') throw new TypeError('Key type must be a string')
const publicKeyEncoding = { type: 'spki', format: 'der' }
const privateKeyEncoding = { type: 'pkcs8', format: 'der' }
switch (type.toLowerCase()) {
case 'rsa': {
if (typeof opts !== 'object' || opts === null)
throw new TypeError('Missing options object for RSA key')
const modulusLength = opts.bits
if (!Number.isInteger(modulusLength)) throw new TypeError('RSA bits must be an integer')
if (modulusLength <= 0 || modulusLength > 16384)
throw new RangeError('RSA bits must be non-zero and <= 16384')
return ['rsa', { modulusLength, publicKeyEncoding, privateKeyEncoding }]
}
case 'ecdsa': {
if (typeof opts !== 'object' || opts === null)
throw new TypeError('Missing options object for ECDSA key')
if (!Number.isInteger(opts.bits)) throw new TypeError('ECDSA bits must be an integer')
let namedCurve
switch (opts.bits) {
case 256:
namedCurve = 'prime256v1'
break
case 384:
namedCurve = 'secp384r1'
break
case 521:
namedCurve = 'secp521r1'
break
default:
throw new Error('ECDSA bits must be 256, 384, or 521')
}
if (!curves.includes(namedCurve)) throw new Error('Unsupported ECDSA bits value')
return ['ec', { namedCurve, publicKeyEncoding, privateKeyEncoding }]
}
case 'ed25519':
return ['ed25519', { publicKeyEncoding, privateKeyEncoding }]
default:
throw new Error(`Unsupported key type: ${type}`)
}
}
function parseDERs(keyType, pub, priv) {
switch (keyType) {
case 'rsa': {
// Note: we don't need to parse the public key since the PKCS8 private key
// already includes the public key parameters
// Parse private key
let reader = new Ber.Reader(priv)
reader.readSequence()
// - Version
if (reader.readInt() !== 0) throw new Error('Unsupported version in RSA private key')
// - Algorithm
reader.readSequence()
if (reader.readOID() !== '1.2.840.113549.1.1.1') throw new Error('Bad RSA private OID')
// - Algorithm parameters (RSA has none)
if (reader.readByte() !== Ber.Null)
throw new Error('Malformed RSA private key (expected null)')
if (reader.readByte() !== 0x00) {
throw new Error('Malformed RSA private key (expected zero-length null)')
}
reader = new Ber.Reader(reader.readString(Ber.OctetString, true))
reader.readSequence()
if (reader.readInt() !== 0) throw new Error('Unsupported version in RSA private key')
const n = reader.readString(Ber.Integer, true)
const e = reader.readString(Ber.Integer, true)
const d = reader.readString(Ber.Integer, true)
const p = reader.readString(Ber.Integer, true)
const q = reader.readString(Ber.Integer, true)
reader.readString(Ber.Integer, true) // dmp1
reader.readString(Ber.Integer, true) // dmq1
const iqmp = reader.readString(Ber.Integer, true)
/*
OpenSSH RSA private key:
string "ssh-rsa"
string n -- public
string e -- public
string d -- private
string iqmp -- private
string p -- private
string q -- private
*/
const keyName = Buffer.from('ssh-rsa')
const privBuf = Buffer.allocUnsafe(
4 +
keyName.length +
4 +
n.length +
4 +
e.length +
4 +
d.length +
4 +
iqmp.length +
4 +
p.length +
4 +
q.length
)
let pos = 0
privBuf.writeUInt32BE(keyName.length, (pos += 0))
privBuf.set(keyName, (pos += 4))
privBuf.writeUInt32BE(n.length, (pos += keyName.length))
privBuf.set(n, (pos += 4))
privBuf.writeUInt32BE(e.length, (pos += n.length))
privBuf.set(e, (pos += 4))
privBuf.writeUInt32BE(d.length, (pos += e.length))
privBuf.set(d, (pos += 4))
privBuf.writeUInt32BE(iqmp.length, (pos += d.length))
privBuf.set(iqmp, (pos += 4))
privBuf.writeUInt32BE(p.length, (pos += iqmp.length))
privBuf.set(p, (pos += 4))
privBuf.writeUInt32BE(q.length, (pos += p.length))
privBuf.set(q, (pos += 4))
/*
OpenSSH RSA public key:
string "ssh-rsa"
string e -- public
string n -- public
*/
const pubBuf = Buffer.allocUnsafe(4 + keyName.length + 4 + e.length + 4 + n.length)
pos = 0
pubBuf.writeUInt32BE(keyName.length, (pos += 0))
pubBuf.set(keyName, (pos += 4))
pubBuf.writeUInt32BE(e.length, (pos += keyName.length))
pubBuf.set(e, (pos += 4))
pubBuf.writeUInt32BE(n.length, (pos += e.length))
pubBuf.set(n, (pos += 4))
return { sshName: keyName.toString(), priv: privBuf, pub: pubBuf }
}
case 'ec': {
// Parse public key
let reader = new Ber.Reader(pub)
reader.readSequence()
reader.readSequence()
if (reader.readOID() !== '1.2.840.10045.2.1') throw new Error('Bad ECDSA public OID')
// Skip curve OID, we'll get it from the private key
reader.readOID()
let pubBin = reader.readString(Ber.BitString, true)
{
// Remove leading zero bytes
let i = 0
for (; i < pubBin.length && pubBin[i] === 0x00; ++i);
if (i > 0) pubBin = pubBin.slice(i)
}
// Parse private key
reader = new Ber.Reader(priv)
reader.readSequence()
// - Version
if (reader.readInt() !== 0) throw new Error('Unsupported version in ECDSA private key')
reader.readSequence()
if (reader.readOID() !== '1.2.840.10045.2.1') throw new Error('Bad ECDSA private OID')
const curveOID = reader.readOID()
let sshCurveName
switch (curveOID) {
case '1.2.840.10045.3.1.7':
// prime256v1/secp256r1
sshCurveName = 'nistp256'
break
case '1.3.132.0.34':
// secp384r1
sshCurveName = 'nistp384'
break
case '1.3.132.0.35':
// secp521r1
sshCurveName = 'nistp521'
break
default:
throw new Error('Unsupported curve in ECDSA private key')
}
reader = new Ber.Reader(reader.readString(Ber.OctetString, true))
reader.readSequence()
// - Version
if (reader.readInt() !== 1) throw new Error('Unsupported version in ECDSA private key')
// Add leading zero byte to prevent negative bignum in private key
const privBin = Buffer.concat([Buffer.from([0x00]), reader.readString(Ber.OctetString, true)])
/*
OpenSSH ECDSA private key:
string "ecdsa-sha2-<sshCurveName>"
string curve name
string Q -- public
string d -- private
*/
const keyName = Buffer.from(`ecdsa-sha2-${sshCurveName}`)
sshCurveName = Buffer.from(sshCurveName)
const privBuf = Buffer.allocUnsafe(
4 + keyName.length + 4 + sshCurveName.length + 4 + pubBin.length + 4 + privBin.length
)
let pos = 0
privBuf.writeUInt32BE(keyName.length, (pos += 0))
privBuf.set(keyName, (pos += 4))
privBuf.writeUInt32BE(sshCurveName.length, (pos += keyName.length))
privBuf.set(sshCurveName, (pos += 4))
privBuf.writeUInt32BE(pubBin.length, (pos += sshCurveName.length))
privBuf.set(pubBin, (pos += 4))
privBuf.writeUInt32BE(privBin.length, (pos += pubBin.length))
privBuf.set(privBin, (pos += 4))
/*
OpenSSH ECDSA public key:
string "ecdsa-sha2-<sshCurveName>"
string curve name
string Q -- public
*/
const pubBuf = Buffer.allocUnsafe(
4 + keyName.length + 4 + sshCurveName.length + 4 + pubBin.length
)
pos = 0
pubBuf.writeUInt32BE(keyName.length, (pos += 0))
pubBuf.set(keyName, (pos += 4))
pubBuf.writeUInt32BE(sshCurveName.length, (pos += keyName.length))
pubBuf.set(sshCurveName, (pos += 4))
pubBuf.writeUInt32BE(pubBin.length, (pos += sshCurveName.length))
pubBuf.set(pubBin, (pos += 4))
return { sshName: keyName.toString(), priv: privBuf, pub: pubBuf }
}
case 'ed25519': {
// Parse public key
let reader = new Ber.Reader(pub)
reader.readSequence()
// - Algorithm
reader.readSequence()
if (reader.readOID() !== '1.3.101.112') throw new Error('Bad ED25519 public OID')
// - Attributes (absent for ED25519)
let pubBin = reader.readString(Ber.BitString, true)
{
// Remove leading zero bytes
let i = 0
for (; i < pubBin.length && pubBin[i] === 0x00; ++i);
if (i > 0) pubBin = pubBin.slice(i)
}
// Parse private key
reader = new Ber.Reader(priv)
reader.readSequence()
// - Version
if (reader.readInt() !== 0) throw new Error('Unsupported version in ED25519 private key')
// - Algorithm
reader.readSequence()
if (reader.readOID() !== '1.3.101.112') throw new Error('Bad ED25519 private OID')
// - Attributes (absent)
reader = new Ber.Reader(reader.readString(Ber.OctetString, true))
const privBin = reader.readString(Ber.OctetString, true)
/*
OpenSSH ed25519 private key:
string "ssh-ed25519"
string public key
string private key + public key
*/
const keyName = Buffer.from('ssh-ed25519')
const privBuf = Buffer.allocUnsafe(
4 + keyName.length + 4 + pubBin.length + 4 + (privBin.length + pubBin.length)
)
let pos = 0
privBuf.writeUInt32BE(keyName.length, (pos += 0))
privBuf.set(keyName, (pos += 4))
privBuf.writeUInt32BE(pubBin.length, (pos += keyName.length))
privBuf.set(pubBin, (pos += 4))
privBuf.writeUInt32BE(privBin.length + pubBin.length, (pos += pubBin.length))
privBuf.set(privBin, (pos += 4))
privBuf.set(pubBin, (pos += privBin.length))
/*
OpenSSH ed25519 public key:
string "ssh-ed25519"
string public key
*/
const pubBuf = Buffer.allocUnsafe(4 + keyName.length + 4 + pubBin.length)
pos = 0
pubBuf.writeUInt32BE(keyName.length, (pos += 0))
pubBuf.set(keyName, (pos += 4))
pubBuf.writeUInt32BE(pubBin.length, (pos += keyName.length))
pubBuf.set(pubBin, (pos += 4))
return { sshName: keyName.toString(), priv: privBuf, pub: pubBuf }
}
}
}
function convertKeys(keyType, pub, priv, opts) {
let format = 'new'
let encrypted
let comment = ''
if (typeof opts === 'object' && opts !== null) {
if (typeof opts.comment === 'string' && opts.comment) comment = opts.comment
if (typeof opts.format === 'string' && opts.format) format = opts.format
if (opts.passphrase) {
let passphrase
if (typeof opts.passphrase === 'string') passphrase = Buffer.from(opts.passphrase)
else if (Buffer.isBuffer(opts.passphrase)) passphrase = opts.passphrase
else throw new Error('Invalid passphrase')
if (opts.cipher === undefined) throw new Error('Missing cipher name')
const cipher = ciphers.get(opts.cipher)
if (cipher === undefined) throw new Error('Invalid cipher name')
if (format === 'new') {
let rounds = DEFAULT_ROUNDS
if (opts.rounds !== undefined) {
if (!Number.isInteger(opts.rounds)) throw new TypeError('rounds must be an integer')
if (opts.rounds > 0) rounds = opts.rounds
}
const gen = Buffer.allocUnsafe(cipher.keyLen + cipher.ivLen)
const salt = randomBytes(SALT_LEN)
const r = bcrypt_pbkdf(
passphrase,
passphrase.length,
salt,
salt.length,
gen,
gen.length,
rounds
)
if (r !== 0) return new Error('Failed to generate information to encrypt key')
/*
string salt
uint32 rounds
*/
const kdfOptions = Buffer.allocUnsafe(4 + salt.length + 4)
{
let pos = 0
kdfOptions.writeUInt32BE(salt.length, (pos += 0))
kdfOptions.set(salt, (pos += 4))
kdfOptions.writeUInt32BE(rounds, (pos += salt.length))
}
encrypted = {
cipher,
cipherName: opts.cipher,
kdfName: 'bcrypt',
kdfOptions,
key: gen.slice(0, cipher.keyLen),
iv: gen.slice(cipher.keyLen)
}
}
}
}
switch (format) {
case 'new': {
let privateB64 = '-----BEGIN OPENSSH PRIVATE KEY-----\n'
let publicB64
/*
byte[] "openssh-key-v1\0"
string ciphername
string kdfname
string kdfoptions
uint32 number of keys N
string publickey1
string encrypted, padded list of private keys
uint32 checkint
uint32 checkint
byte[] privatekey1
string comment1
byte 1
byte 2
byte 3
...
byte padlen % 255
*/
const cipherName = Buffer.from(encrypted ? encrypted.cipherName : 'none')
const kdfName = Buffer.from(encrypted ? encrypted.kdfName : 'none')
const kdfOptions = encrypted ? encrypted.kdfOptions : Buffer.alloc(0)
const blockLen = encrypted ? encrypted.cipher.blockLen : 8
const parsed = parseDERs(keyType, pub, priv)
const checkInt = randomBytes(4)
const commentBin = Buffer.from(comment)
const privBlobLen = 4 + 4 + parsed.priv.length + 4 + commentBin.length
let padding = []
for (let i = 1; (privBlobLen + padding.length) % blockLen; ++i) padding.push(i & 0xff)
padding = Buffer.from(padding)
let privBlob = Buffer.allocUnsafe(privBlobLen + padding.length)
let extra
{
let pos = 0
privBlob.set(checkInt, (pos += 0))
privBlob.set(checkInt, (pos += 4))
privBlob.set(parsed.priv, (pos += 4))
privBlob.writeUInt32BE(commentBin.length, (pos += parsed.priv.length))
privBlob.set(commentBin, (pos += 4))
privBlob.set(padding, (pos += commentBin.length))
}
if (encrypted) {
const options = { authTagLength: encrypted.cipher.authLen }
const cipher = createCipheriv(
encrypted.cipher.sslName,
encrypted.key,
encrypted.iv,
options
)
cipher.setAutoPadding(false)
privBlob = Buffer.concat([cipher.update(privBlob), cipher.final()])
if (encrypted.cipher.authLen > 0) extra = cipher.getAuthTag()
else extra = Buffer.alloc(0)
encrypted.key.fill(0)
encrypted.iv.fill(0)
} else {
extra = Buffer.alloc(0)
}
const magicBytes = Buffer.from('openssh-key-v1\0')
const privBin = Buffer.allocUnsafe(
magicBytes.length +
4 +
cipherName.length +
4 +
kdfName.length +
4 +
kdfOptions.length +
4 +
4 +
parsed.pub.length +
4 +
privBlob.length +
extra.length
)
{
let pos = 0
privBin.set(magicBytes, (pos += 0))
privBin.writeUInt32BE(cipherName.length, (pos += magicBytes.length))
privBin.set(cipherName, (pos += 4))
privBin.writeUInt32BE(kdfName.length, (pos += cipherName.length))
privBin.set(kdfName, (pos += 4))
privBin.writeUInt32BE(kdfOptions.length, (pos += kdfName.length))
privBin.set(kdfOptions, (pos += 4))
privBin.writeUInt32BE(1, (pos += kdfOptions.length))
privBin.writeUInt32BE(parsed.pub.length, (pos += 4))
privBin.set(parsed.pub, (pos += 4))
privBin.writeUInt32BE(privBlob.length, (pos += parsed.pub.length))
privBin.set(privBlob, (pos += 4))
privBin.set(extra, (pos += privBlob.length))
}
{
const b64 = privBin.base64Slice(0, privBin.length)
let formatted = b64.replace(/.{64}/g, '$&\n')
if (b64.length & 63) formatted += '\n'
privateB64 += formatted
}
{
const b64 = parsed.pub.base64Slice(0, parsed.pub.length)
publicB64 = `${parsed.sshName} ${b64}${comment ? ` ${comment}` : ''}`
}
privateB64 += '-----END OPENSSH PRIVATE KEY-----\n'
return {
private: privateB64,
public: publicB64
}
}
default:
throw new Error('Invalid output key format')
}
}
function noop() {}
module.exports = {
generateKeyPair: (keyType, opts, cb) => {
if (typeof opts === 'function') {
cb = opts
opts = undefined
}
if (typeof cb !== 'function') cb = noop
const args = makeArgs(keyType, opts)
generateKeyPair_(...args, (err, pub, priv) => {
if (err) return cb(err)
let ret
try {
ret = convertKeys(args[0], pub, priv, opts)
} catch (ex) {
return cb(ex)
}
cb(null, ret)
})
},
generateKeyPairSync: (keyType, opts) => {
const args = makeArgs(keyType, opts)
const { publicKey: pub, privateKey: priv } = generateKeyPairSync_(...args)
return convertKeys(args[0], pub, priv, opts)
}
}
File diff suppressed because it is too large Load Diff
+3661
View File
File diff suppressed because it is too large Load Diff
+361
View File
@@ -0,0 +1,361 @@
'use strict'
const crypto = require('crypto')
let cpuInfo
try {
cpuInfo = require('cpu-features')()
} catch {}
const { bindingAvailable, CIPHER_INFO, MAC_INFO } = require('./crypto.js')
const eddsaSupported = (() => {
if (typeof crypto.sign === 'function' && typeof crypto.verify === 'function') {
const key =
'-----BEGIN PRIVATE KEY-----\r\nMC4CAQAwBQYDK2VwBCIEIHKj+sVa9WcD' +
'/q2DJUJaf43Kptc8xYuUQA4bOFj9vC8T\r\n-----END PRIVATE KEY-----'
const data = Buffer.from('a')
let sig
let verified
try {
sig = crypto.sign(null, data, key)
verified = crypto.verify(null, data, key, sig)
} catch {}
return Buffer.isBuffer(sig) && sig.length === 64 && verified === true
}
return false
})()
const curve25519Supported =
typeof crypto.diffieHellman === 'function' &&
typeof crypto.generateKeyPairSync === 'function' &&
typeof crypto.createPublicKey === 'function'
const DEFAULT_KEX = [
// https://tools.ietf.org/html/rfc5656#section-10.1
'ecdh-sha2-nistp256',
'ecdh-sha2-nistp384',
'ecdh-sha2-nistp521',
// https://tools.ietf.org/html/rfc4419#section-4
'diffie-hellman-group-exchange-sha256',
// https://tools.ietf.org/html/rfc8268
'diffie-hellman-group14-sha256',
'diffie-hellman-group15-sha512',
'diffie-hellman-group16-sha512',
'diffie-hellman-group17-sha512',
'diffie-hellman-group18-sha512'
]
if (curve25519Supported) {
DEFAULT_KEX.unshift('curve25519-sha256')
DEFAULT_KEX.unshift('[email protected]')
}
const SUPPORTED_KEX = DEFAULT_KEX.concat([
// https://tools.ietf.org/html/rfc4419#section-4
'diffie-hellman-group-exchange-sha1',
'diffie-hellman-group14-sha1', // REQUIRED
'diffie-hellman-group1-sha1' // REQUIRED
])
const DEFAULT_SERVER_HOST_KEY = [
'ecdsa-sha2-nistp256',
'ecdsa-sha2-nistp384',
'ecdsa-sha2-nistp521',
'rsa-sha2-512', // RFC 8332
'rsa-sha2-256', // RFC 8332
'ssh-rsa'
]
if (eddsaSupported) DEFAULT_SERVER_HOST_KEY.unshift('ssh-ed25519')
const SUPPORTED_SERVER_HOST_KEY = DEFAULT_SERVER_HOST_KEY.concat(['ssh-dss'])
const canUseCipher = (() => {
const ciphers = crypto.getCiphers()
return (name) => ciphers.includes(CIPHER_INFO[name].sslName)
})()
let DEFAULT_CIPHER = [
// http://tools.ietf.org/html/rfc5647
'[email protected]',
'[email protected]',
// http://tools.ietf.org/html/rfc4344#section-4
'aes128-ctr',
'aes192-ctr',
'aes256-ctr'
]
if (cpuInfo && cpuInfo.flags && !cpuInfo.flags.aes) {
// We know for sure the CPU does not support AES acceleration
if (bindingAvailable) DEFAULT_CIPHER.unshift('[email protected]')
else DEFAULT_CIPHER.push('[email protected]')
} else if (bindingAvailable && cpuInfo && cpuInfo.arch === 'x86') {
// Places chacha20-poly1305 immediately after GCM ciphers since GCM ciphers
// seem to outperform it on x86, but it seems to be faster than CTR ciphers
DEFAULT_CIPHER.splice(4, 0, '[email protected]')
} else {
DEFAULT_CIPHER.push('[email protected]')
}
DEFAULT_CIPHER = DEFAULT_CIPHER.filter(canUseCipher)
const SUPPORTED_CIPHER = DEFAULT_CIPHER.concat(
[
'aes256-cbc',
'aes192-cbc',
'aes128-cbc',
'blowfish-cbc',
'3des-cbc',
'aes128-gcm',
'aes256-gcm',
// http://tools.ietf.org/html/rfc4345#section-4:
'arcfour256',
'arcfour128',
'cast128-cbc',
'arcfour'
].filter(canUseCipher)
)
const canUseMAC = (() => {
const hashes = crypto.getHashes()
return (name) => hashes.includes(MAC_INFO[name].sslName)
})()
const DEFAULT_MAC = [
'[email protected]',
'[email protected]',
'[email protected]',
'hmac-sha2-256',
'hmac-sha2-512',
'hmac-sha1'
].filter(canUseMAC)
const SUPPORTED_MAC = DEFAULT_MAC.concat(
[
'hmac-md5',
'hmac-sha2-256-96', // first 96 bits of HMAC-SHA256
'hmac-sha2-512-96', // first 96 bits of HMAC-SHA512
'hmac-ripemd160',
'hmac-sha1-96', // first 96 bits of HMAC-SHA1
'hmac-md5-96' // first 96 bits of HMAC-MD5
].filter(canUseMAC)
)
const DEFAULT_COMPRESSION = [
'none',
'[email protected]', // ZLIB (LZ77) compression, except
// compression/decompression does not start until after
// successful user authentication
'zlib' // ZLIB (LZ77) compression
]
const SUPPORTED_COMPRESSION = DEFAULT_COMPRESSION.concat([])
const COMPAT = {
BAD_DHGEX: 1 << 0,
OLD_EXIT: 1 << 1,
DYN_RPORT_BUG: 1 << 2,
BUG_DHGEX_LARGE: 1 << 3,
IMPLY_RSA_SHA2_SIGALGS: 1 << 4
}
module.exports = {
MESSAGE: {
// Transport layer protocol -- generic (1-19)
DISCONNECT: 1,
IGNORE: 2,
UNIMPLEMENTED: 3,
DEBUG: 4,
SERVICE_REQUEST: 5,
SERVICE_ACCEPT: 6,
EXT_INFO: 7, // RFC 8308
// Transport layer protocol -- algorithm negotiation (20-29)
KEXINIT: 20,
NEWKEYS: 21,
// Transport layer protocol -- key exchange method-specific (30-49)
KEXDH_INIT: 30,
KEXDH_REPLY: 31,
KEXDH_GEX_GROUP: 31,
KEXDH_GEX_INIT: 32,
KEXDH_GEX_REPLY: 33,
KEXDH_GEX_REQUEST: 34,
KEXECDH_INIT: 30,
KEXECDH_REPLY: 31,
// User auth protocol -- generic (50-59)
USERAUTH_REQUEST: 50,
USERAUTH_FAILURE: 51,
USERAUTH_SUCCESS: 52,
USERAUTH_BANNER: 53,
// User auth protocol -- user auth method-specific (60-79)
USERAUTH_PASSWD_CHANGEREQ: 60,
USERAUTH_PK_OK: 60,
USERAUTH_INFO_REQUEST: 60,
USERAUTH_INFO_RESPONSE: 61,
// Connection protocol -- generic (80-89)
GLOBAL_REQUEST: 80,
REQUEST_SUCCESS: 81,
REQUEST_FAILURE: 82,
// Connection protocol -- channel-related (90-127)
CHANNEL_OPEN: 90,
CHANNEL_OPEN_CONFIRMATION: 91,
CHANNEL_OPEN_FAILURE: 92,
CHANNEL_WINDOW_ADJUST: 93,
CHANNEL_DATA: 94,
CHANNEL_EXTENDED_DATA: 95,
CHANNEL_EOF: 96,
CHANNEL_CLOSE: 97,
CHANNEL_REQUEST: 98,
CHANNEL_SUCCESS: 99,
CHANNEL_FAILURE: 100
// Reserved for client protocols (128-191)
// Local extensions (192-155)
},
DISCONNECT_REASON: {
HOST_NOT_ALLOWED_TO_CONNECT: 1,
PROTOCOL_ERROR: 2,
KEY_EXCHANGE_FAILED: 3,
RESERVED: 4,
MAC_ERROR: 5,
COMPRESSION_ERROR: 6,
SERVICE_NOT_AVAILABLE: 7,
PROTOCOL_VERSION_NOT_SUPPORTED: 8,
HOST_KEY_NOT_VERIFIABLE: 9,
CONNECTION_LOST: 10,
BY_APPLICATION: 11,
TOO_MANY_CONNECTIONS: 12,
AUTH_CANCELED_BY_USER: 13,
NO_MORE_AUTH_METHODS_AVAILABLE: 14,
ILLEGAL_USER_NAME: 15
},
DISCONNECT_REASON_STR: undefined,
CHANNEL_OPEN_FAILURE: {
ADMINISTRATIVELY_PROHIBITED: 1,
CONNECT_FAILED: 2,
UNKNOWN_CHANNEL_TYPE: 3,
RESOURCE_SHORTAGE: 4
},
TERMINAL_MODE: {
TTY_OP_END: 0, // Indicates end of options.
VINTR: 1, // Interrupt character; 255 if none. Similarly for the
// other characters. Not all of these characters are
// supported on all systems.
VQUIT: 2, // The quit character (sends SIGQUIT signal on POSIX
// systems).
VERASE: 3, // Erase the character to left of the cursor.
VKILL: 4, // Kill the current input line.
VEOF: 5, // End-of-file character (sends EOF from the
// terminal).
VEOL: 6, // End-of-line character in addition to carriage
// return and/or linefeed.
VEOL2: 7, // Additional end-of-line character.
VSTART: 8, // Continues paused output (normally control-Q).
VSTOP: 9, // Pauses output (normally control-S).
VSUSP: 10, // Suspends the current program.
VDSUSP: 11, // Another suspend character.
VREPRINT: 12, // Reprints the current input line.
VWERASE: 13, // Erases a word left of cursor.
VLNEXT: 14, // Enter the next character typed literally, even if
// it is a special character
VFLUSH: 15, // Character to flush output.
VSWTCH: 16, // Switch to a different shell layer.
VSTATUS: 17, // Prints system status line (load, command, pid,
// etc).
VDISCARD: 18, // Toggles the flushing of terminal output.
IGNPAR: 30, // The ignore parity flag. The parameter SHOULD be 0
// if this flag is FALSE, and 1 if it is TRUE.
PARMRK: 31, // Mark parity and framing errors.
INPCK: 32, // Enable checking of parity errors.
ISTRIP: 33, // Strip 8th bit off characters.
INLCR: 34, // Map NL into CR on input.
IGNCR: 35, // Ignore CR on input.
ICRNL: 36, // Map CR to NL on input.
IUCLC: 37, // Translate uppercase characters to lowercase.
IXON: 38, // Enable output flow control.
IXANY: 39, // Any char will restart after stop.
IXOFF: 40, // Enable input flow control.
IMAXBEL: 41, // Ring bell on input queue full.
ISIG: 50, // Enable signals INTR, QUIT, [D]SUSP.
ICANON: 51, // Canonicalize input lines.
XCASE: 52, // Enable input and output of uppercase characters by
// preceding their lowercase equivalents with "\".
ECHO: 53, // Enable echoing.
ECHOE: 54, // Visually erase chars.
ECHOK: 55, // Kill character discards current line.
ECHONL: 56, // Echo NL even if ECHO is off.
NOFLSH: 57, // Don't flush after interrupt.
TOSTOP: 58, // Stop background jobs from output.
IEXTEN: 59, // Enable extensions.
ECHOCTL: 60, // Echo control characters as ^(Char).
ECHOKE: 61, // Visual erase for line kill.
PENDIN: 62, // Retype pending input.
OPOST: 70, // Enable output processing.
OLCUC: 71, // Convert lowercase to uppercase.
ONLCR: 72, // Map NL to CR-NL.
OCRNL: 73, // Translate carriage return to newline (output).
ONOCR: 74, // Translate newline to carriage return-newline
// (output).
ONLRET: 75, // Newline performs a carriage return (output).
CS7: 90, // 7 bit mode.
CS8: 91, // 8 bit mode.
PARENB: 92, // Parity enable.
PARODD: 93, // Odd parity, else even.
TTY_OP_ISPEED: 128, // Specifies the input baud rate in bits per second.
TTY_OP_OSPEED: 129 // Specifies the output baud rate in bits per second.
},
CHANNEL_EXTENDED_DATATYPE: {
STDERR: 1
},
SIGNALS: [
'ABRT',
'ALRM',
'FPE',
'HUP',
'ILL',
'INT',
'QUIT',
'SEGV',
'TERM',
'USR1',
'USR2',
'KILL',
'PIPE'
].reduce((cur, val) => ({ ...cur, [val]: 1 }), {}),
COMPAT,
COMPAT_CHECKS: [
['Cisco-1.25', COMPAT.BAD_DHGEX],
[/^Cisco-1[.]/, COMPAT.BUG_DHGEX_LARGE],
[/^[0-9.]+$/, COMPAT.OLD_EXIT], // old SSH.com implementations
[/^OpenSSH_5[.][0-9]+/, COMPAT.DYN_RPORT_BUG],
[/^OpenSSH_7[.]4/, COMPAT.IMPLY_RSA_SHA2_SIGALGS]
],
// KEX proposal-related
DEFAULT_KEX,
SUPPORTED_KEX,
DEFAULT_SERVER_HOST_KEY,
SUPPORTED_SERVER_HOST_KEY,
DEFAULT_CIPHER,
SUPPORTED_CIPHER,
DEFAULT_MAC,
SUPPORTED_MAC,
DEFAULT_COMPRESSION,
SUPPORTED_COMPRESSION,
curve25519Supported,
eddsaSupported
}
module.exports.DISCONNECT_REASON_BY_VALUE = Array.from(
Object.entries(module.exports.DISCONNECT_REASON)
).reduce((obj, [key, value]) => ({ ...obj, [value]: key }), {})
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+13
View File
@@ -0,0 +1,13 @@
'use strict'
const MESSAGE_HANDLERS = new Array(256)
;[require('./kex.js').HANDLERS, require('./handlers.misc.js')].forEach((handlers) => {
// eslint-disable-next-line prefer-const
for (let [type, handler] of Object.entries(handlers)) {
type = +type
if (isFinite(type) && type >= 0 && type < MESSAGE_HANDLERS.length)
MESSAGE_HANDLERS[type] = handler
}
})
module.exports = MESSAGE_HANDLERS
File diff suppressed because it is too large Load Diff
+1777
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+110
View File
@@ -0,0 +1,110 @@
'use strict'
const assert = require('assert')
const { inspect } = require('util')
// Only use this for integers! Decimal numbers do not work with this function.
function addNumericalSeparator(val) {
let res = ''
let i = val.length
const start = val[0] === '-' ? 1 : 0
for (; i >= start + 4; i -= 3) res = `_${val.slice(i - 3, i)}${res}`
return `${val.slice(0, i)}${res}`
}
function oneOf(expected, thing) {
assert(typeof thing === 'string', '`thing` has to be of type string')
if (Array.isArray(expected)) {
const len = expected.length
assert(len > 0, 'At least one expected value needs to be specified')
expected = expected.map((i) => String(i))
if (len > 2) {
return `one of ${thing} ${expected.slice(0, len - 1).join(', ')}, or ` + expected[len - 1]
} else if (len === 2) {
return `one of ${thing} ${expected[0]} or ${expected[1]}`
}
return `of ${thing} ${expected[0]}`
}
return `of ${thing} ${String(expected)}`
}
exports.ERR_INTERNAL_ASSERTION = class ERR_INTERNAL_ASSERTION extends Error {
constructor(message) {
super()
Error.captureStackTrace(this, ERR_INTERNAL_ASSERTION)
const suffix =
'This is caused by either a bug in ssh2 ' +
'or incorrect usage of ssh2 internals.\n' +
'Please open an issue with this stack trace at ' +
'https://github.com/mscdex/ssh2/issues\n'
this.message = message === undefined ? suffix : `${message}\n${suffix}`
}
}
const MAX_32BIT_INT = 2 ** 32
const MAX_32BIT_BIGINT = (() => {
try {
return new Function('return 2n ** 32n')()
} catch {}
})()
exports.ERR_OUT_OF_RANGE = class ERR_OUT_OF_RANGE extends RangeError {
constructor(str, range, input, replaceDefaultBoolean) {
super()
Error.captureStackTrace(this, ERR_OUT_OF_RANGE)
assert(range, 'Missing "range" argument')
let msg = replaceDefaultBoolean ? str : `The value of "${str}" is out of range.`
let received
if (Number.isInteger(input) && Math.abs(input) > MAX_32BIT_INT) {
received = addNumericalSeparator(String(input))
} else if (typeof input === 'bigint') {
received = String(input)
if (input > MAX_32BIT_BIGINT || input < -MAX_32BIT_BIGINT)
received = addNumericalSeparator(received)
received += 'n'
} else {
received = inspect(input)
}
msg += ` It must be ${range}. Received ${received}`
this.message = msg
}
}
class ERR_INVALID_ARG_TYPE extends TypeError {
constructor(name, expected, actual) {
super()
Error.captureStackTrace(this, ERR_INVALID_ARG_TYPE)
assert(typeof name === 'string', `'name' must be a string`)
// determiner: 'must be' or 'must not be'
let determiner
if (typeof expected === 'string' && expected.startsWith('not ')) {
determiner = 'must not be'
expected = expected.replace(/^not /, '')
} else {
determiner = 'must be'
}
let msg
if (name.endsWith(' argument')) {
// For cases like 'first argument'
msg = `The ${name} ${determiner} ${oneOf(expected, 'type')}`
} else {
const type = name.includes('.') ? 'property' : 'argument'
msg = `The "${name}" ${type} ${determiner} ${oneOf(expected, 'type')}`
}
msg += `. Received type ${typeof actual}`
this.message = msg
}
}
exports.ERR_INVALID_ARG_TYPE = ERR_INVALID_ARG_TYPE
exports.validateNumber = function validateNumber(value, name) {
if (typeof value !== 'number') throw new ERR_INVALID_ARG_TYPE(name, 'number', value)
}
+316
View File
@@ -0,0 +1,316 @@
'use strict'
const Ber = require('asn1').Ber
let DISCONNECT_REASON
const FastBuffer = Buffer[Symbol.species]
const TypedArrayFill = Object.getPrototypeOf(Uint8Array.prototype).fill
function readUInt32BE(buf, offset) {
return buf[offset++] * 16777216 + buf[offset++] * 65536 + buf[offset++] * 256 + buf[offset]
}
function bufferCopy(src, dest, srcStart, srcEnd, destStart) {
if (!destStart) destStart = 0
if (srcEnd > src.length) srcEnd = src.length
let nb = srcEnd - srcStart
const destLeft = dest.length - destStart
if (nb > destLeft) nb = destLeft
dest.set(new Uint8Array(src.buffer, src.byteOffset + srcStart, nb), destStart)
return nb
}
function bufferSlice(buf, start, end) {
if (end === undefined) end = buf.length
return new FastBuffer(buf.buffer, buf.byteOffset + start, end - start)
}
function makeBufferParser() {
let pos = 0
let buffer
const self = {
init: (buf, start) => {
buffer = buf
pos = typeof start === 'number' ? start : 0
},
pos: () => pos,
length: () => (buffer ? buffer.length : 0),
avail: () => (buffer && pos < buffer.length ? buffer.length - pos : 0),
clear: () => {
buffer = undefined
},
readUInt32BE: () => {
if (!buffer || pos + 3 >= buffer.length) return
return buffer[pos++] * 16777216 + buffer[pos++] * 65536 + buffer[pos++] * 256 + buffer[pos++]
},
readUInt64BE: (behavior) => {
if (!buffer || pos + 7 >= buffer.length) return
switch (behavior) {
case 'always':
return BigInt(`0x${buffer.hexSlice(pos, (pos += 8))}`)
case 'maybe':
if (buffer[pos] > 0x1f) return BigInt(`0x${buffer.hexSlice(pos, (pos += 8))}`)
// FALLTHROUGH
default:
return (
buffer[pos++] * 72057594037927940 +
buffer[pos++] * 281474976710656 +
buffer[pos++] * 1099511627776 +
buffer[pos++] * 4294967296 +
buffer[pos++] * 16777216 +
buffer[pos++] * 65536 +
buffer[pos++] * 256 +
buffer[pos++]
)
}
},
skip: (n) => {
if (buffer && n > 0) pos += n
},
skipString: () => {
const len = self.readUInt32BE()
if (len === undefined) return
pos += len
return pos <= buffer.length ? len : undefined
},
readByte: () => {
if (buffer && pos < buffer.length) return buffer[pos++]
},
readBool: () => {
if (buffer && pos < buffer.length) return !!buffer[pos++]
},
readList: () => {
const list = self.readString(true)
if (list === undefined) return
return list ? list.split(',') : []
},
readString: (dest, maxLen) => {
if (typeof dest === 'number') {
maxLen = dest
dest = undefined
}
const len = self.readUInt32BE()
if (len === undefined) return
if (buffer.length - pos < len || (typeof maxLen === 'number' && len > maxLen)) {
return
}
if (dest) {
if (Buffer.isBuffer(dest)) return bufferCopy(buffer, dest, pos, (pos += len))
return buffer.toString('utf8', pos, (pos += len))
}
return bufferSlice(buffer, pos, (pos += len))
},
readRaw: (len) => {
if (!buffer) return
if (typeof len !== 'number') return bufferSlice(buffer, pos, (pos += buffer.length - pos))
if (buffer.length - pos >= len) return bufferSlice(buffer, pos, (pos += len))
}
}
return self
}
function makeError(msg, level, fatal) {
const err = new Error(msg)
if (typeof level === 'boolean') {
fatal = level
err.level = 'protocol'
} else {
err.level = level || 'protocol'
}
err.fatal = !!fatal
return err
}
function writeUInt32BE(buf, value, offset) {
buf[offset++] = value >>> 24
buf[offset++] = value >>> 16
buf[offset++] = value >>> 8
buf[offset++] = value
return offset
}
const utilBufferParser = makeBufferParser()
module.exports = {
bufferCopy,
bufferSlice,
FastBuffer,
bufferFill: (buf, value, start, end) => {
return TypedArrayFill.call(buf, value, start, end)
},
makeError,
doFatalError: (protocol, msg, level, reason) => {
let err
if (DISCONNECT_REASON === undefined) ({ DISCONNECT_REASON } = require('./constants.js'))
if (msg instanceof Error) {
// doFatalError(protocol, err[, reason])
err = msg
if (typeof level !== 'number') reason = DISCONNECT_REASON.PROTOCOL_ERROR
else reason = level
} else {
// doFatalError(protocol, msg[, level[, reason]])
err = makeError(msg, level, true)
}
if (typeof reason !== 'number') reason = DISCONNECT_REASON.PROTOCOL_ERROR
protocol.disconnect(reason)
protocol._destruct()
protocol._onError(err)
return Infinity
},
readUInt32BE,
writeUInt32BE,
writeUInt32LE: (buf, value, offset) => {
buf[offset++] = value
buf[offset++] = value >>> 8
buf[offset++] = value >>> 16
buf[offset++] = value >>> 24
return offset
},
makeBufferParser,
bufferParser: makeBufferParser(),
readString: (buffer, start, dest, maxLen) => {
if (typeof dest === 'number') {
maxLen = dest
dest = undefined
}
if (start === undefined) start = 0
const left = buffer.length - start
if (start < 0 || start >= buffer.length || left < 4) return
const len = readUInt32BE(buffer, start)
if (left < 4 + len || (typeof maxLen === 'number' && len > maxLen)) return
start += 4
const end = start + len
buffer._pos = end
if (dest) {
if (Buffer.isBuffer(dest)) return bufferCopy(buffer, dest, start, end)
return buffer.toString('utf8', start, end)
}
return bufferSlice(buffer, start, end)
},
sigSSHToASN1: (sig, type) => {
switch (type) {
case 'ssh-dss': {
if (sig.length > 40) return sig
// Change bare signature r and s values to ASN.1 BER values for OpenSSL
const asnWriter = new Ber.Writer()
asnWriter.startSequence()
let r = sig.slice(0, 20)
let s = sig.slice(20)
if (r[0] & 0x80) {
const rNew = Buffer.allocUnsafe(21)
rNew[0] = 0x00
r.copy(rNew, 1)
r = rNew
} else if (r[0] === 0x00 && !(r[1] & 0x80)) {
r = r.slice(1)
}
if (s[0] & 0x80) {
const sNew = Buffer.allocUnsafe(21)
sNew[0] = 0x00
s.copy(sNew, 1)
s = sNew
} else if (s[0] === 0x00 && !(s[1] & 0x80)) {
s = s.slice(1)
}
asnWriter.writeBuffer(r, Ber.Integer)
asnWriter.writeBuffer(s, Ber.Integer)
asnWriter.endSequence()
return asnWriter.buffer
}
case 'ecdsa-sha2-nistp256':
case 'ecdsa-sha2-nistp384':
case 'ecdsa-sha2-nistp521': {
utilBufferParser.init(sig, 0)
const r = utilBufferParser.readString()
const s = utilBufferParser.readString()
utilBufferParser.clear()
if (r === undefined || s === undefined) return
const asnWriter = new Ber.Writer()
asnWriter.startSequence()
asnWriter.writeBuffer(r, Ber.Integer)
asnWriter.writeBuffer(s, Ber.Integer)
asnWriter.endSequence()
return asnWriter.buffer
}
default:
return sig
}
},
convertSignature: (signature, keyType) => {
switch (keyType) {
case 'ssh-dss': {
if (signature.length <= 40) return signature
// This is a quick and dirty way to get from BER encoded r and s that
// OpenSSL gives us, to just the bare values back to back (40 bytes
// total) like OpenSSH (and possibly others) are expecting
const asnReader = new Ber.Reader(signature)
asnReader.readSequence()
let r = asnReader.readString(Ber.Integer, true)
let s = asnReader.readString(Ber.Integer, true)
let rOffset = 0
let sOffset = 0
if (r.length < 20) {
const rNew = Buffer.allocUnsafe(20)
rNew.set(r, 1)
r = rNew
r[0] = 0
}
if (s.length < 20) {
const sNew = Buffer.allocUnsafe(20)
sNew.set(s, 1)
s = sNew
s[0] = 0
}
if (r.length > 20 && r[0] === 0) rOffset = 1
if (s.length > 20 && s[0] === 0) sOffset = 1
const newSig = Buffer.allocUnsafe(r.length - rOffset + (s.length - sOffset))
bufferCopy(r, newSig, rOffset, r.length, 0)
bufferCopy(s, newSig, sOffset, s.length, r.length - rOffset)
return newSig
}
case 'ecdsa-sha2-nistp256':
case 'ecdsa-sha2-nistp384':
case 'ecdsa-sha2-nistp521': {
if (signature[0] === 0) return signature
// Convert SSH signature parameters to ASN.1 BER values for OpenSSL
const asnReader = new Ber.Reader(signature)
asnReader.readSequence()
const r = asnReader.readString(Ber.Integer, true)
const s = asnReader.readString(Ber.Integer, true)
if (r === null || s === null) return
const newSig = Buffer.allocUnsafe(4 + r.length + 4 + s.length)
writeUInt32BE(newSig, r.length, 0)
newSig.set(r, 4)
writeUInt32BE(newSig, s.length, 4 + r.length)
newSig.set(s, 4 + 4 + r.length)
return newSig
}
}
return signature
},
sendPacket: (proto, packet, bypass) => {
if (!bypass && proto._kexinit !== undefined) {
// We're currently in the middle of a handshake
if (proto._queue === undefined) proto._queue = []
proto._queue.push(packet)
proto._debug && proto._debug('Outbound: ... packet queued')
return false
}
proto._cipher.encrypt(packet)
return true
}
}
+246
View File
@@ -0,0 +1,246 @@
'use strict'
const { kMaxLength } = require('buffer')
const {
createInflate,
constants: {
DEFLATE,
INFLATE,
Z_DEFAULT_CHUNK,
Z_DEFAULT_COMPRESSION,
Z_DEFAULT_MEMLEVEL,
Z_DEFAULT_STRATEGY,
Z_DEFAULT_WINDOWBITS,
Z_PARTIAL_FLUSH
}
} = require('zlib')
const ZlibHandle = createInflate()._handle.constructor
function processCallback() {
throw new Error('Should not get here')
}
function zlibOnError(message, errno, code) {
const self = this._owner
// There is no way to cleanly recover.
// Continuing only obscures problems.
const error = new Error(message)
error.errno = errno
error.code = code
self._err = error
}
function _close(engine) {
// Caller may invoke .close after a zlib error (which will null _handle).
if (!engine._handle) return
engine._handle.close()
engine._handle = null
}
class Zlib {
constructor(mode) {
const windowBits = Z_DEFAULT_WINDOWBITS
const level = Z_DEFAULT_COMPRESSION
const memLevel = Z_DEFAULT_MEMLEVEL
const strategy = Z_DEFAULT_STRATEGY
const dictionary = undefined
this._err = undefined
this._writeState = new Uint32Array(2)
this._chunkSize = Z_DEFAULT_CHUNK
this._maxOutputLength = kMaxLength
this._outBuffer = Buffer.allocUnsafe(this._chunkSize)
this._outOffset = 0
this._handle = new ZlibHandle(mode)
this._handle._owner = this
this._handle.onerror = zlibOnError
this._handle.init(
windowBits,
level,
memLevel,
strategy,
this._writeState,
processCallback,
dictionary
)
}
writeSync(chunk, retChunks) {
const handle = this._handle
if (!handle) throw new Error('Invalid Zlib instance')
let availInBefore = chunk.length
let availOutBefore = this._chunkSize - this._outOffset
let inOff = 0
let availOutAfter
let availInAfter
let buffers
let nread = 0
const state = this._writeState
let buffer = this._outBuffer
let offset = this._outOffset
const chunkSize = this._chunkSize
while (true) {
handle.writeSync(
Z_PARTIAL_FLUSH,
chunk, // in
inOff, // in_off
availInBefore, // in_len
buffer, // out
offset, // out_off
availOutBefore
) // out_len
if (this._err) throw this._err
availOutAfter = state[0]
availInAfter = state[1]
const inDelta = availInBefore - availInAfter
const have = availOutBefore - availOutAfter
if (have > 0) {
const out =
offset === 0 && have === buffer.length ? buffer : buffer.slice(offset, offset + have)
offset += have
if (!buffers) buffers = out
else if (buffers.push === undefined) buffers = [buffers, out]
else buffers.push(out)
nread += out.byteLength
if (nread > this._maxOutputLength) {
_close(this)
throw new Error(`Output length exceeded maximum of ${this._maxOutputLength}`)
}
} else if (have !== 0) {
throw new Error('have should not go down')
}
// Exhausted the output buffer, or used all the input create a new one.
if (availOutAfter === 0 || offset >= chunkSize) {
availOutBefore = chunkSize
offset = 0
buffer = Buffer.allocUnsafe(chunkSize)
}
if (availOutAfter === 0) {
// Not actually done. Need to reprocess.
// Also, update the availInBefore to the availInAfter value,
// so that if we have to hit it a third (fourth, etc.) time,
// it'll have the correct byte counts.
inOff += inDelta
availInBefore = availInAfter
} else {
break
}
}
this._outBuffer = buffer
this._outOffset = offset
if (nread === 0) buffers = Buffer.alloc(0)
if (retChunks) {
buffers.totalLen = nread
return buffers
}
if (buffers.push === undefined) return buffers
const output = Buffer.allocUnsafe(nread)
for (let i = 0, p = 0; i < buffers.length; ++i) {
const buf = buffers[i]
output.set(buf, p)
p += buf.length
}
return output
}
}
class ZlibPacketWriter {
constructor(protocol) {
this.allocStart = 0
this.allocStartKEX = 0
this._protocol = protocol
this._zlib = new Zlib(DEFLATE)
}
cleanup() {
if (this._zlib) _close(this._zlib)
}
alloc(payloadSize, force) {
return Buffer.allocUnsafe(payloadSize)
}
finalize(payload, force) {
if (this._protocol._kexinit === undefined || force) {
const output = this._zlib.writeSync(payload, true)
const packet = this._protocol._cipher.allocPacket(output.totalLen)
if (output.push === undefined) {
packet.set(output, 5)
} else {
for (let i = 0, p = 5; i < output.length; ++i) {
const chunk = output[i]
packet.set(chunk, p)
p += chunk.length
}
}
return packet
}
return payload
}
}
class PacketWriter {
constructor(protocol) {
this.allocStart = 5
this.allocStartKEX = 5
this._protocol = protocol
}
cleanup() {}
alloc(payloadSize, force) {
if (this._protocol._kexinit === undefined || force)
return this._protocol._cipher.allocPacket(payloadSize)
return Buffer.allocUnsafe(payloadSize)
}
finalize(packet, force) {
return packet
}
}
class ZlibPacketReader {
constructor() {
this._zlib = new Zlib(INFLATE)
}
cleanup() {
if (this._zlib) _close(this._zlib)
}
read(data) {
return this._zlib.writeSync(data, false)
}
}
class PacketReader {
cleanup() {}
read(data) {
return data
}
}
module.exports = {
PacketReader,
PacketWriter,
ZlibPacketReader,
ZlibPacketWriter
}
+1292
View File
File diff suppressed because it is too large Load Diff
+304
View File
@@ -0,0 +1,304 @@
'use strict'
const { SFTP } = require('./protocol/SFTP.js')
const MAX_CHANNEL = 2 ** 32 - 1
function onChannelOpenFailure(self, recipient, info, cb) {
self._chanMgr.remove(recipient)
if (typeof cb !== 'function') return
let err
if (info instanceof Error) {
err = info
} else if (typeof info === 'object' && info !== null) {
err = new Error(`(SSH) Channel open failure: ${info.description}`)
err.reason = info.reason
} else {
err = new Error('(SSH) Channel open failure: server closed channel unexpectedly')
err.reason = ''
}
cb(err)
}
function onCHANNEL_CLOSE(self, recipient, channel, err, dead) {
if (typeof channel === 'function') {
// We got CHANNEL_CLOSE instead of CHANNEL_OPEN_FAILURE when
// requesting to open a channel
onChannelOpenFailure(self, recipient, err, channel)
return
}
if (typeof channel !== 'object' || channel === null) return
if (channel.incoming && channel.incoming.state === 'closed') return
self._chanMgr.remove(recipient)
if (channel.server && channel.constructor.name === 'Session') return
channel.incoming.state = 'closed'
if (channel.readable) channel.push(null)
if (channel.server) {
if (channel.stderr.writable) channel.stderr.end()
} else if (channel.stderr.readable) {
channel.stderr.push(null)
}
if (
channel.constructor !== SFTP &&
(channel.outgoing.state === 'open' || channel.outgoing.state === 'eof') &&
!dead
) {
channel.close()
}
if (channel.outgoing.state === 'closing') channel.outgoing.state = 'closed'
const readState = channel._readableState
const writeState = channel._writableState
if (writeState && !writeState.ending && !writeState.finished && !dead) channel.end()
// Take care of any outstanding channel requests
const chanCallbacks = channel._callbacks
channel._callbacks = []
for (let i = 0; i < chanCallbacks.length; ++i) chanCallbacks[i](true)
if (channel.server) {
if (!channel.readable || channel.destroyed || (readState && readState.endEmitted)) {
channel.emit('close')
} else {
channel.once('end', () => channel.emit('close'))
}
} else {
let doClose
switch (channel.type) {
case '[email protected]':
case 'direct-tcpip':
doClose = () => channel.emit('close')
break
default: {
// Align more with node child processes, where the close event gets
// the same arguments as the exit event
const exit = channel._exit
doClose = () => {
if (exit.code === null)
channel.emit('close', exit.code, exit.signal, exit.dump, exit.desc)
else channel.emit('close', exit.code)
}
}
}
if (!channel.readable || channel.destroyed || (readState && readState.endEmitted)) {
doClose()
} else {
channel.once('end', doClose)
}
const errReadState = channel.stderr._readableState
if (
!channel.stderr.readable ||
channel.stderr.destroyed ||
(errReadState && errReadState.endEmitted)
) {
channel.stderr.emit('close')
} else {
channel.stderr.once('end', () => channel.stderr.emit('close'))
}
}
}
class ChannelManager {
constructor(client) {
this._client = client
this._channels = {}
this._cur = -1
this._count = 0
}
add(val) {
// Attempt to reserve an id
let id
// Optimized paths
if (this._cur < MAX_CHANNEL) {
id = ++this._cur
} else if (this._count === 0) {
// Revert and reset back to fast path once we no longer have any channels
// open
this._cur = 0
id = 0
} else {
// Slower lookup path
// This path is triggered we have opened at least MAX_CHANNEL channels
// while having at least one channel open at any given time, so we have
// to search for a free id.
const channels = this._channels
for (let i = 0; i < MAX_CHANNEL; ++i) {
if (channels[i] === undefined) {
id = i
break
}
}
}
if (id === undefined) return -1
this._channels[id] = val || true
++this._count
return id
}
update(id, val) {
if (typeof id !== 'number' || id < 0 || id >= MAX_CHANNEL || !isFinite(id))
throw new Error(`Invalid channel id: ${id}`)
if (val && this._channels[id]) this._channels[id] = val
}
get(id) {
if (typeof id !== 'number' || id < 0 || id >= MAX_CHANNEL || !isFinite(id))
throw new Error(`Invalid channel id: ${id}`)
return this._channels[id]
}
remove(id) {
if (typeof id !== 'number' || id < 0 || id >= MAX_CHANNEL || !isFinite(id))
throw new Error(`Invalid channel id: ${id}`)
if (this._channels[id]) {
delete this._channels[id]
if (this._count) --this._count
}
}
cleanup(err) {
const channels = this._channels
this._channels = {}
this._cur = -1
this._count = 0
const chanIDs = Object.keys(channels)
const client = this._client
for (let i = 0; i < chanIDs.length; ++i) {
const id = +chanIDs[i]
const channel = channels[id]
onCHANNEL_CLOSE(client, id, channel._channel || channel, err, true)
}
}
}
const isRegExp = (() => {
const toString = Object.prototype.toString
return (val) => toString.call(val) === '[object RegExp]'
})()
function generateAlgorithmList(algoList, defaultList, supportedList) {
if (Array.isArray(algoList) && algoList.length > 0) {
// Exact list
for (let i = 0; i < algoList.length; ++i) {
if (supportedList.indexOf(algoList[i]) === -1)
throw new Error(`Unsupported algorithm: ${algoList[i]}`)
}
return algoList
}
if (typeof algoList === 'object' && algoList !== null) {
// Operations based on the default list
const keys = Object.keys(algoList)
let list = defaultList
for (let i = 0; i < keys.length; ++i) {
const key = keys[i]
let val = algoList[key]
switch (key) {
case 'append':
if (!Array.isArray(val)) val = [val]
if (Array.isArray(val)) {
for (let j = 0; j < val.length; ++j) {
const append = val[j]
if (typeof append === 'string') {
if (!append || list.indexOf(append) !== -1) continue
if (supportedList.indexOf(append) === -1)
throw new Error(`Unsupported algorithm: ${append}`)
if (list === defaultList) list = list.slice()
list.push(append)
} else if (isRegExp(append)) {
for (let k = 0; k < supportedList.length; ++k) {
const algo = supportedList[k]
if (append.test(algo)) {
if (list.indexOf(algo) !== -1) continue
if (list === defaultList) list = list.slice()
list.push(algo)
}
}
}
}
}
break
case 'prepend':
if (!Array.isArray(val)) val = [val]
if (Array.isArray(val)) {
for (let j = val.length; j >= 0; --j) {
const prepend = val[j]
if (typeof prepend === 'string') {
if (!prepend || list.indexOf(prepend) !== -1) continue
if (supportedList.indexOf(prepend) === -1)
throw new Error(`Unsupported algorithm: ${prepend}`)
if (list === defaultList) list = list.slice()
list.unshift(prepend)
} else if (isRegExp(prepend)) {
for (let k = supportedList.length; k >= 0; --k) {
const algo = supportedList[k]
if (prepend.test(algo)) {
if (list.indexOf(algo) !== -1) continue
if (list === defaultList) list = list.slice()
list.unshift(algo)
}
}
}
}
}
break
case 'remove':
if (!Array.isArray(val)) val = [val]
if (Array.isArray(val)) {
for (let j = 0; j < val.length; ++j) {
const search = val[j]
if (typeof search === 'string') {
if (!search) continue
const idx = list.indexOf(search)
if (idx === -1) continue
if (list === defaultList) list = list.slice()
list.splice(idx, 1)
} else if (isRegExp(search)) {
for (let k = 0; k < list.length; ++k) {
if (search.test(list[k])) {
if (list === defaultList) list = list.slice()
list.splice(k, 1)
--k
}
}
}
}
}
break
}
}
return list
}
return defaultList
}
module.exports = {
ChannelManager,
generateAlgorithmList,
onChannelOpenFailure,
onCHANNEL_CLOSE,
isWritable: (stream) => {
// XXX: hack to workaround regression in node
// See: https://github.com/nodejs/node/issues/36029
return (
stream && stream.writable && stream._readableState && stream._readableState.ended === false
)
}
}
+987
View File
@@ -0,0 +1,987 @@
{
"name": "bare-ssh2",
"version": "1.17.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "bare-ssh2",
"version": "1.17.1",
"license": "MIT",
"dependencies": {
"asn1": "^0.2.6",
"assert": "npm:bare-node-assert@^1.0.0",
"bare-node-child-process": "^1.0.1",
"bare-node-dns": "^1.0.0",
"bare-node-events": "^1.0.1",
"bare-node-fs": "^1.0.2",
"bare-node-http": "^1.0.1",
"bare-node-https": "^1.0.0",
"bare-node-net": "^1.0.0",
"bare-node-path": "^1.0.1",
"bare-node-stream": "^1.0.0",
"bare-node-tls": "^1.0.0",
"bare-node-util": "^1.0.0",
"bare-node-zlib": "^1.0.0",
"bcrypt-pbkdf": "^1.0.2",
"buffer": "npm:bare-node-buffer@^1.0.0",
"chacha20": "^0.1.4",
"crypto": "file:shims/crypto"
},
"devDependencies": {
"bare-node-readline": "^1.0.1",
"bare-node-worker-threads": "^1.0.0",
"bare-process": "^4.4.1",
"prettier": "^3.4.1",
"prettier-config-holepunch": "^2.0.0"
},
"engines": {
"bare": ">=1.0.5",
"node": ">=10.16.0"
}
},
"node_modules/asn1": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
"license": "MIT",
"dependencies": {
"safer-buffer": "~2.1.0"
}
},
"node_modules/assert": {
"name": "bare-node-assert",
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/bare-node-assert/-/bare-node-assert-1.0.0.tgz",
"integrity": "sha512-twItXSJk9/Q3AE6ZKwNl0gIo/FiciPp35VRJ/rPh64GzUiW5uDcSBOeoVW1JCikYh+APPvh+Ix2vuH2+WqwKTQ==",
"license": "Apache-2.0",
"dependencies": {
"bare-assert": "*"
}
},
"node_modules/b4a": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.0.tgz",
"integrity": "sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==",
"license": "Apache-2.0",
"peerDependencies": {
"react-native-b4a": "*"
},
"peerDependenciesMeta": {
"react-native-b4a": {
"optional": true
}
}
},
"node_modules/bare-abort": {
"version": "2.0.13",
"resolved": "https://registry.npmjs.org/bare-abort/-/bare-abort-2.0.13.tgz",
"integrity": "sha512-zdc8l88eB11Jsz5rDd6sCAgv2kUFXgdrZWoMlgU6JMkfAi1/uuGFC3IEHswKbIRQTk5H3T5CMuechsXYxiaHlQ==",
"license": "Apache-2.0"
},
"node_modules/bare-addon-resolve": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/bare-addon-resolve/-/bare-addon-resolve-1.10.0.tgz",
"integrity": "sha512-sSd0jieRJlDaODOzj0oe0RjFVC1QI0ZIjGIdPkbrTXsdVVtENg14c+lHHAhHwmWCZ2nQlMhy8jA3Y5LYPc/isA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"bare-module-resolve": "^1.10.0",
"bare-semver": "^1.0.0"
},
"peerDependencies": {
"bare-url": "*"
},
"peerDependenciesMeta": {
"bare-url": {
"optional": true
}
}
},
"node_modules/bare-ansi-escapes": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/bare-ansi-escapes/-/bare-ansi-escapes-2.2.3.tgz",
"integrity": "sha512-02ES4/E2RbrtZSnHJ9LntBhYkLA6lPpSEeP8iqS3MccBIVhVBlEmruF1I7HZqx5Q8aiTeYfQVeqmrU9YO2yYoQ==",
"license": "Apache-2.0",
"dependencies": {
"bare-stream": "^2.6.5"
},
"peerDependencies": {
"bare-buffer": "*"
},
"peerDependenciesMeta": {
"bare-buffer": {
"optional": true
}
}
},
"node_modules/bare-assert": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/bare-assert/-/bare-assert-1.2.0.tgz",
"integrity": "sha512-c6uvgvTJBspTDxtVnPgrBKmLgcpW3Fp72NVKDLg6oT4QjQbhGtvrkHMhGYMK1sh4vjBHOBmuUalyt9hSzV37fQ==",
"license": "Apache-2.0",
"dependencies": {
"bare-inspect": "^3.1.2"
}
},
"node_modules/bare-buffer": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/bare-buffer/-/bare-buffer-3.6.0.tgz",
"integrity": "sha512-/maRWEQ2eBkVNMbNFVsq1pHXJYVj4Y3AixwruB24eKZDs5Gtu0fixzvjYmBIuTsBMtVH5Yb27pQO9BhFa+IlIQ==",
"license": "Apache-2.0",
"engines": {
"bare": ">=1.20.0"
}
},
"node_modules/bare-bundle": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/bare-bundle/-/bare-bundle-1.10.0.tgz",
"integrity": "sha512-4LVlnJAHr00Hh6Vu6ZUJS38rcEtJT3b3vChXSsBsJ2mk1TN0lQ+gzd+Dw5L0aV7uqDZv84smuwW+O02X7PfDlw==",
"dev": true,
"license": "Apache-2.0",
"peerDependencies": {
"bare-buffer": "*",
"bare-url": "*"
},
"peerDependenciesMeta": {
"bare-buffer": {
"optional": true
},
"bare-url": {
"optional": true
}
}
},
"node_modules/bare-channel": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/bare-channel/-/bare-channel-5.2.3.tgz",
"integrity": "sha512-2cRErqS4fzzr3ZUSd5W67ka70dZKJ1VWrCsvxPVC8vr3rWvd4aaCG5iCDas9+MFVaUIWvfw04+NH4+FHQDddMQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"bare-events": "^2.0.0",
"bare-stream": "^2.7.0",
"bare-structured-clone": "^1.4.0"
},
"engines": {
"bare": ">=1.7.0"
}
},
"node_modules/bare-crypto": {
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/bare-crypto/-/bare-crypto-1.13.4.tgz",
"integrity": "sha512-JiCZ5l2YOG1y8J7yy1BCAKTCZrPnHLb7pDRIdurBTOn5oIwBQDIv8iH5Pl2V85vzjl1NZXRfNY4HZLsE942jJA==",
"license": "Apache-2.0",
"dependencies": {
"bare-assert": "^1.2.0",
"bare-stream": "^2.6.3"
},
"peerDependencies": {
"bare-buffer": "*"
},
"peerDependenciesMeta": {
"bare-buffer": {
"optional": true
}
}
},
"node_modules/bare-debug-log": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/bare-debug-log/-/bare-debug-log-2.0.0.tgz",
"integrity": "sha512-Vi42PkMQsNV9PUpx2Gl1hikshx5O9FzMJ6o9Nnopseg7qLBBK7Nl31d0RHcfwLEAfmcPApytpc0ZFfq68u22FQ==",
"license": "Apache-2.0",
"dependencies": {
"bare-os": "^3.0.1"
}
},
"node_modules/bare-dns": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/bare-dns/-/bare-dns-2.1.4.tgz",
"integrity": "sha512-abwjHmpWqSRNB7V5615QxPH92L71AVzFm/kKTs8VYiNTAi2xVdonpv0BjJ0hwXLwomoW+xsSOPjW6PZPO14asg==",
"license": "Apache-2.0",
"engines": {
"bare": ">=1.7.0"
}
},
"node_modules/bare-encoding": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/bare-encoding/-/bare-encoding-1.0.3.tgz",
"integrity": "sha512-Kqf+t/azs13lUeyK4Tb7ha4wdLRXKWCXQ8w1rVmt7KtoPCPdHD/Xwt7LBIsCSwwGglrcmblo5VOLa5avkJqULA==",
"license": "Apache-2.0",
"peerDependencies": {
"bare-buffer": "*"
},
"peerDependenciesMeta": {
"bare-buffer": {
"optional": true
}
}
},
"node_modules/bare-env": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/bare-env/-/bare-env-3.0.0.tgz",
"integrity": "sha512-0u964P5ZLAxTi+lW4Kjp7YRJQ5gZr9ycYOtjLxsSrupgMz3sn5Z9n4SH/JIifHwvadsf1brA2JAjP+9IOWwTiw==",
"license": "Apache-2.0",
"dependencies": {
"bare-os": "^3.0.1"
}
},
"node_modules/bare-events": {
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz",
"integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==",
"license": "Apache-2.0",
"peerDependencies": {
"bare-abort-controller": "*"
},
"peerDependenciesMeta": {
"bare-abort-controller": {
"optional": true
}
}
},
"node_modules/bare-format": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bare-format/-/bare-format-1.0.2.tgz",
"integrity": "sha512-GswdhnOnP9QtwRbrf4wLApw5widkaLMsLe2XOs35fQD2YfEN1ApoGka+cZ7PfvzxMgfYXmMhj/2OGlVn5/Dxgw==",
"license": "Apache-2.0",
"dependencies": {
"bare-inspect": "^3.0.0"
}
},
"node_modules/bare-fs": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.6.0.tgz",
"integrity": "sha512-2YkS7NuiJceSEbyEOdSNLE9tsGd+f4+f7C+Nik/MCk27SYdwIMPT/yRKvg++FZhQXgk0KWJKJyXX9RhVV0RGqA==",
"license": "Apache-2.0",
"dependencies": {
"bare-events": "^2.5.4",
"bare-path": "^3.0.0",
"bare-stream": "^2.6.4",
"bare-url": "^2.2.2",
"fast-fifo": "^1.3.2"
},
"engines": {
"bare": ">=1.16.0"
},
"peerDependencies": {
"bare-buffer": "*"
},
"peerDependenciesMeta": {
"bare-buffer": {
"optional": true
}
}
},
"node_modules/bare-hrtime": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/bare-hrtime/-/bare-hrtime-2.1.1.tgz",
"integrity": "sha512-VMb3tHo05gsnbu3OXTmkDiwTjMlOsbQmKoysKqKEyR09m77TuDrYFbj3Q5GGk10dAKsUHrnXmwCaeJqzVpB5ZA==",
"license": "Apache-2.0"
},
"node_modules/bare-http-parser": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/bare-http-parser/-/bare-http-parser-1.1.3.tgz",
"integrity": "sha512-+dhVvQi6brHq14L/XHNRQ+TLuVE76VjRmMt61wVEtS+Od8xUslfMHWJN/ZjIIt3RtTG6vPuA+x9cOh7KrkBJsA==",
"license": "Apache-2.0"
},
"node_modules/bare-http1": {
"version": "4.5.5",
"resolved": "https://registry.npmjs.org/bare-http1/-/bare-http1-4.5.5.tgz",
"integrity": "sha512-ADITiRo0huP76JGMbv6Arsh9KehHqjEBoYcmjvAo67IY78+/9mV2MeKLLCkiJSFxA85T/m8cTaE44OwJQCcwdw==",
"license": "Apache-2.0",
"dependencies": {
"bare-events": "^2.6.0",
"bare-http-parser": "^1.1.1",
"bare-stream": "^2.10.0",
"bare-tcp": "^2.2.0"
},
"peerDependencies": {
"bare-buffer": "*",
"bare-url": "*"
},
"peerDependenciesMeta": {
"bare-buffer": {
"optional": true
},
"bare-url": {
"optional": true
}
}
},
"node_modules/bare-https": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/bare-https/-/bare-https-2.1.3.tgz",
"integrity": "sha512-0TI/mJXQGYXmG7UUyWEG+KCJusayIAQLywUjFAskDoKuxfqVnGF+M/mTMrEV8J64DaIdU+5x761FvgmT7M68tA==",
"license": "Apache-2.0",
"dependencies": {
"bare-http1": "^4.4.0",
"bare-tcp": "^2.2.0",
"bare-tls": "^2.0.0"
}
},
"node_modules/bare-inspect": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/bare-inspect/-/bare-inspect-3.1.4.tgz",
"integrity": "sha512-jfW5KRA84o3REpI6Vr4nbvMn+hqVAw8GU1mMdRwUsY5yJovQamxYeKGVKGqdzs+8ZbG4jRzGUXP/3Ji/DnqfPg==",
"license": "Apache-2.0",
"dependencies": {
"bare-ansi-escapes": "^2.1.0",
"bare-type": "^1.0.0"
},
"engines": {
"bare": ">=1.18.0"
}
},
"node_modules/bare-module": {
"version": "6.1.3",
"resolved": "https://registry.npmjs.org/bare-module/-/bare-module-6.1.3.tgz",
"integrity": "sha512-5XWsVHsvtWMH4tK4DQWgpNTV0t/sg3ZrAaQLIxrwjrS5+u8Q9vEgc/zQ4QaDPWDse/y/5h+d+YG1Q0JfSMt0zA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"bare-bundle": "^1.3.0",
"bare-module-lexer": "^1.0.0",
"bare-module-resolve": "^1.8.0",
"bare-path": "^3.0.0",
"bare-url": "^2.0.1"
},
"engines": {
"bare": ">=1.23.0"
},
"peerDependencies": {
"bare-buffer": "*"
},
"peerDependenciesMeta": {
"bare-buffer": {
"optional": true
}
}
},
"node_modules/bare-module-lexer": {
"version": "1.4.7",
"resolved": "https://registry.npmjs.org/bare-module-lexer/-/bare-module-lexer-1.4.7.tgz",
"integrity": "sha512-0klU4eMsjh/wcxi8FdHmNom2j2F4kmkXOhyJFL9qTaSFp2lE3m6BtbKgMHY8R5miqC9r8/IfA8wzXnC5Os14WA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"require-addon": "^1.0.2"
},
"peerDependencies": {
"bare-buffer": "*"
},
"peerDependenciesMeta": {
"bare-buffer": {
"optional": true
}
}
},
"node_modules/bare-module-resolve": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/bare-module-resolve/-/bare-module-resolve-1.12.1.tgz",
"integrity": "sha512-hbmAPyFpEq8FoZMd5sFO3u6MC5feluWoGE8YKlA8fCrl6mNtx68Wjg4DTiDJcqRJaovTvOYKfYngoBUnbaT7eg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"bare-semver": "^1.0.0"
},
"peerDependencies": {
"bare-url": "*"
},
"peerDependenciesMeta": {
"bare-url": {
"optional": true
}
}
},
"node_modules/bare-module-traverse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/bare-module-traverse/-/bare-module-traverse-2.0.1.tgz",
"integrity": "sha512-1au+Og5p97T9b6Y7xmHZ7KtpW8vEYtz2jC2whmm+YJp46EaHfk26j91MmQhufdkR/8sdK1Q5p+P9A/Y5GrJg7Q==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"bare-addon-resolve": "^1.5.0",
"bare-module-lexer": "^1.4.0",
"bare-module-resolve": "^1.7.0"
},
"peerDependencies": {
"bare-buffer": "*",
"bare-url": "*"
},
"peerDependenciesMeta": {
"bare-buffer": {
"optional": true
},
"bare-url": {
"optional": true
}
}
},
"node_modules/bare-net": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/bare-net/-/bare-net-2.3.1.tgz",
"integrity": "sha512-MypSqDKpDU2Xt7FIfazn5yGvRnV09gFcIPHGWstW0gxuzA4tucTcwJSZeos97C4F89vtU5oGwXDN/HrGN6Y4Jw==",
"license": "Apache-2.0",
"dependencies": {
"bare-events": "^2.2.2",
"bare-pipe": "^4.0.0",
"bare-stream": "^2.0.0",
"bare-tcp": "^2.0.0"
}
},
"node_modules/bare-node-child-process": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/bare-node-child-process/-/bare-node-child-process-1.0.1.tgz",
"integrity": "sha512-zfLNSl0fmARbseK5InrczAgs2j1jgEMV7CU9N2JO5c200g6Cmzrjuxua4AHL+PjDl+W64VnmtNSWKzQe3mkU3w==",
"license": "Apache-2.0",
"dependencies": {
"bare-subprocess": "*"
}
},
"node_modules/bare-node-dns": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/bare-node-dns/-/bare-node-dns-1.0.0.tgz",
"integrity": "sha512-Kn5BjOUiWUstHVfVWulZ5A81XAckVX5OsQqx6uBpNYDXjRac5EMGDJxnbof/NtCThlZTc4RT/NPzFUTfg4URtA==",
"license": "Apache-2.0",
"dependencies": {
"bare-dns": "*"
}
},
"node_modules/bare-node-events": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/bare-node-events/-/bare-node-events-1.0.1.tgz",
"integrity": "sha512-3RZAWtrpWmpI0BwvJpH3VxyN0FCvsIGfhf2tvwbM795qoqqltTaC2IjrUBm39OVmJNVUZxBIf+noo945hsvtUw==",
"license": "Apache-2.0",
"dependencies": {
"bare-events": "*"
}
},
"node_modules/bare-node-fs": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bare-node-fs/-/bare-node-fs-1.0.2.tgz",
"integrity": "sha512-Tas23gfqHmkNQe1VUID6ifMi3oAYHqTuYr8sCq/xcskpTaDChGxZKJnFJzi1/pSnHzgQCLlkX+FpPnqNJTyQgg==",
"license": "Apache-2.0",
"dependencies": {
"bare-fs": "*"
}
},
"node_modules/bare-node-http": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/bare-node-http/-/bare-node-http-1.0.1.tgz",
"integrity": "sha512-74KBjcJPXpl6ySRM9YHy40m9eFckPNvS0jLtwBdWhPfxJWTlW7oJQL30LIaKkX7Y6ZMnZ2XV6ek3PGdcljS6aQ==",
"license": "Apache-2.0",
"dependencies": {
"bare-http1": "*"
}
},
"node_modules/bare-node-https": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/bare-node-https/-/bare-node-https-1.0.0.tgz",
"integrity": "sha512-HhIWViqqewd32YHJZQ6c1nJ9s0ukWwTPmobiaClx7Ihzrj0x5oEosjXIIw2p++7zV/38LdH2I8zLYSgOnHOp3g==",
"license": "Apache-2.0",
"dependencies": {
"bare-https": "*"
}
},
"node_modules/bare-node-net": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/bare-node-net/-/bare-node-net-1.0.0.tgz",
"integrity": "sha512-vO1XJAMvFxLz/zm4SDq5NSAgk07Wv3g10zPpkFj7+/9oABiMHz6vgQciASeI9258ua+ij7kjrZoeHw5ZI73dDw==",
"license": "Apache-2.0",
"dependencies": {
"bare-net": "*"
}
},
"node_modules/bare-node-path": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/bare-node-path/-/bare-node-path-1.0.1.tgz",
"integrity": "sha512-44YiNN/ofG1cEOWwdRVbG9ZFyskZKXPJnSUOyUpdeRm+MeSXiY+pSjSa7SZ56C/XpPVxE0OEl/AV8u+3FKsclw==",
"license": "Apache-2.0",
"dependencies": {
"bare-path": "*"
}
},
"node_modules/bare-node-readline": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/bare-node-readline/-/bare-node-readline-1.0.1.tgz",
"integrity": "sha512-A+6ewT/b4wkHe5clWe+H589fQDKrFMYsMsSCk1KHFzmVI60wXL6eT5iRB4n3wlCH476Zauig2XLMj2RznCBs4g==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"bare-readline": "*"
}
},
"node_modules/bare-node-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/bare-node-stream/-/bare-node-stream-1.0.0.tgz",
"integrity": "sha512-fE3xRlcMyxqMi96k4FxvZdGJMndt4fsf9U1T7mU7ZV8h+r6DxNkm2qCdX1+Ie+5mCx6Hoh/jv+Lw/OKpta9H7w==",
"license": "Apache-2.0",
"dependencies": {
"bare-stream": "*"
}
},
"node_modules/bare-node-tls": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/bare-node-tls/-/bare-node-tls-1.0.0.tgz",
"integrity": "sha512-BHRiftAc5F4PvRDcVYhuCYRv06NqbToYLQZQJQlifmkIJ74Rujy0fVn8UZ9Q6xrq3C7OenSeUV0rcgroppjiBw==",
"license": "Apache-2.0",
"dependencies": {
"bare-tls": "*"
}
},
"node_modules/bare-node-util": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/bare-node-util/-/bare-node-util-1.0.0.tgz",
"integrity": "sha512-as4V8zYrS0dMw5RI77qqRtEmngb68drxK2BJszxRFqmKWMc5x7izlHy9cG+Z8CmVefPSb191Fy3gpm8VHFtmpw==",
"license": "Apache-2.0",
"dependencies": {
"bare-utils": "*"
}
},
"node_modules/bare-node-worker-threads": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/bare-node-worker-threads/-/bare-node-worker-threads-1.0.0.tgz",
"integrity": "sha512-N3cLs8edH4x6UkZDq8NmZqX/WbNsWMgDuPLFmW8v711ail0+JwmX8D+zGUraVZgWnfBTTlnPYjD5sm+y4h9vtQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"bare-worker": "*"
}
},
"node_modules/bare-node-zlib": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/bare-node-zlib/-/bare-node-zlib-1.0.0.tgz",
"integrity": "sha512-1PTJaUKTBEZ2HdDnGYKYos6t5HEvHQzrJjSVvVSBaEOVMN+cpl2LuwV02rK9lpOTKPv+Lbs0A/a2MdETKPCIWg==",
"license": "Apache-2.0",
"dependencies": {
"bare-zlib": "*"
}
},
"node_modules/bare-os": {
"version": "3.8.7",
"resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.8.7.tgz",
"integrity": "sha512-G4Gr1UsGeEy2qtDTZwL7JFLo2wapUarz7iTMcYcMFdS89AIQuBoyjgXZz0Utv7uHs3xA9LckhVbeBi8lEQrC+w==",
"license": "Apache-2.0",
"engines": {
"bare": ">=1.14.0"
}
},
"node_modules/bare-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz",
"integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==",
"license": "Apache-2.0",
"dependencies": {
"bare-os": "^3.0.1"
}
},
"node_modules/bare-pipe": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/bare-pipe/-/bare-pipe-4.1.5.tgz",
"integrity": "sha512-6OfxaG8JSkRh3Gc4hzHRsxNt+yu2PpN7lrv1V+T78GdknWQkVGwiEvu4m+1nbfk8cMVQ0TGxRvQ90XA4rhnTuw==",
"license": "Apache-2.0",
"dependencies": {
"bare-events": "^2.0.0",
"bare-stream": "^2.0.0"
},
"engines": {
"bare": ">=1.16.0"
}
},
"node_modules/bare-process": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/bare-process/-/bare-process-4.4.1.tgz",
"integrity": "sha512-JfcTtymq6akqM2bdyTsP4A4GYJceBzb91k/ECmFps75uFf6uO33SM1bOZsRAqyRXExabsQJLn5S41NBl8HTM4A==",
"license": "Apache-2.0",
"dependencies": {
"bare-abort": "^2.0.13",
"bare-env": "^3.0.0",
"bare-events": "^2.3.1",
"bare-hrtime": "^2.0.0",
"bare-os": "^3.7.1",
"bare-signals": "^4.0.0",
"bare-stdio": "^1.0.1"
}
},
"node_modules/bare-readline": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/bare-readline/-/bare-readline-1.3.1.tgz",
"integrity": "sha512-QtSU4ZfgQcDI6AQssjDFqTiRe4rCiciMn+Yqx6siMJZBIftAIFrNSOK0sa5SBrmNv/a7CD9Dm0onUDCRyn5Fdg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"bare-ansi-escapes": "^2.0.0",
"bare-stream": "^2.0.0"
}
},
"node_modules/bare-semver": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/bare-semver/-/bare-semver-1.0.3.tgz",
"integrity": "sha512-HS/A30bi2+PiRJfU6R4+Kp+6KeLSCSByjYM2iiobOKzLAvtu1CT+S8xWfiU7wz0erknjkUoC+yXy108tzIuP5Q==",
"dev": true,
"license": "Apache-2.0"
},
"node_modules/bare-signals": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/bare-signals/-/bare-signals-4.2.0.tgz",
"integrity": "sha512-fNHMOdQIlYuTvMB3Oh9Apk99hLKn351+Ir8vz+khiPTcOqIyGG4uWWjdLTzxWdYGsA0eT+We3y0K74hjj2nq7A==",
"license": "Apache-2.0",
"dependencies": {
"bare-events": "^2.5.3",
"bare-os": "^3.3.1"
},
"engines": {
"bare": ">=1.7.0"
}
},
"node_modules/bare-stdio": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bare-stdio/-/bare-stdio-1.0.2.tgz",
"integrity": "sha512-3WJDqtvVGP4f+j68kyEC05umOYNwKJ1xG+YAXL8yZ605WgNqiRhVaFq+mVIhBt2eKNp7pa5vCQdhOt1pNh79SA==",
"license": "Apache-2.0",
"dependencies": {
"bare-fs": "^4.5.2",
"bare-pipe": "^4.1.5",
"bare-tty": "^5.0.3"
}
},
"node_modules/bare-stream": {
"version": "2.12.0",
"resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.12.0.tgz",
"integrity": "sha512-w28i8lkBgREV3rPXGbgK+BO66q+ZpKqRWrZLiCdmmUlLPrQ45CzkvRhN+7lnv00Gpi2zy5naRxnUFAxCECDm9g==",
"license": "Apache-2.0",
"dependencies": {
"streamx": "^2.25.0",
"teex": "^1.0.1"
},
"peerDependencies": {
"bare-abort-controller": "*",
"bare-buffer": "*",
"bare-events": "*"
},
"peerDependenciesMeta": {
"bare-abort-controller": {
"optional": true
},
"bare-buffer": {
"optional": true
},
"bare-events": {
"optional": true
}
}
},
"node_modules/bare-structured-clone": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/bare-structured-clone/-/bare-structured-clone-1.5.3.tgz",
"integrity": "sha512-vC/YqGsp67ZeFnpyAskwaEIXtNscnCwFVKlSk0Oh2X3AqWT6H+7DC9vVI080FohUJeuUuB9UNx4UFdDcyQgZaw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"bare-type": "^1.1.0",
"compact-encoding": "^2.15.0"
},
"engines": {
"bare": ">=1.2.0"
},
"peerDependencies": {
"bare-buffer": "*",
"bare-url": "*"
},
"peerDependenciesMeta": {
"bare-buffer": {
"optional": true
},
"bare-url": {
"optional": true
}
}
},
"node_modules/bare-stylize": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/bare-stylize/-/bare-stylize-0.0.1.tgz",
"integrity": "sha512-l3MjmIl476bWijYWf3RbE+osl4iuXSOMudzp0vAqzIK7gPgn/+G3oAxp8Oin9CFF911KBP0LO9kts8Ci8mGZaQ==",
"license": "Apache-2.0",
"dependencies": {
"bare-ansi-escapes": "^2.2.3",
"bare-process": "^4.2.1"
}
},
"node_modules/bare-subprocess": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/bare-subprocess/-/bare-subprocess-5.2.3.tgz",
"integrity": "sha512-07wwswlV7M3sC9IykbZRZ/jHAkrXFWVLqdBWGv1y0ojCimtRD9hGwxdHmR5FUFmDUZLNsBmTYJNQqgio5+A85Q==",
"license": "Apache-2.0",
"dependencies": {
"bare-env": "^3.0.0",
"bare-events": "^2.5.4",
"bare-os": "^3.0.1",
"bare-pipe": "^4.0.0",
"bare-url": "^2.2.2"
},
"engines": {
"bare": ">=1.7.0"
},
"peerDependencies": {
"bare-buffer": "*"
},
"peerDependenciesMeta": {
"bare-buffer": {
"optional": true
}
}
},
"node_modules/bare-tcp": {
"version": "2.2.7",
"resolved": "https://registry.npmjs.org/bare-tcp/-/bare-tcp-2.2.7.tgz",
"integrity": "sha512-rjpqNQ2cOCkNo3NeYA/W4GTK3DRkl8sDHO3uos+AEswUjLC8XXMQF8WrJCSjlIowCbS6NUVxKE92X5RGXjyefg==",
"license": "Apache-2.0",
"dependencies": {
"bare-dns": "^2.0.4",
"bare-events": "^2.5.4",
"bare-stream": "^2.6.4"
},
"engines": {
"bare": ">=1.16.0"
}
},
"node_modules/bare-thread": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/bare-thread/-/bare-thread-1.2.0.tgz",
"integrity": "sha512-evYpeDqaTROp2JIdVgWrIBc5rVCV64tFMwZdeL13ahYt/lno2RLvTbYrcf1p6NA2p1SxybbSbGQ2F9/gHudrTg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"bare-bundle": "^1.9.0",
"bare-module-resolve": "^1.11.2",
"bare-module-traverse": "^2.0.0"
}
},
"node_modules/bare-tls": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/bare-tls/-/bare-tls-2.2.1.tgz",
"integrity": "sha512-hZ+ZqwrUO4dyH7/6WYkYWjgAFNJKjzwEYJiDaMnMs+eRleBDjQ3CvNZawpkw0Ar9jnM9NZK6+f6GqjkZ2FLGmQ==",
"license": "Apache-2.0",
"dependencies": {
"bare-net": "^2.0.1",
"bare-stream": "^2.6.4"
},
"engines": {
"bare": ">=1.7.0"
}
},
"node_modules/bare-tty": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/bare-tty/-/bare-tty-5.1.0.tgz",
"integrity": "sha512-EZLvW4A+XiJgI3TW+e1pMME9PIJsfEXe/DA/WSKzIkq/v7Yarpv/rvG6Z5pGnpo4V/Bd+qopwnCLSR71hMMBYA==",
"license": "Apache-2.0",
"dependencies": {
"bare-events": "^2.2.0",
"bare-signals": "^4.0.0",
"bare-stream": "^2.0.0"
},
"engines": {
"bare": ">=1.16.0"
}
},
"node_modules/bare-type": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/bare-type/-/bare-type-1.1.0.tgz",
"integrity": "sha512-LdtnnEEYldOc87Dr4GpsKnStStZk3zfgoEMXy8yvEZkXrcCv9RtYDrUYWFsBQHtaB0s1EUWmcvS6XmEZYIj3Bw==",
"license": "Apache-2.0",
"engines": {
"bare": ">=1.2.0"
}
},
"node_modules/bare-url": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.4.0.tgz",
"integrity": "sha512-NSTU5WN+fy/L0DDenfE8SXQna4voXuW0FHM7wH8i3/q9khUSchfPbPezO4zSFMnDGIf9YE+mt/RWhZgNRKRIXA==",
"license": "Apache-2.0",
"dependencies": {
"bare-path": "^3.0.0"
}
},
"node_modules/bare-utils": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/bare-utils/-/bare-utils-1.6.0.tgz",
"integrity": "sha512-WhQEIkkAxkSnW7u1QgrI0AfNm5JpMruETXeYsb5qnkBJ0TTfNKygZmsh6rkoHBANaV+C/7Jed7bJP9OmEHG7rQ==",
"license": "Apache-2.0",
"dependencies": {
"bare-debug-log": "^2.0.0",
"bare-encoding": "^1.0.0",
"bare-format": "^1.0.0",
"bare-inspect": "^3.0.0",
"bare-stylize": "^0.0.1",
"bare-type": "^1.0.6"
}
},
"node_modules/bare-worker": {
"version": "4.1.6",
"resolved": "https://registry.npmjs.org/bare-worker/-/bare-worker-4.1.6.tgz",
"integrity": "sha512-yvsektF7xNqlAyjJV+YYeBx+sGZ8Fhbo5Cjc/lpIdkM8Gd/e3MlaxTFg8NknkyvJ4oDJXqvp38Q+ZOn5Gyr+nQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"bare-channel": "^5.1.5",
"bare-events": "^2.2.1",
"bare-module": "^6.0.1",
"bare-thread": "^1.1.3"
}
},
"node_modules/bare-zlib": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/bare-zlib/-/bare-zlib-1.3.3.tgz",
"integrity": "sha512-rXNczo+SQg6cn20olmh/mUiGeJK9maipFH/zI/QwYgwhEmOns1R7fl1GV5apNO+aAp4x2d4uUa7HLhO4mhOnBQ==",
"license": "Apache-2.0",
"dependencies": {
"bare-stream": "^2.0.0"
}
},
"node_modules/bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
"integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
"license": "BSD-3-Clause",
"dependencies": {
"tweetnacl": "^0.14.3"
}
},
"node_modules/buffer": {
"name": "bare-node-buffer",
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/bare-node-buffer/-/bare-node-buffer-1.0.0.tgz",
"integrity": "sha512-sgKJRlxGOjdvT/th+7OY/ONvq4DoVXfiAlnQDa0gNLbftS0wHrsoYBkDUoHMKmdY8IMlPXn+KBidnl///sFBxA==",
"license": "Apache-2.0",
"dependencies": {
"bare-buffer": "*"
}
},
"node_modules/chacha20": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/chacha20/-/chacha20-0.1.4.tgz",
"integrity": "sha512-nxKJwtcXKxXIITkHQDrgCrZKAHjL6CY94n74obSux9WynGnoYj4wGTYHygp6DDSrBB9Efjts0QXSAFRz7E1hJg==",
"license": "CC0-1.0",
"engines": {
"node": ">=0.10.x",
"npm": ">=1.2.x"
}
},
"node_modules/compact-encoding": {
"version": "2.19.2",
"resolved": "https://registry.npmjs.org/compact-encoding/-/compact-encoding-2.19.2.tgz",
"integrity": "sha512-/YjhHQE/5L4F7l5Bht69dRbP9RV6zoJPeowi8bMKQxNKe3Nh6hOY8pBGoVE9fz5GaWfEd8fWJ2aU9sB4KZuMYg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"b4a": "^1.3.0"
}
},
"node_modules/crypto": {
"resolved": "shims/crypto",
"link": true
},
"node_modules/events-universal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz",
"integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==",
"license": "Apache-2.0",
"dependencies": {
"bare-events": "^2.7.0"
}
},
"node_modules/fast-fifo": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
"integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==",
"license": "MIT"
},
"node_modules/prettier": {
"version": "3.8.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz",
"integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==",
"dev": true,
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/prettier-config-holepunch": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/prettier-config-holepunch/-/prettier-config-holepunch-2.0.0.tgz",
"integrity": "sha512-yuskcdPRfQYLFPkOGvxS4TFmCb7QvAowjO+YaNLPLBWRev+qu6HXoKkPWH9lfNsL9gUThV7IeZ6t/B1QSu/jng==",
"dev": true,
"license": "Apache-2.0",
"peerDependencies": {
"prettier": "^3.6.2"
}
},
"node_modules/require-addon": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/require-addon/-/require-addon-1.2.0.tgz",
"integrity": "sha512-VNPDZlYgIYQwWp9jMTzljx+k0ZtatKlcvOhktZ/anNPI3dQ9NXk7cq2U4iJ1wd9IrytRnYhyEocFWbkdPb+MYA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"bare-addon-resolve": "^1.3.0"
},
"engines": {
"bare": ">=1.10.0"
}
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/streamx": {
"version": "2.25.0",
"resolved": "https://registry.npmjs.org/streamx/-/streamx-2.25.0.tgz",
"integrity": "sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==",
"license": "MIT",
"dependencies": {
"events-universal": "^1.0.0",
"fast-fifo": "^1.3.2",
"text-decoder": "^1.1.0"
}
},
"node_modules/teex": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz",
"integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==",
"license": "MIT",
"dependencies": {
"streamx": "^2.12.5"
}
},
"node_modules/text-decoder": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz",
"integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==",
"license": "Apache-2.0",
"dependencies": {
"b4a": "^1.6.4"
}
},
"node_modules/tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
"license": "Unlicense"
},
"shims/crypto": {
"version": "0.0.0",
"dependencies": {
"bare-crypto": "^1.13.4"
}
}
}
}
+150
View File
@@ -0,0 +1,150 @@
{
"name": "bare-ssh2",
"version": "1.17.1",
"description": "SSH2 client and server modules for Bare (Holepunch/Pear runtime) — drop-in compatible with the Node.js ssh2 package API",
"type": "commonjs",
"main": "./lib/index.js",
"exports": {
"./package": "./package.json",
".": "./lib/index.js"
},
"imports": {
"assert": {
"bare": "assert",
"default": "assert"
},
"buffer": {
"bare": "buffer",
"default": "buffer"
},
"child_process": {
"bare": "bare-node-child-process",
"default": "child_process"
},
"crypto": {
"bare": "./shims/crypto/index.js",
"default": "crypto"
},
"dns": {
"bare": "bare-node-dns",
"default": "dns"
},
"events": {
"bare": "bare-node-events",
"default": "events"
},
"fs": {
"bare": "bare-node-fs",
"default": "fs"
},
"http": {
"bare": "bare-node-http",
"default": "http"
},
"https": {
"bare": "bare-node-https",
"default": "https"
},
"net": {
"bare": "bare-node-net",
"default": "net"
},
"path": {
"bare": "bare-node-path",
"default": "path"
},
"readline": {
"bare": "bare-node-readline",
"default": "readline"
},
"stream": {
"bare": "bare-node-stream",
"default": "stream"
},
"tls": {
"bare": "bare-node-tls",
"default": "tls"
},
"util": {
"bare": "bare-node-util",
"default": "util"
},
"worker_threads": {
"bare": "bare-node-worker-threads",
"default": "worker_threads"
},
"zlib": {
"bare": "bare-node-zlib",
"default": "zlib"
}
},
"files": [
"lib",
"shims",
"examples",
"scripts/openssh-test-server",
"test",
"README.md",
"LICENSE",
"NOTICE"
],
"scripts": {
"test": "prettier . --check && bare test/test-protocol-crypto.js && node test/test-protocol-keyparser.js",
"test:all": "prettier . --check && bare test/test.js",
"test:crypto": "bare test/test-protocol-crypto.js",
"test:node": "node test/test.js",
"openssh:test-server": "bash scripts/openssh-test-server/run.sh"
},
"engines": {
"bare": ">=1.0.5",
"node": ">=10.16.0"
},
"keywords": [
"bare",
"pear",
"holepunch",
"ssh2",
"ssh",
"client",
"server",
"p2p",
"sftp"
],
"author": "Brian White <[email protected]> (original ssh2); Bare port by Holepunch",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/holepunchto/bare-ssh2.git"
},
"bugs": {
"url": "https://github.com/holepunchto/bare-ssh2/issues"
},
"homepage": "https://github.com/holepunchto/bare-ssh2#readme",
"dependencies": {
"asn1": "^0.2.6",
"chacha20": "^0.1.4",
"assert": "npm:bare-node-assert@^1.0.0",
"buffer": "npm:bare-node-buffer@^1.0.0",
"bare-node-child-process": "^1.0.1",
"bare-node-dns": "^1.0.0",
"bare-node-events": "^1.0.1",
"bare-node-fs": "^1.0.2",
"bare-node-http": "^1.0.1",
"bare-node-https": "^1.0.0",
"bare-node-net": "^1.0.0",
"bare-node-path": "^1.0.1",
"bare-node-stream": "^1.0.0",
"bare-node-tls": "^1.0.0",
"bare-node-util": "^1.0.0",
"bare-node-zlib": "^1.0.0",
"bcrypt-pbkdf": "^1.0.2",
"crypto": "file:shims/crypto"
},
"devDependencies": {
"bare-node-readline": "^1.0.1",
"bare-node-worker-threads": "^1.0.0",
"bare-process": "^4.4.1",
"prettier": "^3.4.1",
"prettier-config-holepunch": "^2.0.0"
}
}
+1
View File
@@ -0,0 +1 @@
runtime/
+71
View File
@@ -0,0 +1,71 @@
# Local OpenSSH test server
Runs a minimal **`sshd`** on **127.0.0.1:2222** (configurable) with **public-key authentication** only. No Docker.
## Requirements
- OpenSSH **server** binary (`sshd`) on the machine.
- **macOS**: enable “Remote Login” in System Settings (installs/enables `sshd`), or `brew install openssh` and set `SSHD_BINARY` to the Homebrew `sshd`.
- **Linux**: `openssh-server` (Debian/Ubuntu: `sudo apt install openssh-server`).
## Run
```bash
cd /path/to/bare-ssh2
chmod +x scripts/openssh-test-server/run.sh
./scripts/openssh-test-server/run.sh
```
Or from the repo root:
```bash
npm run openssh:test-server
```
Environment (optional):
| Variable | Default | Meaning |
| ---------------------- | ------------------------------- | -------------------------------- |
| `OPENSSH_TEST_PORT` | `2222` | TCP port |
| `OPENSSH_TEST_LISTEN` | `127.0.0.1` | Bind address |
| `OPENSSH_TEST_RUNTIME` | `scripts/openssh-test-server/runtime` | Keys + config directory |
| `SSHD_BINARY` | (auto) | Full path to `sshd` if not found |
State is stored under **`scripts/openssh-test-server/runtime/`** (gitignored): host key, client key, `authorized_keys`, `sshd_config`.
## Connect
The server authenticates **your current OS username** using the generated client key:
```bash
KEY=scripts/openssh-test-server/runtime/client_ed25519
ssh -i "$KEY" -p 2222 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$(id -un)@127.0.0.1"
```
## bare-ssh2 example
```js
const { readFileSync } = require('fs')
const { Client } = require('bare-ssh2')
const client = new Client()
client
.on('ready', () => {
client.exec('echo hello-from-server', (err, stream) => {
if (err) throw err
stream.on('close', () => client.end()).on('data', (d) => process.stdout.write(d))
})
})
.connect({
host: '127.0.0.1',
port: 2222,
username: require('os').userInfo().username,
privateKey: readFileSync('scripts/openssh-test-server/runtime/client_ed25519'),
})
```
## Notes
- **Foreground only**: the script runs `sshd -D -e` so logs go to the terminal; Ctrl+C stops it.
- If `sshd` complains about permissions or PAM, try running from a normal user session and ensure `StrictModes no` in the generated config (the script sets this).
- Some managed macOS profiles block custom `sshd`; use a Linux VM or Homebrew `openssh` in that case.
+99
View File
@@ -0,0 +1,99 @@
#!/usr/bin/env bash
# Local OpenSSH test server (no Docker). Listens on 127.0.0.1:2222 with pubkey auth
# for your current login user. Ctrl+C stops the server.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
RUNTIME_DIR="${OPENSSH_TEST_RUNTIME:-$SCRIPT_DIR/runtime}"
PORT="${OPENSSH_TEST_PORT:-2222}"
LISTEN="${OPENSSH_TEST_LISTEN:-127.0.0.1}"
mkdir -p "$RUNTIME_DIR"
RUNTIME_DIR="$(cd "$RUNTIME_DIR" && pwd)"
find_sshd() {
if [[ -n "${SSHD_BINARY:-}" && -x "$SSHD_BINARY" ]]; then
echo "$SSHD_BINARY"
return
fi
for c in /usr/sbin/sshd /usr/lib/ssh/sshd /usr/libexec/sshd /sbin/sshd; do
if [[ -x "$c" ]]; then
echo "$c"
return
fi
done
if command -v sshd &>/dev/null; then
command -v sshd
return
fi
echo "sshd not found. Install OpenSSH server (macOS: System Settings → General → Sharing → Remote Login, or use Homebrew openssh)." >&2
exit 1
}
SSHD_BIN="$(find_sshd)"
TEST_USER="$(id -un)"
HOST_KEY="$RUNTIME_DIR/ssh_host_ed25519_key"
CLIENT_KEY="$RUNTIME_DIR/client_ed25519"
AUTH_KEYS="$RUNTIME_DIR/authorized_keys"
CONFIG="$RUNTIME_DIR/sshd_config"
PID_FILE="$RUNTIME_DIR/sshd.pid"
if [[ ! -f "$HOST_KEY" ]]; then
echo "Generating host key..."
ssh-keygen -t ed25519 -f "$HOST_KEY" -N "" -q
fi
chmod 600 "$HOST_KEY" 2>/dev/null || true
if [[ ! -f "$CLIENT_KEY" ]]; then
echo "Generating client key (for ssh / bare-ssh2 tests)..."
ssh-keygen -t ed25519 -f "$CLIENT_KEY" -N "" -q
fi
chmod 600 "$CLIENT_KEY" 2>/dev/null || true
cp "${CLIENT_KEY}.pub" "$AUTH_KEYS"
chmod 644 "$AUTH_KEYS"
# internal-sftp avoids hunting for sftp-server binary paths
cat >"$CONFIG" <<EOF
# Generated by bare-ssh2 scripts/openssh-test-server/run.sh — do not edit by hand
Port $PORT
ListenAddress $LISTEN
HostKey $HOST_KEY
PidFile $PID_FILE
UseDNS no
PermitEmptyPasswords no
PasswordAuthentication no
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile $AUTH_KEYS
PermitRootLogin no
StrictModes no
Subsystem sftp internal-sftp
LogLevel INFO
UsePAM no
EOF
cleanup() {
rm -f "$PID_FILE"
}
trap cleanup EXIT
echo ""
echo "OpenSSH test server"
echo " sshd: $SSHD_BIN"
echo " listen: $LISTEN port $PORT"
echo " user: $TEST_USER (your OS login — pubkey only)"
echo " identity: $CLIENT_KEY"
echo ""
echo "Quick test (OpenSSH client):"
echo " ssh -i \"$CLIENT_KEY\" -p $PORT -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${TEST_USER}@${LISTEN} echo ok"
echo ""
echo "SFTP:"
echo " sftp -i \"$CLIENT_KEY\" -P $PORT -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${TEST_USER}@${LISTEN}"
echo ""
echo "Starting sshd in foreground (Ctrl+C to stop)..."
echo ""
exec "$SSHD_BIN" -D -e -f "$CONFIG"
+9
View File
@@ -0,0 +1,9 @@
'use strict'
const bareCrypto = require('bare-crypto')
const { getCiphers, getHashes } = require('./lists.js')
module.exports = Object.assign({}, bareCrypto, {
getCiphers,
getHashes
})
+42
View File
@@ -0,0 +1,42 @@
'use strict'
const { constants } = require('bare-crypto')
const CIPHER_TO_OPENSSL = {
AES128ECB: 'aes-128-ecb',
AES128CBC: 'aes-128-cbc',
AES128CTR: 'aes-128-ctr',
AES128OFB: 'aes-128-ofb',
AES256ECB: 'aes-256-ecb',
AES256CBC: 'aes-256-cbc',
AES256CTR: 'aes-256-ctr',
AES256OFB: 'aes-256-ofb',
AES128GCM: 'aes-128-gcm',
AES256GCM: 'aes-256-gcm',
CHACHA20POLY1305: 'chacha20-poly1305',
XCHACHA20POLY1305: 'xchacha20-poly1305'
}
const HASH_TO_OPENSSL = {
MD5: 'md5',
SHA1: 'sha1',
SHA256: 'sha256',
SHA384: 'sha384',
SHA512: 'sha512',
BLAKE2B256: 'blake2b256',
RIPEMD160: 'ripemd160'
}
function getCiphers() {
const out = Object.keys(constants.cipher).map(
(k) => CIPHER_TO_OPENSSL[k] || k.toLowerCase().replace(/(\d+)/g, '-$1')
)
if (!out.includes('chacha20')) out.push('chacha20')
return out
}
function getHashes() {
return Object.keys(constants.hash).map((k) => HASH_TO_OPENSSL[k] || k.toLowerCase())
}
module.exports = { getCiphers, getHashes }
+10
View File
@@ -0,0 +1,10 @@
{
"name": "crypto",
"version": "0.0.0",
"description": "Local shim: bare-crypto + OpenSSL-style getCiphers/getHashes for Bare",
"main": "index.js",
"private": true,
"dependencies": {
"bare-crypto": "^1.13.4"
}
}
+83
View File
@@ -0,0 +1,83 @@
'use strict'
const assert = require('assert')
function deepStrictEqualInner(a, b) {
if (Object.is(a, b)) return true
if (a === null || b === null) return a === b
if (typeof a !== 'object' || typeof b !== 'object') return false
if (Buffer.isBuffer(a) && Buffer.isBuffer(b)) return a.length === b.length && a.equals(b)
if (Buffer.isBuffer(a) || Buffer.isBuffer(b)) return false
if (Array.isArray(a)) {
if (!Array.isArray(b) || a.length !== b.length) return false
for (let i = 0; i < a.length; i++) {
if (!deepStrictEqualInner(a[i], b[i])) return false
}
return true
}
if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime()
if (a instanceof RegExp && b instanceof RegExp)
return a.source === b.source && a.flags === b.flags
const keysA = Object.keys(a).sort()
const keysB = Object.keys(b).sort()
if (keysA.length !== keysB.length) return false
for (let i = 0; i < keysA.length; i++) {
if (keysA[i] !== keysB[i]) return false
}
for (const k of keysA) {
if (!deepStrictEqualInner(a[k], b[k])) return false
}
return true
}
function patch(name, impl) {
if (typeof assert[name] !== 'function') assert[name] = impl
}
patch('deepStrictEqual', function deepStrictEqual(actual, expected, message) {
if (!deepStrictEqualInner(actual, expected)) {
assert.fail(message || 'deepStrictEqual mismatch')
}
})
patch('deepEqual', function deepEqual(actual, expected, message) {
return assert.deepStrictEqual(actual, expected, message)
})
patch('throws', function throws(fn, expected, message) {
let err
try {
fn()
} catch (e) {
err = e
}
if (err === undefined) {
assert.fail(message || 'Expected function to throw')
}
if (expected === undefined) return
if (typeof expected === 'string') {
if (!String(err.message).includes(expected)) {
assert.fail(message || `Expected message to include ${JSON.stringify(expected)}`)
}
return
}
if (expected instanceof RegExp) {
if (!expected.test(String(err.message))) {
assert.fail(message || `Expected message to match ${expected}`)
}
return
}
if (typeof expected === 'function' && expected.prototype) {
if (!(err instanceof expected)) {
assert.fail(message || `Expected ${expected.name || 'Error'}`)
}
return
}
if (typeof expected === 'function') {
if (!expected(err)) {
assert.fail(message || 'Expected validation function to return true')
}
}
})
module.exports = assert
+315
View File
@@ -0,0 +1,315 @@
'use strict'
try {
require('bare-process/global')
} catch {
/* Node.js */
}
const assert = require('./assert-compat.js')
const { readFileSync } = require('fs')
const { join } = require('path')
const { inspect } = require('util')
const Client = require('../lib/client.js')
const Server = require('../lib/server.js')
const { parseKey } = require('../lib/protocol/keyParser.js')
const mustCallChecks = []
const DEFAULT_TEST_TIMEOUT = 30 * 1000
function noop() {}
function runCallChecks(exitCode) {
if (exitCode !== 0) return
const failed = mustCallChecks.filter((context) => {
if ('minimum' in context) {
context.messageSegment = `at least ${context.minimum}`
return context.actual < context.minimum
}
context.messageSegment = `exactly ${context.exact}`
return context.actual !== context.exact
})
failed.forEach((context) => {
console.error(
'Mismatched %s function calls. Expected %s, actual %d.',
context.name,
context.messageSegment,
context.actual
)
console.error(context.stack.split('\n').slice(2).join('\n'))
})
if (failed.length) process.exit(1)
}
function mustCall(fn, exact) {
return _mustCallInner(fn, exact, 'exact')
}
function mustCallAtLeast(fn, minimum) {
return _mustCallInner(fn, minimum, 'minimum')
}
function _mustCallInner(fn, criteria = 1, field) {
if (process._exiting) throw new Error('Cannot use common.mustCall*() in process exit handler')
if (typeof fn === 'number') {
criteria = fn
fn = noop
} else if (fn === undefined) {
fn = noop
}
if (typeof criteria !== 'number') throw new TypeError(`Invalid ${field} value: ${criteria}`)
const context = {
[field]: criteria,
actual: 0,
stack: inspect(new Error()),
name: fn.name || '<anonymous>'
}
// Add the exit listener only once to avoid listener leak warnings
if (mustCallChecks.length === 0) process.on('exit', runCallChecks)
mustCallChecks.push(context)
function wrapped(...args) {
++context.actual
return fn.call(this, ...args)
}
// TODO: remove origFn?
wrapped.origFn = fn
return wrapped
}
function getCallSite(top) {
const originalStackFormatter = Error.prepareStackTrace
Error.prepareStackTrace = (err, stack) => `${stack[0].getFileName()}:${stack[0].getLineNumber()}`
const err = new Error()
Error.captureStackTrace(err, top)
// With the V8 Error API, the stack is not formatted until it is accessed
// eslint-disable-next-line no-unused-expressions
err.stack
Error.prepareStackTrace = originalStackFormatter
return err.stack
}
function mustNotCall(msg) {
const callSite = getCallSite(mustNotCall)
return function mustNotCall(...args) {
args = args.map(inspect).join(', ')
const argsInfo = args.length > 0 ? `\ncalled with arguments: ${args}` : ''
assert.fail(`${msg || 'function should not have been called'} at ${callSite}` + argsInfo)
}
}
function setup(title, configs) {
const {
client: clientCfg_,
server: serverCfg_,
allReady: allReady_,
timeout: timeout_,
debug,
noForceClientReady,
noForceServerReady,
noClientError,
noServerError
} = configs
// Make shallow copies of client/server configs to avoid mutating them when
// multiple tests share the same config object reference
let clientCfg
if (clientCfg_) clientCfg = { ...clientCfg_ }
let serverCfg
if (serverCfg_) serverCfg = { ...serverCfg_ }
let clientClose = false
let clientReady = false
let serverClose = false
let serverReady = false
const msg = (text) => {
return `${title}: ${text}`
}
const timeout = typeof timeout_ === 'number' ? timeout_ : DEFAULT_TEST_TIMEOUT
const allReady = typeof allReady_ === 'function' ? allReady_ : undefined
if (debug) {
if (clientCfg) {
clientCfg.debug = (...args) => {
console.log(`[${title}][CLIENT]`, ...args)
}
}
if (serverCfg) {
serverCfg.debug = (...args) => {
console.log(`[${title}][SERVER]`, ...args)
}
}
}
let timer
let client
let clientReadyFn
let server
let serverReadyFn
if (clientCfg) {
client = new Client()
if (!noClientError) client.on('error', onError)
clientReadyFn = noForceClientReady ? onReady : mustCall(onReady)
client.on('ready', clientReadyFn).on('close', mustCall(onClose))
} else {
clientReady = clientClose = true
}
if (serverCfg) {
server = new Server(serverCfg)
if (!noServerError) server.on('error', onError)
serverReadyFn = noForceServerReady ? onReady : mustCall(onReady)
server
.on(
'connection',
mustCall((conn) => {
if (!noServerError) conn.on('error', onError)
conn.on('ready', serverReadyFn)
server.close()
})
)
.on('close', mustCall(onClose))
} else {
serverReady = serverClose = true
}
function onError(err) {
const which = this === client ? 'client' : 'server'
assert(false, msg(`Unexpected ${which} error: ${err.stack}\n`))
}
function onReady() {
if (this === client) {
assert(!clientReady, msg('Received multiple ready events for client'))
clientReady = true
} else {
assert(!serverReady, msg('Received multiple ready events for server'))
serverReady = true
}
clientReady && serverReady && allReady && allReady()
}
function onClose() {
if (this === client) {
assert(!clientClose, msg('Received multiple close events for client'))
clientClose = true
} else {
assert(!serverClose, msg('Received multiple close events for server'))
serverClose = true
}
if (clientClose && serverClose) clearTimeout(timer)
}
process.nextTick(
mustCall(() => {
function connectClient() {
if (clientCfg.sock) {
clientCfg.sock.connect(server.address().port, 'localhost')
} else {
clientCfg.host = 'localhost'
clientCfg.port = server.address().port
}
try {
client.connect(clientCfg)
} catch (ex) {
ex.message = msg(ex.message)
throw ex
}
}
if (server) {
server.listen(
0,
'localhost',
mustCall(() => {
if (timeout >= 0) {
timer = setTimeout(() => {
assert(false, msg('Test timed out'))
}, timeout)
}
if (client) connectClient()
})
)
}
})
)
return { client, server }
}
const FIXTURES_DIR = join(__dirname, 'fixtures')
const fixture = (() => {
const cache = new Map()
return (file) => {
const existing = cache.get(file)
if (existing !== undefined) return existing
const result = readFileSync(join(FIXTURES_DIR, file))
cache.set(file, result)
return result
}
})()
const fixtureKey = (() => {
const cache = new Map()
return (file, passphrase, bypass) => {
if (typeof passphrase === 'boolean') {
bypass = passphrase
passphrase = undefined
}
if (typeof bypass !== 'boolean' || !bypass) {
const existing = cache.get(file)
if (existing !== undefined) return existing
}
const fullPath = join(FIXTURES_DIR, file)
const raw = fixture(file)
let key = parseKey(raw, passphrase)
if (Array.isArray(key)) key = key[0]
const result = { key, raw, fullPath }
cache.set(file, result)
return result
}
})()
function setupSimple(debug, title) {
const { client, server } = setup(title, {
client: { username: 'Password User', password: '12345' },
server: { hostKeys: [fixtureKey('ssh_host_rsa_key').raw] },
debug
})
server.on(
'connection',
mustCall((conn) => {
conn.on(
'authentication',
mustCall((ctx) => {
ctx.accept()
})
)
})
)
return { client, server }
}
module.exports = {
fixture,
fixtureKey,
FIXTURES_DIR,
mustCall,
mustCallAtLeast,
mustNotCall,
setup,
setupSimple
}
+26
View File
@@ -0,0 +1,26 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAz7MF4vhgw6HxNf3KtVf3VULTYgrRSlv+cCZdB1xxI1p/nGyu
/eekUn5C+mGeDS488DX5ulzicxVpL7pamc/tFNcp91MrR7PiIMK2l+bwbZJubbLj
DHhNcBklnFOSKxtmQRfuorGakpy/kXmIxF5of0xXGns6DlHRq9dGCJIXvrkqhcEb
k4n2y4aV4VOiMHdo6FrFQVPzA8DlbJP2SjIFZ/0VdK7O7eiyiqV1p1xlbTQQ5rAX
LdsshBn/GvoBOTCVupMXurn2582vgGh26Mmovj2QGzScMGUVttkMlnxUmKT/aQka
mC0vR54QOW7lyWPjAitOV0qgmtGm3/cl7W7NjwIDAQABAoIBAFxH0C+951BEXWV9
s1jLEqshG8YNxFtjcDLn+KFSoznv9Y7MgxtwlgPI8X1Jbe2xQ4X+lUwGBN7Y/nkk
NSjtxwphZtXqb+pVs/yWRoZLJzunucSnnFVoBg/uPFWuk9zvOYlmVrKWcnT9i+fY
tbl5sLgOdQzg/zRpidztssIQFti3o2jnpyrEGcepPWLkfCgqPfGmNv78BAIt/6iT
zYDB4GMSq/LnPTIOFsIOvlkZg3RCcLWeAPRC+lvFQVY+M/uJL5WIbA5il1IMMKH7
MULWpRO3lnb1JVrkZlBldK5uew6AN3tHDQOmg+C2JuIbOZ35J9dcnwsE+IptWWBj
XiFRJCECgYEA8BeuufkslureqOycaPLMkqchMTue1OxbLJFvPN+dh/cW6Lng3b8+
xAyzZrc0vccH/jl9WVHhIZ7TcKXDzSmmrtnZ/3m1c4gANGqIPwO+emL1ZzzkIKGd
FrLeBZKP4TWry9kjg4cG1SKGpcB5ngJMPXUxMZNe74tC4Hk820PkFjcCgYEA3XXn
ngRCgH9N1eKSD2daxxlBhTTSnTgjU+dDaDFQzPIhJCcS8HwyQBQmNTOSXXK9sShC
fdXAsmiBby5WEBq/K5+cXeDG2ZlFLyPovEgTUrLgraw42PYs0+A8Ls7dFk7PuMez
3G2gUPkY039JiyXKfcog9/dIRfbWCwzQ6s7TV2kCgYEArsme81cahhgg1zvCNokk
M1Omz2/HFt2nFpAeOmPVDGnu7Kh9sxGKgTF53bpclBh0kjiKL99zFYXKCoUzQYYk
CcEhemLBnYUSGRbBb5arMfAfFfR3Y+YkNaUsC0SCqILpOfMvbo57g+ipu7ufDlA/
7rIFiUDvaVap7j909W+8egsCgYEAsuc/0DBixMmSyHl7QwRcmkC15HVSu32RVIOb
ub01KAtmaH1EWJAMTCW64/mggOtjgI0kgeE/BSFVhsqo7eOdkhEj0db27OxbroRU
zF1xdrpYtRRO7D6a4iLgm3OzuQS72+tASo8pFqDUxG6sq8NAvLOgRJE4ioSoT07w
KvAgXRkCgYEAmWgcsX/BdNcKOteSDtPkys5NRtWCBz7Coxb+xXXoXz1FVegBolpY
wXVePvXTIbU8VJOLunMyH5wpmMUiJbTX9v2o/yfpsH0ci4GaAeVtqpA=
-----END RSA PRIVATE KEY-----
+33
View File
@@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFuzCCA6OgAwIBAgIUPtNIRfp8v8RsObCr+9LVosWVD/QwDQYJKoZIhvcNAQEL
BQAwbTELMAkGA1UEBhMCVVMxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcM
CVNvbWUtQ2l0eTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIw
EAYDVQQDDAlsb2NhbGhvc3QwHhcNMjAxMjIwMDQwNTM1WhcNMzAxMjE4MDQwNTM1
WjBtMQswCQYDVQQGEwJVUzETMBEGA1UECAwKU29tZS1TdGF0ZTESMBAGA1UEBwwJ
U29tZS1DaXR5MSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQ
BgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
AJ/m96/mBMFoUWUOFSvvmJjHj/XxnO89ClCcCIFA6bJNCJMFZV3m853HAhP9g3kF
M3hL0c96GKS5IsRJiNUMrIUYrWCPh1yUJCNfczyGbBJNcEoRhfqCuuzjA5U7jAil
jqLWBP+ZI0tKRuQXX4bDHp51qDESscxNHZQp0+Lho86y4XjZPnT1OYd5rl3D6D82
AElOrGOtsj7KmHl3eYhQoKNDlCGa5ZK+L05rsClU5m/LXyGmf5QtOIF00JqJ7KS4
mX3ZF+XE/+3gkXLJyOCOYFDLjGY7WjsJXz3Wm6pktW8NGqhMaaRfIINqtCQkDgMk
gTjF3TtEA/M2DsGU2edL3qm/ibQ4z88dMVkLGZ6DWZg5oGwZR0W8jRAauhWO01Qq
JSLF3Rhvj4VasF4Hj6sI2HQcgGlDFqPNs/ErTA91mN/+yzXzCYIGBUeF5cSbIsLL
TNo6fCHKRIYqpHYCQjwBYQh/2R4/o/BHHkePVWDN0dg2VAyrp/YhV3YTfs3M4ond
yx2CoW1FJHPlhsmGH3A6PlWe2dRgu9f0ZejOX+eefqkkJtrVbmxfVCB9KET7TrV1
lBX/V6bnFwmT0fygeBHd0aR+h8dvIs3E/wovLp4MZjtT97p+IMcGUcH9AmbFlXgi
VOnYx4/3WLuqGpyurDaCWwJDmtdCDoclZeZ3ef+IEi3/AgMBAAGjUzBRMB0GA1Ud
DgQWBBTQsY4pBOEhu4+hJb5KqaxKNBMPLTAfBgNVHSMEGDAWgBTQsY4pBOEhu4+h
Jb5KqaxKNBMPLTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQBf
+YfOSlOw79aCdtU40OH51QFJxuK54ryxpzRcpBeDE57HfnuNHAM+z+5xVu8+qaRn
jo27ylmLLmzlWV946Yb+fyxIZb37KNXiIYehPTYyiG9MYmE3kEH/kLEvU8SQ6zO5
6CVP3RN+HP1ZdgHi4Zq6DLsngr/ma8nAXuRUgsvLogB2yrtTJTlMB5631ahdD3U8
kInPa1FlWYjq0QvllzMJ2q/uUG8kMLZRArqKMxb6j5hqHZuA2PAhb1h2K54doOWt
26HdGPVBxZcnE7HUUqKMAxAf++vmYicDTSv6rsEONxmG9cn0SQWzUnr3G6zZ4uxF
9wlvl5/VN6jT9XtS9rpZfwOVLigmuhMFkUCxTTN0eHOh0u76QSk2nphxumIj1vc+
I9G/KNk0R3G+7AyjDK2WIxaqUTChpBfytQoiiQCOYEL+KlJboWhYL7mfeBT2flzH
H3/LfF61Y8V2H5pjX1x+e/FghA5OFiHsrgoJVegVYu6v0JyCzNwGaSvnpu8QZcOZ
lT6d4UKS8JmIuq2w7iru6cURBRzMfBZ4qaX3Gm/NSDfi6q/8aL/mogzQHg91lrFz
AXZUkb+WGikJ6TEgL9M4qBHwgssk7ayEejBhIuLxQD654Py8P8diEt/77iY0qsS9
EEw/onPXr9nLLeIcigQEa2+14msAb2I7a2/RhlUW+Q==
-----END CERTIFICATE-----
+52
View File
@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQCf5vev5gTBaFFl
DhUr75iYx4/18ZzvPQpQnAiBQOmyTQiTBWVd5vOdxwIT/YN5BTN4S9HPehikuSLE
SYjVDKyFGK1gj4dclCQjX3M8hmwSTXBKEYX6grrs4wOVO4wIpY6i1gT/mSNLSkbk
F1+Gwx6edagxErHMTR2UKdPi4aPOsuF42T509TmHea5dw+g/NgBJTqxjrbI+yph5
d3mIUKCjQ5QhmuWSvi9Oa7ApVOZvy18hpn+ULTiBdNCaieykuJl92RflxP/t4JFy
ycjgjmBQy4xmO1o7CV891puqZLVvDRqoTGmkXyCDarQkJA4DJIE4xd07RAPzNg7B
lNnnS96pv4m0OM/PHTFZCxmeg1mYOaBsGUdFvI0QGroVjtNUKiUixd0Yb4+FWrBe
B4+rCNh0HIBpQxajzbPxK0wPdZjf/ss18wmCBgVHheXEmyLCy0zaOnwhykSGKqR2
AkI8AWEIf9keP6PwRx5Hj1VgzdHYNlQMq6f2IVd2E37NzOKJ3csdgqFtRSRz5YbJ
hh9wOj5VntnUYLvX9GXozl/nnn6pJCba1W5sX1QgfShE+061dZQV/1em5xcJk9H8
oHgR3dGkfofHbyLNxP8KLy6eDGY7U/e6fiDHBlHB/QJmxZV4IlTp2MeP91i7qhqc
rqw2glsCQ5rXQg6HJWXmd3n/iBIt/wIDAQABAoICAQCb0z8o4WVc/UXkzvZ+3Hy+
1itKp+whkECPEZ+QJiwXn85tR+LiwYBDD37M8E7BDvp7jpemMvv0+p4Q3wBDbphp
FAVRhk2JQKx+9DOelfiXVXPKGo2P9Poog4ooUeFDQ+NeeGZil1+3rWisOsLS1y7t
iQcg23D9AWGD08cy4GT7t4LWfA7Ld3ZauY/cvF+FyiA5UDva35hGbLRuGqoK11fU
ArVGkmaKvF/pcjQ38w6lf3DzoAfP5MmeDrKDB0nftC2QYJFTTsmBjUjwrgfeHaFq
2xG1Rr3FrnpsDsmgIYhV8lU6EU0Z68IJj2CBn8kv8tEi/F99s+iNiO6UY3R+XIdd
Jng5zPxHwprzKjvdfl6e4KhwkV8YJbPW0SFDj6Y0Ie0CdSysdJ8BhT7dk7LvJH1Q
DhQSAFftSna4MW5fzAogyQVL+KF3JnQ9BvFZX1swlIqBDHc6DeM+sFg0U++7qFyl
nZellskBgfLXlGCjgGEC/W5pUOaZzBk1BGa8x8Zm3vA//uaoOw/BKizfa+p0VqoU
bC4E8HEK+Rqj9oB07wVliqU9mCqrc5offhjeft9YbUAqx6GPG+1kPiKW1F4++iT2
Yils/euv+gtK9d9JbMUCCH6mp1wIy40a14XisA8/O8NONjF63VTZX3try7rjOKxd
D0W68FGzACIkRkmTTc2NsQKCAQEAzKq7Lk/6cf2bzSQc0oH0XWxuA497czTQYj7l
k4UkGcUeEu9qOp3qU66KjmqLXLJnF233tQ2ArpiwX7tHNmhXZmIufNxa0Gue2VGx
eyRO/aTCnD1FsSayX1KcaLrwvg5gvwOPQLNCacMc47RCyI6/05irXfNtRlqKKm+R
ZgnhHxcwMzX5lLX9Rr54AWp0yuLEK+i0lcKsNnypAMl/C9GTqk3dEpao0y6SGHiW
Ih8Q2Cy4LbRD48PWuf9rBvb3iZyiLe0xemD8wuNN0j7/Xt9tcL4OuzkmkzWCyslM
Qi3yNw6eRziFhzdpDdHpJjFjEnGI94jgt1AYJtesFvSf8Tz7jQKCAQEAyAH7JQKx
mYvaRioAaUKQHiLImPxypt5cEGiyrPdiBBrU+3fBTC/EZJn/VK7ApM+7YRqvO/vz
d9orkvsWfzxpQM1xhBZ3bwTWXXWRz7g5vzKwJk4pZkXaUk+QAUwp79OrZFTcQokJ
d/l1wj5sUQCrs0l5gD5M3O6ZXPWLoSv1gBI7ktBxXY3VBrQ0uAwE9mQHjyrO+Utc
fcdFEtOqwOxyQQmcsj0vjGm385FmtuIG/pSzhvPXGyo3VYrQjTXT7pYnghu3LBgg
JJuE8kOAlSVTL0ccSO9GLqvj2bTyLlrFcKPBReXHNLwl5kij2w7WBTPGQn61u+ye
+bmSunIkjE2muwKCAQEAr/k4OcjAgJRbCpY7RfBAyLb7HIqYzWSiq2aDBEUc1h97
DTLXNpEislLHhU4sh0ZJh4agzgZPF0/njlg7EZfDVh+i8u6QEtYF3br1C/kbBdFN
FwND0d6AzZ79JrtdVTyNiI8p86pttvvw8gPCzCiY3PlOltg/o5cjZvtIm+BwtMe+
RLnq3ydfHx2TlzwOMYeqvko2QvIAGlUzBp85YlMPUQXjyCDMBc/sA6hjBfGKDSTe
M0XkfYicLo5jWrir+6E2fKCNwzhy+6pu9g/+iHc45RA1IFsyRK5kx7EupVRWB2rF
Ql1hyfIlnKFYguNB2NDPwG3rMRJnwbX8nDw27TfO3QKCAQEAlHAb82DnbFzGF3LO
sVBMY4FPPXOGp9+5lhgOG57SKNe9IBDF7gQ5jqxYOoIjyW2+1JeYXD1meZn64u/k
x3OPbh/LUsvVwhhl/CDoobBJc2RsJVG3GgdXu+T+rGfZa/u9ZQ4yFlNcKqWCxzHK
8+c6hypNuWcDZqjSO5KlGW3lmzJs8k4vBM7hvkL6KWoKOM8OaSvNRmmu8E53LjzX
qq0RMsGugP42DtDbTDKqd6qSpFi6ULsh9zBCtwL6OwMrEhRwp/hn3prdKC4f4ilF
Aewcq6bsEBk9DiBWT1oir1KA3FM8euLJEJNe0WUx7r85Cc1eJDWkLR+08QPQKP3T
sCllRwKCAQBQgSFFI65dlLJf/iJrZPuP3sCzZNABe4y7lxZK2Gij4FXzf2KA1SAl
dyxuUU+Hv98l52pJIWmoNYWKEXOorsu+TuadgiK11DSx/ajQ9y8OEbscOVTJwrv3
aVbaz4f0z2AKRLrBLsln2aVLQVPF5dsPNmsYIUWOrvBJ+DFFeXQG+QWimS2VbS+P
wrDdpVej8sEaUVfCqvCAx8gWtrFtE401BmfNla1xFGHiHhcLrsqKj3uxIojQ0Met
fFCrKqxES0OQ6pY/9VlrBmfihw/Bt1LWMPUo90atFArbwGaUxXLwi4FwRafkW5Di
k77w3OGObcFv4zxCOoFxcXXc3MCyw3r8
-----END PRIVATE KEY-----
+12
View File
@@ -0,0 +1,12 @@
-----BEGIN DSA PRIVATE KEY-----
MIIBuwIBAAKBgQC3/2VIGHgqHuxvhPa6rryqqLy6sQmjeSIwyrIW5F/o8W4sz/mE
0noDSW4PaoXjgPQv5egj1EByws6dMOUqLaZHNWNn+Lh/jkKlwKyhbSCAjqoWH3v3
uI1j58GO/eZ2+REijfyA0XJxdm7kqEexxbg0UpFr1F/eLBUxpLIbhhS1cwIVAKcB
B9DnAObuPJGTwYTCaIIBQDy9AoGAJicW0pIFwgoTYsIeywmUQopJ3FQ4M3eDwQ0U
T33pzWvBZFN2OsUDTFg64PNm9ow09wk042qMg168eKCUTp2iR/Y9R4xTj8dls8iv
aMGMZ/B32eURIjUREGiXYTyG1pfuB2znSvr/5pavhuz5yG9M0AJCiYiexdaQKO3N
oJp6T3ACgYEAsep79p4WljnawrJc928zGq6dLYjs+5apYhqx4vf2l3Z2u26VqVNG
i5zZkUzhWQYV3/qtEOpO43dyZTHW+d9L8ni6HbXFWRVx60WE+5WKkzkimHJ6gox2
kDvOqPudiS34KJOCEYYLEnJmK8aUZBZzWFORXkN8QgA/h9ts8AU785UCFAVXZMWq
CteWCH2HzcY2x/65dMwL
-----END DSA PRIVATE KEY-----
+5
View File
@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIPMZuWP7fMsZeyC1XXVUALVebJOX7PTwmsPql9qG25SeoAoGCCqGSM49
AwEHoUQDQgAEB/B6mC5lrekKPWfGEkKpnCk08+dRnzFUg2jUHpaIrOTt4jGdvq6T
yAN57asB+PYmFyVIpi35NcmicF18qX3ayg==
-----END EC PRIVATE KEY-----
+15
View File
@@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDL0yFO4W4xbdrJk/i+CW3itPATvhRkS+x+gKmkdH739AqWYP6r
kTFAmFTw9gLJ/c2tN7ow0T0QUR9iUsv/3QzTuwsjBu0feo3CVxwMkaJTo5ks9XBo
OW0R3tyCcOLlAcQ1WjC7cv5Ifn4gXLLM+k8/y/m3u8ERtidNxbRqpQ/gPQIDAQAB
AoGABirSRC/ABNDdIOJQUXe5knWFGiPTPCGr+zvrZiV8PgZtV5WBvzE6e0jgsRXQ
icobMhWQla+PGHJL786vi4NlwuhwKcF7Pd908ofej1eeBOd1u/HQ/qsfxPdxI0zF
dcWPYgAOo9ydOMGcSx4v1zDIgFInELJzKbv64LJQD0/xhoUCQQD7KhJ7M8Nkwsr2
iKCyWTFM2M8/VKltgaiSmsNKZETashk5tKOrM3EWX4RcB/DnvHe8VNyYpC6Sd1uQ
AHwPDfxDAkEAz7+7hDybH6Cfvmr8kUOlDXiJJWXp5lP37FLzMDU6a9wTKZFnh57F
e91zRmKlQTegFet93MXaFYljRkI+4lMpfwJBAPPLbNEF973Qjq4rBMDZbs9HDDRO
+35+AqD7dGC7X1Jg2bd3rf66GiU7ZgDm/GIUQK0gOlg31bT6AniO39zFGH0CQFBh
Yd9HR8nT7xrQ8EoQPzNYGNBUf0xz3rAcZCWZ4rHK48sojEMoBkbnputrzX7PU+xH
QlqCXuAIWVXc2dHd1WcCQQDIUJHPOsgeAfTLoRRRURp/m8zZ9IpbaPTyDstPVNYe
zARW3Oa/tzPqdO6NWaetCp17u7Kb6X9np7Vz17i/4KED
-----END RSA PRIVATE KEY-----
+26
View File
@@ -0,0 +1,26 @@
PuTTY-User-Key-File-2: ssh-rsa
Encryption: none
Comment: rsa-key-20150522
Public-Lines: 6
AAAAB3NzaC1yc2EAAAABJQAAAQB1quqP0rhl78NOLD4lj+1x5FGAqZ3aqo6GiEPz
KOaQmy86FuJMK0nHj3gUKTa/Kvaa+8PZyeu+uVseHg47YrynCOcJEEnpqvbArc8M
xMWuUnTUMrjvokGDOBBiQu4UAE4bybpgXkNHJfbrcDVgivmv3Ikn8PVIZ1rLBMLZ
6Lzn0rjPjFD0X4WqsAJW2SFiZnsjMZtVL2TWadNTyyfjjm2NCRBvd32VLohkSe9Q
BZBD6MW8YQyBKUnEF/7WNY0eehDVrfx1YqPOV1bDwFUhRaAYpLDLDR0KCAPvx7qb
8G5Cq0TIBsEr3H8ztNRcOTQoaKgn0T18M7cyS4ykoNLYW4Zx
Private-Lines: 14
AAABACyF3DZraF3sBLXLjSL4MFSblHXfUHxAiPSiQzlpa/9dUCPRTrUJddzOgHZU
yJtcXU9mLm4VDRe7wZyxbSs6Hd5WZUGzIuLLEUH8k4hKdE/MLDSdkhV7qhX5iaij
tAeRaammRoVUGXTd7rnzGx2cXnnkvkZ22VmqkQ6MLg1DTmWNfOO9cdwFGdQawf/n
yUV0nTkWsHXy5Qrozq9wRFk8eyw+pFllxqavsNftZX8VDiQt27JLZPTU4LGkH660
3gq1KhNS/l05TlXnMZGjlcPN8UEaBzmCWRezhJSttjs5Kgp1K3yDf4ozMR/HWOCj
Jq8fd3VIgli6ML8yjr/c0A0T9MUAAACBAL1/byxHiCvY/2C+/L5T+ZZq13jdZuYK
MmOFaNITgEdNGWSIFYRzhLKGXj7awQWOIW6chj470GNOfQjFL1TvXhbwfqW6esDa
kETOYQPYQHZijABcn7uurMUm/bu5x/z9gYkAfniOCI5vmvMvJ09JcZ0iUmFWDZZY
fAutBvrt+n/vAAAAgQCe9jrA51wn1/wzKmWF+2+OWFUG9usheIcEbHB8mxLguLfU
+x4i+2vLo0FtXEPAw+Bt7Tge4t0m6USiVZXtW/QKsh0kMj4mNVHFz+XXw4l1QOYv
n5TjnLepiP7majXv4GHI2eOcHkyly4sIkj4jNLYqvT86hMxW4IC+jtJEWhn/nwAA
AIEAlJ8cExu2WrWukTDJQHrVegtvdJUhNjol2wLucPuWwSxKuB8FHYwaPRYRkf3d
DkZ53hhjJZ0BVkAaQ28uqM09xKD+q1H4/r0nnbtlV4uHLl3cCD5mGrH8I/iDPJX4
fFIqCa0+n1D6RzvDqs1QIu+PGSp0K6vHOOS5fP0ZpuT025E=
Private-MAC: 4ca26008c85b901f4d2766b0924c25e527678d7e
+30
View File
@@ -0,0 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,CCE70744FB28F2EFB1D74377281A780C
1WiGnqpSGXFIg+WYr7T2XN72C1YrNQ1jmRISb32TB/Rh2Zo47fjyQnv9impz8b6m
91R/qF7uCLI0fswvT5oqwn1L0vUAA0YtW/E2IQJEx5GPiaexoDJYYfu2yy036Kca
e9VtCajgrV+kycg1CknCxQKMcKXNq8Czvq66PM4Bzknek5hhdmxHxOl0QAE+8EXt
pnasOGz3szTUKkD6givwWgvDXY3BnVG46fXff99Xqgb6fx5IDbAkVKaxWIN/c81E
b0rcfyoLb7yjPgNYn9vUI6Z+24NMYUYARzb3dG5geaeX0BYb/VlCtJUsP0Rp2P2P
jl+cdvBKaeOvA9gPo/jAtSOFexQRs7AzKzoOLYU1fokd8HhqxOKAljn9ujmEqif7
qcimk2s7ff6tSSlxtRzDP+Uq9d1u5tyaONRV2lwj+GdP1gRoOmdZL5chdvoAi0I8
5eMf58hEuN2d4h4FryO6z7K+XQ9oo6/N/xHU0U/t2Pco9oY2L6oWMDxKwbfPhaD5
CcoEElsK4XFArYDielEq9Y1sXaEuwR5I0ksDDsANp74r9Bhcqz60gJa6hVz0ouEU
QA67wV9+TRmulKRxwANvqxQwqPuxqcTPeJjXSUN/ZCaDwYmI+d1poxMx2fQzT82M
onlgOWq+3HbCotyoeFpCameymwDQzmrYdMBr7oWLgnOrxmJ89zDc6+jkHFgQJvnU
atyeVDqe866ZvvIGWS+r/EsDjV3cTW/cJvdsC+5BpnoXoVF4LqxE3LFbEbQBvqio
4enCZpspQSMOJra37vSofbD+DyI5Wd+y8SBmfDLjyDFhT0spW9aN99uFqSc3UElA
SAmnFmpYBFEQrRGpvpu5sC0c/YjZeRXr0/F1xPpIT1SWzpRsbcsWRBDzWjLOKWQx
8ytwc2QS7eKedfqkPWpYKW0Qtps+XgnGWA6PBX42IYhLsKANRfhFXQv5LPqLNNOn
3EsG9pd+0dBpfxFQfyyAKAUuvpJNgJ6kNx8VSj8Ppj8lyUdGa9YucgB02m7gHC9U
A4YyJsIcjo6IcrjM+ez1govRRS0nE8AUb8ups9tn8mdBwqcPCrgcJhV7JkOYNJYh
NAh0vgmneOq8LSVs2SRaL3uuLNbjh1LR9iViwbIY8kMQXkiXa2/V+PFwt5oqeX5f
2x3yzCeGBiQW10InyBBnKutbPD85R4YJhQ55bOMDSFfGGqwOU1QURiO1NUzf9n/2
+E8VE7J/IQoO0TrJpC+EV0ROKME9W6+AvEFdmdIigbq3bkdEgSixyLnrhV8V8T4N
nbKlLoqfXt8DmT+h8XPzgsu0Fq/PNi6xBaiUsaN9tK6OP2ZVjr9ihbeLTI0rcKDr
XX2cWPvTcboRLt+S4wmqchMf7Kxa2PfX5Tf+KCcdZNQO4YqS23wQZgk61kuOQCsS
uOop+ICI7yWZkjqCOzGOeHLl/7FyFeprsFDIwD1g20y9bzibbJlbQPhwXSalqDQT
MWLH3rdFuvgLH7ujtjxSakES+VzkOhbnmb/Wypbl1D7P7GT2seau16EEGQDhDzcJ
Q4d/BjR2WqqxmC79MOAvUWAu6fZQjPD30/gYPGpMaEuiLrDlzDqvf+oi4A9+EtRL
-----END RSA PRIVATE KEY-----
+21
View File
@@ -0,0 +1,21 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsgAAAAdzc2gtZH
NzAAAAgQDg+DsMAituSW/NJpWVy2w7xN6Uu/IfCqpy38CFBW+mBnOX7OzPulI+1uZxXRLy
UKiQDAegXCqSHMCo5ACZhw2BRwq74J4VA5fOFGdwcacTQo1zKDF64wvyVSgQE/E2PSFLKu
NHHtRFnjvq6WrgTQsL9aif2FBWS5q0MGahzXhNkQAAABUAn1ASRSRcIVsWqrrZubFQq4pU
OlMAAACBALcKIRLTtYG5+N/vzEULdsXSGToDRth6X5Yjb7c0UotAmy9VGrnmN5IO+//1em
2USHeSoO+5shRq92zdggdQwNaXXzU301huIETztfRwGHOfUGZbzJmIqdzLhdziFhneAzaN
zVeUFyIqvWL1Q89WgC2Uh3DY/lK/gIhRK7WD0cDAAAAAgC882WUEEig48DVyjbNi1xf8rG
svyypMHSs2rj6pja2Upfm+C5AKKU387x8Vj/Kz291ROIl7h/AhmKOlwdxwPZOG5ffDygaW
Tlo4/JagwP9HmTsK1Tyd1chuyMk9cNLdgWFsCGGHY2RcEwccq9panvvtKp57HqDaT1W7AS
g2spT9AAAB8G4oDW5uKA1uAAAAB3NzaC1kc3MAAACBAOD4OwwCK25Jb80mlZXLbDvE3pS7
8h8KqnLfwIUFb6YGc5fs7M+6Uj7W5nFdEvJQqJAMB6BcKpIcwKjkAJmHDYFHCrvgnhUDl8
4UZ3BxpxNCjXMoMXrjC/JVKBAT8TY9IUsq40ce1EWeO+rpauBNCwv1qJ/YUFZLmrQwZqHN
eE2RAAAAFQCfUBJFJFwhWxaqutm5sVCrilQ6UwAAAIEAtwohEtO1gbn43+/MRQt2xdIZOg
NG2HpfliNvtzRSi0CbL1UaueY3kg77//V6bZRId5Kg77myFGr3bN2CB1DA1pdfNTfTWG4g
RPO19HAYc59QZlvMmYip3MuF3OIWGd4DNo3NV5QXIiq9YvVDz1aALZSHcNj+Ur+AiFErtY
PRwMAAAACALzzZZQQSKDjwNXKNs2LXF/ysay/LKkwdKzauPqmNrZSl+b4LkAopTfzvHxWP
8rPb3VE4iXuH8CGYo6XB3HA9k4bl98PKBpZOWjj8lqDA/0eZOwrVPJ3VyG7IyT1w0t2BYW
wIYYdjZFwTBxyr2lqe++0qnnseoNpPVbsBKDaylP0AAAAVAIoWASGAfFqckLwvtPRNCzow
TTl1AAAAEm5ldyBvcGVuc3NoIGZvcm1hdAECAwQFBgc=
-----END OPENSSH PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
ssh-dss AAAAB3NzaC1kc3MAAACBAOD4OwwCK25Jb80mlZXLbDvE3pS78h8KqnLfwIUFb6YGc5fs7M+6Uj7W5nFdEvJQqJAMB6BcKpIcwKjkAJmHDYFHCrvgnhUDl84UZ3BxpxNCjXMoMXrjC/JVKBAT8TY9IUsq40ce1EWeO+rpauBNCwv1qJ/YUFZLmrQwZqHNeE2RAAAAFQCfUBJFJFwhWxaqutm5sVCrilQ6UwAAAIEAtwohEtO1gbn43+/MRQt2xdIZOgNG2HpfliNvtzRSi0CbL1UaueY3kg77//V6bZRId5Kg77myFGr3bN2CB1DA1pdfNTfTWG4gRPO19HAYc59QZlvMmYip3MuF3OIWGd4DNo3NV5QXIiq9YvVDz1aALZSHcNj+Ur+AiFErtYPRwMAAAACALzzZZQQSKDjwNXKNs2LXF/ysay/LKkwdKzauPqmNrZSl+b4LkAopTfzvHxWP8rPb3VE4iXuH8CGYo6XB3HA9k4bl98PKBpZOWjj8lqDA/0eZOwrVPJ3VyG7IyT1w0t2BYWwIYYdjZFwTBxyr2lqe++0qnnseoNpPVbsBKDaylP0= new openssh format
+7
View File
@@ -0,0 +1,7 @@
{
"type": "ssh-dss",
"comment": "new openssh format",
"public": "-----BEGIN PUBLIC KEY-----\nMIIBtzCCASwGByqGSM44BAEwggEfAoGBAOD4OwwCK25Jb80mlZXLbDvE3pS78h8K\nqnLfwIUFb6YGc5fs7M+6Uj7W5nFdEvJQqJAMB6BcKpIcwKjkAJmHDYFHCrvgnhUD\nl84UZ3BxpxNCjXMoMXrjC/JVKBAT8TY9IUsq40ce1EWeO+rpauBNCwv1qJ/YUFZL\nmrQwZqHNeE2RAhUAn1ASRSRcIVsWqrrZubFQq4pUOlMCgYEAtwohEtO1gbn43+/M\nRQt2xdIZOgNG2HpfliNvtzRSi0CbL1UaueY3kg77//V6bZRId5Kg77myFGr3bN2C\nB1DA1pdfNTfTWG4gRPO19HAYc59QZlvMmYip3MuF3OIWGd4DNo3NV5QXIiq9YvVD\nz1aALZSHcNj+Ur+AiFErtYPRwMADgYQAAoGALzzZZQQSKDjwNXKNs2LXF/ysay/L\nKkwdKzauPqmNrZSl+b4LkAopTfzvHxWP8rPb3VE4iXuH8CGYo6XB3HA9k4bl98PK\nBpZOWjj8lqDA/0eZOwrVPJ3VyG7IyT1w0t2BYWwIYYdjZFwTBxyr2lqe++0qnnse\noNpPVbsBKDaylP0=\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAB3NzaC1kc3MAAACBAOD4OwwCK25Jb80mlZXLbDvE3pS78h8KqnLfwIUFb6YGc5fs7M+6Uj7W5nFdEvJQqJAMB6BcKpIcwKjkAJmHDYFHCrvgnhUDl84UZ3BxpxNCjXMoMXrjC/JVKBAT8TY9IUsq40ce1EWeO+rpauBNCwv1qJ/YUFZLmrQwZqHNeE2RAAAAFQCfUBJFJFwhWxaqutm5sVCrilQ6UwAAAIEAtwohEtO1gbn43+/MRQt2xdIZOgNG2HpfliNvtzRSi0CbL1UaueY3kg77//V6bZRId5Kg77myFGr3bN2CB1DA1pdfNTfTWG4gRPO19HAYc59QZlvMmYip3MuF3OIWGd4DNo3NV5QXIiq9YvVDz1aALZSHcNj+Ur+AiFErtYPRwMAAAACALzzZZQQSKDjwNXKNs2LXF/ysay/LKkwdKzauPqmNrZSl+b4LkAopTfzvHxWP8rPb3VE4iXuH8CGYo6XB3HA9k4bl98PKBpZOWjj8lqDA/0eZOwrVPJ3VyG7IyT1w0t2BYWwIYYdjZFwTBxyr2lqe++0qnnseoNpPVbsBKDaylP0=",
"private": null
}
+7
View File
@@ -0,0 +1,7 @@
{
"type": "ssh-dss",
"comment": "new openssh format",
"public": "-----BEGIN PUBLIC KEY-----\nMIIBtzCCASwGByqGSM44BAEwggEfAoGBAOD4OwwCK25Jb80mlZXLbDvE3pS78h8K\nqnLfwIUFb6YGc5fs7M+6Uj7W5nFdEvJQqJAMB6BcKpIcwKjkAJmHDYFHCrvgnhUD\nl84UZ3BxpxNCjXMoMXrjC/JVKBAT8TY9IUsq40ce1EWeO+rpauBNCwv1qJ/YUFZL\nmrQwZqHNeE2RAhUAn1ASRSRcIVsWqrrZubFQq4pUOlMCgYEAtwohEtO1gbn43+/M\nRQt2xdIZOgNG2HpfliNvtzRSi0CbL1UaueY3kg77//V6bZRId5Kg77myFGr3bN2C\nB1DA1pdfNTfTWG4gRPO19HAYc59QZlvMmYip3MuF3OIWGd4DNo3NV5QXIiq9YvVD\nz1aALZSHcNj+Ur+AiFErtYPRwMADgYQAAoGALzzZZQQSKDjwNXKNs2LXF/ysay/L\nKkwdKzauPqmNrZSl+b4LkAopTfzvHxWP8rPb3VE4iXuH8CGYo6XB3HA9k4bl98PK\nBpZOWjj8lqDA/0eZOwrVPJ3VyG7IyT1w0t2BYWwIYYdjZFwTBxyr2lqe++0qnnse\noNpPVbsBKDaylP0=\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAB3NzaC1kc3MAAACBAOD4OwwCK25Jb80mlZXLbDvE3pS78h8KqnLfwIUFb6YGc5fs7M+6Uj7W5nFdEvJQqJAMB6BcKpIcwKjkAJmHDYFHCrvgnhUDl84UZ3BxpxNCjXMoMXrjC/JVKBAT8TY9IUsq40ce1EWeO+rpauBNCwv1qJ/YUFZLmrQwZqHNeE2RAAAAFQCfUBJFJFwhWxaqutm5sVCrilQ6UwAAAIEAtwohEtO1gbn43+/MRQt2xdIZOgNG2HpfliNvtzRSi0CbL1UaueY3kg77//V6bZRId5Kg77myFGr3bN2CB1DA1pdfNTfTWG4gRPO19HAYc59QZlvMmYip3MuF3OIWGd4DNo3NV5QXIiq9YvVDz1aALZSHcNj+Ur+AiFErtYPRwMAAAACALzzZZQQSKDjwNXKNs2LXF/ysay/LKkwdKzauPqmNrZSl+b4LkAopTfzvHxWP8rPb3VE4iXuH8CGYo6XB3HA9k4bl98PKBpZOWjj8lqDA/0eZOwrVPJ3VyG7IyT1w0t2BYWwIYYdjZFwTBxyr2lqe++0qnnseoNpPVbsBKDaylP0=",
"private": "-----BEGIN DSA PRIVATE KEY-----\nMIIBvAIBAAKBgQDg+DsMAituSW/NJpWVy2w7xN6Uu/IfCqpy38CFBW+mBnOX7OzP\nulI+1uZxXRLyUKiQDAegXCqSHMCo5ACZhw2BRwq74J4VA5fOFGdwcacTQo1zKDF6\n4wvyVSgQE/E2PSFLKuNHHtRFnjvq6WrgTQsL9aif2FBWS5q0MGahzXhNkQIVAJ9Q\nEkUkXCFbFqq62bmxUKuKVDpTAoGBALcKIRLTtYG5+N/vzEULdsXSGToDRth6X5Yj\nb7c0UotAmy9VGrnmN5IO+//1em2USHeSoO+5shRq92zdggdQwNaXXzU301huIETz\ntfRwGHOfUGZbzJmIqdzLhdziFhneAzaNzVeUFyIqvWL1Q89WgC2Uh3DY/lK/gIhR\nK7WD0cDAAoGALzzZZQQSKDjwNXKNs2LXF/ysay/LKkwdKzauPqmNrZSl+b4LkAop\nTfzvHxWP8rPb3VE4iXuH8CGYo6XB3HA9k4bl98PKBpZOWjj8lqDA/0eZOwrVPJ3V\nyG7IyT1w0t2BYWwIYYdjZFwTBxyr2lqe++0qnnseoNpPVbsBKDaylP0CFQCKFgEh\ngHxanJC8L7T0TQs6ME05dQ==\n-----END DSA PRIVATE KEY-----"
}
+22
View File
@@ -0,0 +1,22 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABBgJ5gXYn
/2IFE2+CrAxYR8AAAAEAAAAAEAAAGxAAAAB3NzaC1kc3MAAACBAPKhVnFGWb0KLibdYnJz
0RwFy/mt98KMIdByHKQWRm9UjoVJk1ypuQpnj+bqFnxCzCFSU9OUj0/Xe0Wuk+kF2BtMO0
w+ZYfVHCqEaaIJ1D/iLqi8aBbYs552l9+P0DsFUlTE0D/AvKTQ2PsztFq7wHUTQVmnj4vy
k1bw7ske+ImLAAAAFQDnXsk6hdenasLyE8ylLHSE+0XR3QAAAIBsMerhmMT0/416hJV/pr
s7crOX0e0gF8C7kar/ILj5WULX7k143+4lgluoogrPXbd5fXgOnqdQawow8a/IjU62Sz6n
/qfHLJtQ2sJOK2Vkj5NF2UCcRHrewqJw9nDCS7yYh3c+gUfIBcIRkEJK6eRJfrZuaq0Yue
nUa9AuFwnjPAAAAIBwjDUjp9jaJu46eobNK8CWJL/Noi2fXTtFZFgUFRwkr/FXLLsOckQT
mYxaWcxP4NwuvMyI25tOueM0RvAIR7J3Afc5pbuCx6dIgiOf2gRClQU5OlqhrnMW2BQXlR
hBKBNMp5LjM5t46KTBkjh/30//s4Kimrp/C2XBGgEuRdgyqQAAAgDIGP0oYyi7sTk0HdU9
uWZLaDhHpW4Z8xTzfgUDbxoTYQ2igO90O32vSqW/cC2QKWTFuPCFnsCerHAIGzX/eyxlCQ
VyNa7VrhbNjIKAHBF3XMcRVRbW2SdYq8tHSkeZHr5EuO5dRfJ7wsR8flkPb4O4viNlIbvF
Ake8dsZEOhcnVNiv+NMR9mTq8l91wR60tr3XiWzCMkEYrJiWOfQuZSvzYi7dUmFxQuEZfQ
vIPkZD3L6XdaAz/r6YAONFAbtUMAOaUxOGV9puSsunSosAvmi+NcJ9iUM2FpAu561gp+Tv
RRcgXHxLGuzTNASiMaTN3M+HenqUh3RWmWauL5wSR7DbrH7Vq47YTnVjtg8xcZnMCfOx2D
Wz775hD6uyLwbkxKMaNMf8p4sOcXsSpHNqKmfkUxQBpNRp6Vg5W+AVaAkyXQng2LRt6txJ
Xv5zBiSFdsobkrWko/ONfGKfG+zVP+LIVcghLpp71GZQX6Ci02vB55pvk8k0G91H3INn/c
t6Q5zY5pK9VZwxjZ29psm7V+FdeD1g8VQ1Rp9muq6zDXHKKyqkBK/oGCM9UhBHFjki0gBR
v6LY/iXsz/eG14svhLjM5zYFSX7jUOI9b/PnhhL7Mos4wguHN2EjfGWuC07PkkqDPoqSwn
cC91OKhub6yqZsqvBz9BcV+2FxVNPNKzRdzA==
-----END OPENSSH PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
ssh-dss AAAAB3NzaC1kc3MAAACBAPKhVnFGWb0KLibdYnJz0RwFy/mt98KMIdByHKQWRm9UjoVJk1ypuQpnj+bqFnxCzCFSU9OUj0/Xe0Wuk+kF2BtMO0w+ZYfVHCqEaaIJ1D/iLqi8aBbYs552l9+P0DsFUlTE0D/AvKTQ2PsztFq7wHUTQVmnj4vyk1bw7ske+ImLAAAAFQDnXsk6hdenasLyE8ylLHSE+0XR3QAAAIBsMerhmMT0/416hJV/prs7crOX0e0gF8C7kar/ILj5WULX7k143+4lgluoogrPXbd5fXgOnqdQawow8a/IjU62Sz6n/qfHLJtQ2sJOK2Vkj5NF2UCcRHrewqJw9nDCS7yYh3c+gUfIBcIRkEJK6eRJfrZuaq0YuenUa9AuFwnjPAAAAIBwjDUjp9jaJu46eobNK8CWJL/Noi2fXTtFZFgUFRwkr/FXLLsOckQTmYxaWcxP4NwuvMyI25tOueM0RvAIR7J3Afc5pbuCx6dIgiOf2gRClQU5OlqhrnMW2BQXlRhBKBNMp5LjM5t46KTBkjh/30//s4Kimrp/C2XBGgEuRdgyqQ==
@@ -0,0 +1,7 @@
{
"type": "ssh-dss",
"comment": "",
"public": "-----BEGIN PUBLIC KEY-----\nMIIBtjCCASsGByqGSM44BAEwggEeAoGBAPKhVnFGWb0KLibdYnJz0RwFy/mt98KM\nIdByHKQWRm9UjoVJk1ypuQpnj+bqFnxCzCFSU9OUj0/Xe0Wuk+kF2BtMO0w+ZYfV\nHCqEaaIJ1D/iLqi8aBbYs552l9+P0DsFUlTE0D/AvKTQ2PsztFq7wHUTQVmnj4vy\nk1bw7ske+ImLAhUA517JOoXXp2rC8hPMpSx0hPtF0d0CgYBsMerhmMT0/416hJV/\nprs7crOX0e0gF8C7kar/ILj5WULX7k143+4lgluoogrPXbd5fXgOnqdQawow8a/I\njU62Sz6n/qfHLJtQ2sJOK2Vkj5NF2UCcRHrewqJw9nDCS7yYh3c+gUfIBcIRkEJK\n6eRJfrZuaq0YuenUa9AuFwnjPAOBhAACgYBwjDUjp9jaJu46eobNK8CWJL/Noi2f\nXTtFZFgUFRwkr/FXLLsOckQTmYxaWcxP4NwuvMyI25tOueM0RvAIR7J3Afc5pbuC\nx6dIgiOf2gRClQU5OlqhrnMW2BQXlRhBKBNMp5LjM5t46KTBkjh/30//s4Kimrp/\nC2XBGgEuRdgyqQ==\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAB3NzaC1kc3MAAACBAPKhVnFGWb0KLibdYnJz0RwFy/mt98KMIdByHKQWRm9UjoVJk1ypuQpnj+bqFnxCzCFSU9OUj0/Xe0Wuk+kF2BtMO0w+ZYfVHCqEaaIJ1D/iLqi8aBbYs552l9+P0DsFUlTE0D/AvKTQ2PsztFq7wHUTQVmnj4vyk1bw7ske+ImLAAAAFQDnXsk6hdenasLyE8ylLHSE+0XR3QAAAIBsMerhmMT0/416hJV/prs7crOX0e0gF8C7kar/ILj5WULX7k143+4lgluoogrPXbd5fXgOnqdQawow8a/IjU62Sz6n/qfHLJtQ2sJOK2Vkj5NF2UCcRHrewqJw9nDCS7yYh3c+gUfIBcIRkEJK6eRJfrZuaq0YuenUa9AuFwnjPAAAAIBwjDUjp9jaJu46eobNK8CWJL/Noi2fXTtFZFgUFRwkr/FXLLsOckQTmYxaWcxP4NwuvMyI25tOueM0RvAIR7J3Afc5pbuCx6dIgiOf2gRClQU5OlqhrnMW2BQXlRhBKBNMp5LjM5t46KTBkjh/30//s4Kimrp/C2XBGgEuRdgyqQ==",
"private": null
}
+7
View File
@@ -0,0 +1,7 @@
{
"type": "ssh-dss",
"comment": "new openssh format encrypted",
"public": "-----BEGIN PUBLIC KEY-----\nMIIBtjCCASsGByqGSM44BAEwggEeAoGBAPKhVnFGWb0KLibdYnJz0RwFy/mt98KM\nIdByHKQWRm9UjoVJk1ypuQpnj+bqFnxCzCFSU9OUj0/Xe0Wuk+kF2BtMO0w+ZYfV\nHCqEaaIJ1D/iLqi8aBbYs552l9+P0DsFUlTE0D/AvKTQ2PsztFq7wHUTQVmnj4vy\nk1bw7ske+ImLAhUA517JOoXXp2rC8hPMpSx0hPtF0d0CgYBsMerhmMT0/416hJV/\nprs7crOX0e0gF8C7kar/ILj5WULX7k143+4lgluoogrPXbd5fXgOnqdQawow8a/I\njU62Sz6n/qfHLJtQ2sJOK2Vkj5NF2UCcRHrewqJw9nDCS7yYh3c+gUfIBcIRkEJK\n6eRJfrZuaq0YuenUa9AuFwnjPAOBhAACgYBwjDUjp9jaJu46eobNK8CWJL/Noi2f\nXTtFZFgUFRwkr/FXLLsOckQTmYxaWcxP4NwuvMyI25tOueM0RvAIR7J3Afc5pbuC\nx6dIgiOf2gRClQU5OlqhrnMW2BQXlRhBKBNMp5LjM5t46KTBkjh/30//s4Kimrp/\nC2XBGgEuRdgyqQ==\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAB3NzaC1kc3MAAACBAPKhVnFGWb0KLibdYnJz0RwFy/mt98KMIdByHKQWRm9UjoVJk1ypuQpnj+bqFnxCzCFSU9OUj0/Xe0Wuk+kF2BtMO0w+ZYfVHCqEaaIJ1D/iLqi8aBbYs552l9+P0DsFUlTE0D/AvKTQ2PsztFq7wHUTQVmnj4vyk1bw7ske+ImLAAAAFQDnXsk6hdenasLyE8ylLHSE+0XR3QAAAIBsMerhmMT0/416hJV/prs7crOX0e0gF8C7kar/ILj5WULX7k143+4lgluoogrPXbd5fXgOnqdQawow8a/IjU62Sz6n/qfHLJtQ2sJOK2Vkj5NF2UCcRHrewqJw9nDCS7yYh3c+gUfIBcIRkEJK6eRJfrZuaq0YuenUa9AuFwnjPAAAAIBwjDUjp9jaJu46eobNK8CWJL/Noi2fXTtFZFgUFRwkr/FXLLsOckQTmYxaWcxP4NwuvMyI25tOueM0RvAIR7J3Afc5pbuCx6dIgiOf2gRClQU5OlqhrnMW2BQXlRhBKBNMp5LjM5t46KTBkjh/30//s4Kimrp/C2XBGgEuRdgyqQ==",
"private": "-----BEGIN DSA PRIVATE KEY-----\nMIIBugIBAAKBgQDyoVZxRlm9Ci4m3WJyc9EcBcv5rffCjCHQchykFkZvVI6FSZNc\nqbkKZ4/m6hZ8QswhUlPTlI9P13tFrpPpBdgbTDtMPmWH1RwqhGmiCdQ/4i6ovGgW\n2LOedpffj9A7BVJUxNA/wLyk0Nj7M7Rau8B1E0FZp4+L8pNW8O7JHviJiwIVAOde\nyTqF16dqwvITzKUsdIT7RdHdAoGAbDHq4ZjE9P+NeoSVf6a7O3Kzl9HtIBfAu5Gq\n/yC4+VlC1+5NeN/uJYJbqKIKz123eX14Dp6nUGsKMPGvyI1Otks+p/6nxyybUNrC\nTitlZI+TRdlAnER63sKicPZwwku8mId3PoFHyAXCEZBCSunkSX62bmqtGLnp1GvQ\nLhcJ4zwCgYBwjDUjp9jaJu46eobNK8CWJL/Noi2fXTtFZFgUFRwkr/FXLLsOckQT\nmYxaWcxP4NwuvMyI25tOueM0RvAIR7J3Afc5pbuCx6dIgiOf2gRClQU5OlqhrnMW\n2BQXlRhBKBNMp5LjM5t46KTBkjh/30//s4Kimrp/C2XBGgEuRdgyqQIUSNLlRVPv\nMC3Q3P3ajY1DdZvi9z8=\n-----END DSA PRIVATE KEY-----"
}
+23
View File
@@ -0,0 +1,23 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAAFmFlczEyOC1nY21Ab3BlbnNzaC5jb20AAAAGYmNyeXB0AA
AAGAAAABD01pNY1+DTCAHuI6mcjB0YAAAAEAAAAAEAAAGyAAAAB3NzaC1kc3MAAACBAPLA
N0jFExSJiCvw7p2W2v5tqvXIG4YwCglrl2wnGOMBGmfaeIcxZErzW00hOxq+NvDIlK43kJ
iP98Vz0XTHIW6DpkE9DcC5GGA6nDZn9L+BSrBL8NhuBlz2ekgWOTCqnDC7Il/iyUCMi79s
ZPOEg/bMExWJlB5AosJr7v5twVftAAAAFQC5AGsioHKAc2Cd2QwKLUZSmDZAVwAAAIBxYf
EThMIXPQkSer3snKJfDz0uvc1y/6htsjXLk93TAAi3LSD2dGqYs5s0WfzO4RnFso0EovrL
OnIbqU1XApr6CPKAVX2REsXFWWF3VixEHIEF1Q9gIvHdYgAxSxtwYvOPpAwDmaPxWeV5/q
MsMu2RSKkK6f08J0vsESnKU4nmnwAAAIEAxH8NZyntzihIAHnx1Lbo7h1sPi4RhcpKK5pS
UiaKoWxkjseqUsyWENt6DTByIdGhBNrOp9/vw2R5CSUkxuI0TlI8bj3qhq/B3bspx1GWjL
qLfKbeVi4un8CrooRRq2g8+nYLu2EWbF/56pEEzws6DptlDJQi7GdZG8Q0tuyfXxsAAAIA
PDupGK4wMtROtFZqo7vduzkHJuDrE/tAwGqiD2pKMova7WaKM0EUznwcl3gtmhHvFeY+NJ
3Uc9sQcX/9n3y6NAYsC+eZeqe7Sy2GWVyqxOUJHpZqfsKYJidG61TBgKgx+JXAeidYdz4L
4cEapwwocOptbY3ZRFmszekq5xPomnkP9DeSQG6l4eYSv7OpeAHlFj2KCmJMVEZDOl6RyJ
KCqOpfEJIIVoCmna/hQdd9ptLVFmbX/VShgLjvUwfBggJtZNPb5jx+PMy+I0ylywaCIG5K
JQAqust6dzFBx3mBoO4kZPBHlb8XwQ4HYLYph0Ur/lINsHrpLxgmtEw7zzs73Nshl6go2V
uvBtcZ5ywAMk+8CLP5ZgpiGBxlMtFGowp/5zuJxRpc9FgdfxnnVWDyzcQ/YvX9lwzb6cNz
bXeLPsKjOSLPV7G/RFIiuCAOa97ZCM8Ho4FhdNYOGilmjuxV7FJiTc7KP2r+Wh3oxsV7AB
Q6Thj06b2mX3iE4hqLaMKIVE1zs22nMlUtFJv8YY1ZWBihUVlnR9vWgIH7ODoZOwNWBlLd
Qfyfi8w3KgJWj5oVNAM7WniNFQjfNxEbrPklfYg93deVE/LhPghs9I7fsIeHY/p8GtsO/S
amTcjkYi6pUuT8m7IeFYQ8cWvGnbaYz6/9+ni+0aoUL93GKHQw1+mBUVuswVZXBF1WVCf+
LMgZ
-----END OPENSSH PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
ssh-dss AAAAB3NzaC1kc3MAAACBAPLAN0jFExSJiCvw7p2W2v5tqvXIG4YwCglrl2wnGOMBGmfaeIcxZErzW00hOxq+NvDIlK43kJiP98Vz0XTHIW6DpkE9DcC5GGA6nDZn9L+BSrBL8NhuBlz2ekgWOTCqnDC7Il/iyUCMi79sZPOEg/bMExWJlB5AosJr7v5twVftAAAAFQC5AGsioHKAc2Cd2QwKLUZSmDZAVwAAAIBxYfEThMIXPQkSer3snKJfDz0uvc1y/6htsjXLk93TAAi3LSD2dGqYs5s0WfzO4RnFso0EovrLOnIbqU1XApr6CPKAVX2REsXFWWF3VixEHIEF1Q9gIvHdYgAxSxtwYvOPpAwDmaPxWeV5/qMsMu2RSKkK6f08J0vsESnKU4nmnwAAAIEAxH8NZyntzihIAHnx1Lbo7h1sPi4RhcpKK5pSUiaKoWxkjseqUsyWENt6DTByIdGhBNrOp9/vw2R5CSUkxuI0TlI8bj3qhq/B3bspx1GWjLqLfKbeVi4un8CrooRRq2g8+nYLu2EWbF/56pEEzws6DptlDJQi7GdZG8Q0tuyfXxs=
@@ -0,0 +1,7 @@
{
"type": "ssh-dss",
"comment": "",
"public": "-----BEGIN PUBLIC KEY-----\nMIIBtzCCASsGByqGSM44BAEwggEeAoGBAPLAN0jFExSJiCvw7p2W2v5tqvXIG4Yw\nCglrl2wnGOMBGmfaeIcxZErzW00hOxq+NvDIlK43kJiP98Vz0XTHIW6DpkE9DcC5\nGGA6nDZn9L+BSrBL8NhuBlz2ekgWOTCqnDC7Il/iyUCMi79sZPOEg/bMExWJlB5A\nosJr7v5twVftAhUAuQBrIqBygHNgndkMCi1GUpg2QFcCgYBxYfEThMIXPQkSer3s\nnKJfDz0uvc1y/6htsjXLk93TAAi3LSD2dGqYs5s0WfzO4RnFso0EovrLOnIbqU1X\nApr6CPKAVX2REsXFWWF3VixEHIEF1Q9gIvHdYgAxSxtwYvOPpAwDmaPxWeV5/qMs\nMu2RSKkK6f08J0vsESnKU4nmnwOBhQACgYEAxH8NZyntzihIAHnx1Lbo7h1sPi4R\nhcpKK5pSUiaKoWxkjseqUsyWENt6DTByIdGhBNrOp9/vw2R5CSUkxuI0TlI8bj3q\nhq/B3bspx1GWjLqLfKbeVi4un8CrooRRq2g8+nYLu2EWbF/56pEEzws6DptlDJQi\n7GdZG8Q0tuyfXxs=\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAB3NzaC1kc3MAAACBAPLAN0jFExSJiCvw7p2W2v5tqvXIG4YwCglrl2wnGOMBGmfaeIcxZErzW00hOxq+NvDIlK43kJiP98Vz0XTHIW6DpkE9DcC5GGA6nDZn9L+BSrBL8NhuBlz2ekgWOTCqnDC7Il/iyUCMi79sZPOEg/bMExWJlB5AosJr7v5twVftAAAAFQC5AGsioHKAc2Cd2QwKLUZSmDZAVwAAAIBxYfEThMIXPQkSer3snKJfDz0uvc1y/6htsjXLk93TAAi3LSD2dGqYs5s0WfzO4RnFso0EovrLOnIbqU1XApr6CPKAVX2REsXFWWF3VixEHIEF1Q9gIvHdYgAxSxtwYvOPpAwDmaPxWeV5/qMsMu2RSKkK6f08J0vsESnKU4nmnwAAAIEAxH8NZyntzihIAHnx1Lbo7h1sPi4RhcpKK5pSUiaKoWxkjseqUsyWENt6DTByIdGhBNrOp9/vw2R5CSUkxuI0TlI8bj3qhq/B3bspx1GWjLqLfKbeVi4un8CrooRRq2g8+nYLu2EWbF/56pEEzws6DptlDJQi7GdZG8Q0tuyfXxs=",
"private": null
}
@@ -0,0 +1,7 @@
{
"type": "ssh-dss",
"comment": "new openssh format encrypted gcm",
"public": "-----BEGIN PUBLIC KEY-----\nMIIBtzCCASsGByqGSM44BAEwggEeAoGBAPLAN0jFExSJiCvw7p2W2v5tqvXIG4Yw\nCglrl2wnGOMBGmfaeIcxZErzW00hOxq+NvDIlK43kJiP98Vz0XTHIW6DpkE9DcC5\nGGA6nDZn9L+BSrBL8NhuBlz2ekgWOTCqnDC7Il/iyUCMi79sZPOEg/bMExWJlB5A\nosJr7v5twVftAhUAuQBrIqBygHNgndkMCi1GUpg2QFcCgYBxYfEThMIXPQkSer3s\nnKJfDz0uvc1y/6htsjXLk93TAAi3LSD2dGqYs5s0WfzO4RnFso0EovrLOnIbqU1X\nApr6CPKAVX2REsXFWWF3VixEHIEF1Q9gIvHdYgAxSxtwYvOPpAwDmaPxWeV5/qMs\nMu2RSKkK6f08J0vsESnKU4nmnwOBhQACgYEAxH8NZyntzihIAHnx1Lbo7h1sPi4R\nhcpKK5pSUiaKoWxkjseqUsyWENt6DTByIdGhBNrOp9/vw2R5CSUkxuI0TlI8bj3q\nhq/B3bspx1GWjLqLfKbeVi4un8CrooRRq2g8+nYLu2EWbF/56pEEzws6DptlDJQi\n7GdZG8Q0tuyfXxs=\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAB3NzaC1kc3MAAACBAPLAN0jFExSJiCvw7p2W2v5tqvXIG4YwCglrl2wnGOMBGmfaeIcxZErzW00hOxq+NvDIlK43kJiP98Vz0XTHIW6DpkE9DcC5GGA6nDZn9L+BSrBL8NhuBlz2ekgWOTCqnDC7Il/iyUCMi79sZPOEg/bMExWJlB5AosJr7v5twVftAAAAFQC5AGsioHKAc2Cd2QwKLUZSmDZAVwAAAIBxYfEThMIXPQkSer3snKJfDz0uvc1y/6htsjXLk93TAAi3LSD2dGqYs5s0WfzO4RnFso0EovrLOnIbqU1XApr6CPKAVX2REsXFWWF3VixEHIEF1Q9gIvHdYgAxSxtwYvOPpAwDmaPxWeV5/qMsMu2RSKkK6f08J0vsESnKU4nmnwAAAIEAxH8NZyntzihIAHnx1Lbo7h1sPi4RhcpKK5pSUiaKoWxkjseqUsyWENt6DTByIdGhBNrOp9/vw2R5CSUkxuI0TlI8bj3qhq/B3bspx1GWjLqLfKbeVi4un8CrooRRq2g8+nYLu2EWbF/56pEEzws6DptlDJQi7GdZG8Q0tuyfXxs=",
"private": "-----BEGIN DSA PRIVATE KEY-----\nMIIBuwIBAAKBgQDywDdIxRMUiYgr8O6dltr+bar1yBuGMAoJa5dsJxjjARpn2niH\nMWRK81tNITsavjbwyJSuN5CYj/fFc9F0xyFug6ZBPQ3AuRhgOpw2Z/S/gUqwS/DY\nbgZc9npIFjkwqpwwuyJf4slAjIu/bGTzhIP2zBMViZQeQKLCa+7+bcFX7QIVALkA\nayKgcoBzYJ3ZDAotRlKYNkBXAoGAcWHxE4TCFz0JEnq97JyiXw89Lr3Ncv+obbI1\ny5Pd0wAIty0g9nRqmLObNFn8zuEZxbKNBKL6yzpyG6lNVwKa+gjygFV9kRLFxVlh\nd1YsRByBBdUPYCLx3WIAMUsbcGLzj6QMA5mj8Vnlef6jLDLtkUipCun9PCdL7BEp\nylOJ5p8CgYEAxH8NZyntzihIAHnx1Lbo7h1sPi4RhcpKK5pSUiaKoWxkjseqUsyW\nENt6DTByIdGhBNrOp9/vw2R5CSUkxuI0TlI8bj3qhq/B3bspx1GWjLqLfKbeVi4u\nn8CrooRRq2g8+nYLu2EWbF/56pEEzws6DptlDJQi7GdZG8Q0tuyfXxsCFG8ERflm\nOIBFUymTHP8ZeVOgNm/1\n-----END DSA PRIVATE KEY-----"
}
+9
View File
@@ -0,0 +1,9 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTjIb0On/AzYDLFRi+g3fGdAIF72KFG
iZBpP8oKZ8bsncH9ULtVV9517cNcRNuDETQtvLqoCdIn7TipYo8Jv/lKAAAAsA6ULqEOlC
6hAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOMhvQ6f8DNgMsVG
L6Dd8Z0AgXvYoUaJkGk/ygpnxuydwf1Qu1VX3nXtw1xE24MRNC28uqgJ0iftOKlijwm/+U
oAAAAfVd3jjve28r7FhY6Uo//cKIM1rBeWZG16b8bjyVyFswAAABJuZXcgb3BlbnNzaCBm
b3JtYXQBAgMEBQYH
-----END OPENSSH PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOMhvQ6f8DNgMsVGL6Dd8Z0AgXvYoUaJkGk/ygpnxuydwf1Qu1VX3nXtw1xE24MRNC28uqgJ0iftOKlijwm/+Uo= new openssh format
+7
View File
@@ -0,0 +1,7 @@
{
"type": "ecdsa-sha2-nistp256",
"comment": "new openssh format",
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4yG9Dp/wM2AyxUYvoN3xnQCBe9ih\nRomQaT/KCmfG7J3B/VC7VVfede3DXETbgxE0Lby6qAnSJ+04qWKPCb/5Sg==\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOMhvQ6f8DNgMsVGL6Dd8Z0AgXvYoUaJkGk/ygpnxuydwf1Qu1VX3nXtw1xE24MRNC28uqgJ0iftOKlijwm/+Uo=",
"private": null
}
+7
View File
@@ -0,0 +1,7 @@
{
"type": "ecdsa-sha2-nistp256",
"comment": "new openssh format",
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4yG9Dp/wM2AyxUYvoN3xnQCBe9ih\nRomQaT/KCmfG7J3B/VC7VVfede3DXETbgxE0Lby6qAnSJ+04qWKPCb/5Sg==\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOMhvQ6f8DNgMsVGL6Dd8Z0AgXvYoUaJkGk/ygpnxuydwf1Qu1VX3nXtw1xE24MRNC28uqgJ0iftOKlijwm/+Uo=",
"private": "-----BEGIN EC PRIVATE KEY-----\nMHYCAQEEH1Xd4473tvK+xYWOlKP/3CiDNawXlmRtem/G48lchbOgCgYIKoZIzj0D\nAQehRANCAATjIb0On/AzYDLFRi+g3fGdAIF72KFGiZBpP8oKZ8bsncH9ULtVV951\n7cNcRNuDETQtvLqoCdIn7TipYo8Jv/lK\n-----END EC PRIVATE KEY-----"
}
+10
View File
@@ -0,0 +1,10 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABBqNbb13W
CKfO7B1vpwJDwbAAAAEAAAAAEAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlz
dHAyNTYAAABBBJibjz7zvP/EhMZrW/JDdKvYgiEATNUKMfg2NOVxKlf++eTRypLFc1doTp
r+04Ebm1fkyp8RgpFsmvLXLt/dKU0AAADA86k3lHnP6pfD977mwEtKxHOJm44wx8NsdBwN
mNLqxlxUE520nsXjDgpgNU0MF9JDnc1kdhSy8PcdTAAH5+k6bpf3gotPrltPUBMFQdPqst
5kVS7zOgaxv1qZnlyhOqEdNR3Hee09gJByRrAojtcs+sPI7Nba879NPMb5c5K+gKhONHsa
wLAnz66eFQH5iLjd2MwrV4gJe0x6NGCSI2kyzNlxFsoIl7IcHlJHyyuaSlEOFWQJB8cbB4
BVZB+/8yAx
-----END OPENSSH PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJibjz7zvP/EhMZrW/JDdKvYgiEATNUKMfg2NOVxKlf++eTRypLFc1doTpr+04Ebm1fkyp8RgpFsmvLXLt/dKU0=
@@ -0,0 +1,8 @@
{
"type": "ecdsa-sha2-nistp256",
"comment": "",
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEmJuPPvO8/8SExmtb8kN0q9iCIQBM\n1Qox+DY05XEqV/755NHKksVzV2hOmv7TgRubV+TKnxGCkWya8tcu390pTQ==\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJibjz7zvP/EhMZrW/JDdKvYgiEATNUKMfg2NOVxKlf++eTRypLFc1doTpr+04Ebm1fkyp8RgpFsmvLXLt/dKU0=",
"private": null
}
+7
View File
@@ -0,0 +1,7 @@
{
"type": "ecdsa-sha2-nistp256",
"comment": "new openssh format encrypted",
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEmJuPPvO8/8SExmtb8kN0q9iCIQBM\n1Qox+DY05XEqV/755NHKksVzV2hOmv7TgRubV+TKnxGCkWya8tcu390pTQ==\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJibjz7zvP/EhMZrW/JDdKvYgiEATNUKMfg2NOVxKlf++eTRypLFc1doTpr+04Ebm1fkyp8RgpFsmvLXLt/dKU0=",
"private": "-----BEGIN EC PRIVATE KEY-----\nMHgCAQEEIQDG2nALLBBmkBnw1QvdW4ClRfF3Zl3CcRHujsYz9CLvf6AKBggqhkjO\nPQMBB6FEA0IABJibjz7zvP/EhMZrW/JDdKvYgiEATNUKMfg2NOVxKlf++eTRypLF\nc1doTpr+04Ebm1fkyp8RgpFsmvLXLt/dKU0=\n-----END EC PRIVATE KEY-----"
}
+10
View File
@@ -0,0 +1,10 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAAFmFlczEyOC1nY21Ab3BlbnNzaC5jb20AAAAGYmNyeXB0AA
AAGAAAABAHURyWtYwqVbjholNpL6opAAAAEAAAAAEAAABoAAAAE2VjZHNhLXNoYTItbmlz
dHAyNTYAAAAIbmlzdHAyNTYAAABBBM+ppawNxvkdHbOaB3ygsRueTdIKiT+OQkAH/5LpDx
XcD6i5AR8T/vrCsZ9/y+8GxU8gmvg4Uszr6LDfaQBZnsUAAADAFqKM/ylVkJ/ZA40ZROrW
LNgrttf2+lpVkADwXWzhuESFPPzERKlbHVsVtbiiYmPkLnY1s5VM4zXIj7xyO9YNA9KcM5
GHOKUL2/NmDaTyGgc9s3BGu/ibpjSeOd1rtGAB4cw1s9ifbXBQd3qDbqzaEmovs3MGaGHD
c3VagdxhsppjrPjZ+B40Pzs9QkSGutsSJDpH9wVIu4OLr89TquTU3PVACDRU03lPPENVbt
rh2IMJeEQyNINQHtfVwordj8LMOEsBjyQ1aqHNva/iKyTBiw==
-----END OPENSSH PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBM+ppawNxvkdHbOaB3ygsRueTdIKiT+OQkAH/5LpDxXcD6i5AR8T/vrCsZ9/y+8GxU8gmvg4Uszr6LDfaQBZnsU=
@@ -0,0 +1,8 @@
{
"type": "ecdsa-sha2-nistp256",
"comment": "",
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEz6mlrA3G+R0ds5oHfKCxG55N0gqJ\nP45CQAf/kukPFdwPqLkBHxP++sKxn3/L7wbFTyCa+DhSzOvosN9pAFmexQ==\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBM+ppawNxvkdHbOaB3ygsRueTdIKiT+OQkAH/5LpDxXcD6i5AR8T/vrCsZ9/y+8GxU8gmvg4Uszr6LDfaQBZnsU=",
"private": null
}
@@ -0,0 +1,7 @@
{
"type": "ecdsa-sha2-nistp256",
"comment": "new openssh format encrypted gcm",
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEz6mlrA3G+R0ds5oHfKCxG55N0gqJ\nP45CQAf/kukPFdwPqLkBHxP++sKxn3/L7wbFTyCa+DhSzOvosN9pAFmexQ==\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBM+ppawNxvkdHbOaB3ygsRueTdIKiT+OQkAH/5LpDxXcD6i5AR8T/vrCsZ9/y+8GxU8gmvg4Uszr6LDfaQBZnsU=",
"private": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIHQfJ+4ZNcwSBaCR5kwrR6HjUsTF//R1F983RSTR8vbJoAoGCCqGSM49\nAwEHoUQDQgAEz6mlrA3G+R0ds5oHfKCxG55N0gqJP45CQAf/kukPFdwPqLkBHxP+\n+sKxn3/L7wbFTyCa+DhSzOvosN9pAFmexQ==\n-----END EC PRIVATE KEY-----"
}
+7
View File
@@ -0,0 +1,7 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCyOMGts0WaAdug9NeXbGn2Jrt4wwiO64dumxV2a1IgKQAAAJBOfs+eTn7P
ngAAAAtzc2gtZWQyNTUxOQAAACCyOMGts0WaAdug9NeXbGn2Jrt4wwiO64dumxV2a1IgKQ
AAAEBgQKxJoToGE/Xi4UkYR+FXfin4jG8NTcZ13rJ4CDnCfLI4wa2zRZoB26D015dsafYm
u3jDCI7rh26bFXZrUiApAAAAB3Rlc3RpbmcBAgMEBQY=
-----END OPENSSH PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILI4wa2zRZoB26D015dsafYmu3jDCI7rh26bFXZrUiAp testing
@@ -0,0 +1,7 @@
{
"type": "ssh-ed25519",
"comment": "testing",
"public": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAsjjBrbNFmgHboPTXl2xp9ia7eMMIjuuHbpsVdmtSICk=\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAC3NzaC1lZDI1NTE5AAAAILI4wa2zRZoB26D015dsafYmu3jDCI7rh26bFXZrUiAp",
"private": null
}
+7
View File
@@ -0,0 +1,7 @@
{
"type": "ssh-ed25519",
"comment": "testing",
"public": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAsjjBrbNFmgHboPTXl2xp9ia7eMMIjuuHbpsVdmtSICk=\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAC3NzaC1lZDI1NTE5AAAAILI4wa2zRZoB26D015dsafYmu3jDCI7rh26bFXZrUiAp",
"private": "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIGBArEmhOgYT9eLhSRhH4Vd+KfiMbw1NxnXesngIOcJ8\n-----END PRIVATE KEY-----"
}
+27
View File
@@ -0,0 +1,27 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
NhAAAAAwEAAQAAAQEA4q6eZdx7LYh46PcZNcS3CnO7GuYsEJZeTj5LQSgp21IyTelaBPpr
ijnMwKa+pLQt5TEobpKFFNecPdT6oPoOKKMe6oH/pX0BNyAEB9KFZfZgh0v4J4IOiO0KHM
BNkoTFeGrursPkqYRJ0HL4CqYqRdINy1sgDU6jUIOuDD5XZzlpDXb1ftZoCei9OHSWrMKb
zibJc64JFM7tUoK6Vl64YiPgxsNXOJYMTrelVJYebtsNrJFmh3XXQABDVutWMYb8I6IrNs
8zjxsf6c6N2tKXkk9G4EDKKip4g0bzDmD/fREPQ9vLi59N+ZsyjWCKKE3PZSvwtoyLQN38
KvTx3wjNQwAAA8hLhVBxS4VQcQAAAAdzc2gtcnNhAAABAQDirp5l3HstiHjo9xk1xLcKc7
sa5iwQll5OPktBKCnbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+l
fQE3IAQH0oVl9mCHS/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg6
4MPldnOWkNdvV+1mgJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u
2w2skWaHdddAAENW61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28
uLn035mzKNYIooTc9lK/C2jItA3fwq9PHfCM1DAAAAAwEAAQAAAQAmShSbZBiyYkD6KPLr
MCUy8MWED6kVzDB1yvPvN5eKYmH44xe/i4UqvgSl7gR50a2G7zzDIKC2Go1brGQBWPuXRa
ZtOjQygeD4rMHBiH/b7zfy4pQyKDfITTHOFXWE8ERiyL00bAZt09icCy92rQaq8IY/+U56
sPPJH9UAYG9nEev8opFjAWToFDu0U2+dC+lbqLlXDqDRo75NlnDFmgUoja3y2eFr9A0Cc+
hjecrdxyJFsCJfEfaLWtBnZb886gqzzvfbHImSQtBAKERcSxuki7uxMoP67g3iQOXa65uz
8kFWRNmbQTGQttakoUaybh1t9eLpBqvVON/4Kg0THShRAAAAgFBTz2ajBK/R/crOSL9VK1
f7oQv2iJTRVfnUs0r+qPGgf/a/5UwkGRj0KfEWBp3qYD+keShnPr6PDPFrm8UmIdUX8AY7
3tWT2K/JQVlzJNuINsw+DNjn4M17Z25q0LPmReRWL0nRc2w6W/hmQ/Jmqz6w8Qc4+xpeqS
/HG5feliVnAAAAgQD90a+5Ky3o/2YtueqRf/3dKoiMgGB7JAOzye4dDKGABSlWuQ4N4xEI
CW5MSTp7i/uobTF/tyFO3tTSyb5b2Xwbn/kLO0vgvFCdUGR2BQfN3mcT92T0Gn3JDF3Wym
i2mgU6qnPf+eu+RKZQ9IiyNGny61ROUQa0R0z0pgiAfA89xwAAAIEA5KE9i6hHmigJwfD7
/AGI4ujyWIVpNyrTdXG3HAPhsdoFuG5ggHggrPuuBF9wNcosrhL20VNOQGHg15gWZIVudu
0qxky4ivQs67Sk9XUjuvTnf+VubM51rIsmh4atKJFSSZo78DEcTRt8aXLrSNvGQ4WPRweM
2Z0YGfMMDM9KJKUAAAASbmV3IG9wZW5zc2ggZm9ybWF0AQ==
-----END OPENSSH PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDirp5l3HstiHjo9xk1xLcKc7sa5iwQll5OPktBKCnbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+lfQE3IAQH0oVl9mCHS/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg64MPldnOWkNdvV+1mgJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u2w2skWaHdddAAENW61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28uLn035mzKNYIooTc9lK/C2jItA3fwq9PHfCM1D new openssh format
+7
View File
@@ -0,0 +1,7 @@
{
"type": "ssh-rsa",
"comment": "new openssh format",
"public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4q6eZdx7LYh46PcZNcS3\nCnO7GuYsEJZeTj5LQSgp21IyTelaBPprijnMwKa+pLQt5TEobpKFFNecPdT6oPoO\nKKMe6oH/pX0BNyAEB9KFZfZgh0v4J4IOiO0KHMBNkoTFeGrursPkqYRJ0HL4CqYq\nRdINy1sgDU6jUIOuDD5XZzlpDXb1ftZoCei9OHSWrMKbzibJc64JFM7tUoK6Vl64\nYiPgxsNXOJYMTrelVJYebtsNrJFmh3XXQABDVutWMYb8I6IrNs8zjxsf6c6N2tKX\nkk9G4EDKKip4g0bzDmD/fREPQ9vLi59N+ZsyjWCKKE3PZSvwtoyLQN38KvTx3wjN\nQwIDAQAB\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDirp5l3HstiHjo9xk1xLcKc7sa5iwQll5OPktBKCnbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+lfQE3IAQH0oVl9mCHS/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg64MPldnOWkNdvV+1mgJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u2w2skWaHdddAAENW61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28uLn035mzKNYIooTc9lK/C2jItA3fwq9PHfCM1D",
"private": null
}
+7
View File
@@ -0,0 +1,7 @@
{
"type": "ssh-rsa",
"comment": "new openssh format",
"public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4q6eZdx7LYh46PcZNcS3\nCnO7GuYsEJZeTj5LQSgp21IyTelaBPprijnMwKa+pLQt5TEobpKFFNecPdT6oPoO\nKKMe6oH/pX0BNyAEB9KFZfZgh0v4J4IOiO0KHMBNkoTFeGrursPkqYRJ0HL4CqYq\nRdINy1sgDU6jUIOuDD5XZzlpDXb1ftZoCei9OHSWrMKbzibJc64JFM7tUoK6Vl64\nYiPgxsNXOJYMTrelVJYebtsNrJFmh3XXQABDVutWMYb8I6IrNs8zjxsf6c6N2tKX\nkk9G4EDKKip4g0bzDmD/fREPQ9vLi59N+ZsyjWCKKE3PZSvwtoyLQN38KvTx3wjN\nQwIDAQAB\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDirp5l3HstiHjo9xk1xLcKc7sa5iwQll5OPktBKCnbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+lfQE3IAQH0oVl9mCHS/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg64MPldnOWkNdvV+1mgJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u2w2skWaHdddAAENW61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28uLn035mzKNYIooTc9lK/C2jItA3fwq9PHfCM1D",
"private": "-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEA4q6eZdx7LYh46PcZNcS3CnO7GuYsEJZeTj5LQSgp21IyTela\nBPprijnMwKa+pLQt5TEobpKFFNecPdT6oPoOKKMe6oH/pX0BNyAEB9KFZfZgh0v4\nJ4IOiO0KHMBNkoTFeGrursPkqYRJ0HL4CqYqRdINy1sgDU6jUIOuDD5XZzlpDXb1\nftZoCei9OHSWrMKbzibJc64JFM7tUoK6Vl64YiPgxsNXOJYMTrelVJYebtsNrJFm\nh3XXQABDVutWMYb8I6IrNs8zjxsf6c6N2tKXkk9G4EDKKip4g0bzDmD/fREPQ9vL\ni59N+ZsyjWCKKE3PZSvwtoyLQN38KvTx3wjNQwIDAQABAoIBACZKFJtkGLJiQPoo\n8uswJTLwxYQPqRXMMHXK8+83l4piYfjjF7+LhSq+BKXuBHnRrYbvPMMgoLYajVus\nZAFY+5dFpm06NDKB4PiswcGIf9vvN/LilDIoN8hNMc4VdYTwRGLIvTRsBm3T2JwL\nL3atBqrwhj/5Tnqw88kf1QBgb2cR6/yikWMBZOgUO7RTb50L6VuouVcOoNGjvk2W\ncMWaBSiNrfLZ4Wv0DQJz6GN5yt3HIkWwIl8R9ota0GdlvzzqCrPO99sciZJC0EAo\nRFxLG6SLu7Eyg/ruDeJA5drrm7PyQVZE2ZtBMZC21qShRrJuHW314ukGq9U43/gq\nDRMdKFECgYEA/dGvuSst6P9mLbnqkX/93SqIjIBgeyQDs8nuHQyhgAUpVrkODeMR\nCAluTEk6e4v7qG0xf7chTt7U0sm+W9l8G5/5CztL4LxQnVBkdgUHzd5nE/dk9Bp9\nyQxd1spotpoFOqpz3/nrvkSmUPSIsjRp8utUTlEGtEdM9KYIgHwPPccCgYEA5KE9\ni6hHmigJwfD7/AGI4ujyWIVpNyrTdXG3HAPhsdoFuG5ggHggrPuuBF9wNcosrhL2\n0VNOQGHg15gWZIVudu0qxky4ivQs67Sk9XUjuvTnf+VubM51rIsmh4atKJFSSZo7\n8DEcTRt8aXLrSNvGQ4WPRweM2Z0YGfMMDM9KJKUCgYB7Yh0b1EOjCdQv0jqWtDNB\n+dUbB6Te92jdUwHvGR7AzsGDqL2OPp0e3QbDCq3lNO0GuN3hCbKlVmj6dpuUpqpP\n+3ni3dZKzwAZGOVdAaEDkGNnL1Hh36bZvqs3KHmymjiEhiuB60mP2mtG2zg/+H6w\nWXlIANdTd32PR87GNohqLQKBgA36ic/LJy2Wuxn/iPicg2kUQxUEey1jUfCBVmfB\nGQCNywG+xem07pKFBNvBlhPD27187VhZFpS7J0snQl89BUcCMzZSpIniagizT86u\nLdQVez4HohvG98zn6SAqLNYpJHXZl0aVShywzIeJ/jbDMTkZpmv6WzNG9p1HjfoO\nhoL9AoGAUFPPZqMEr9H9ys5Iv1UrV/uhC/aIlNFV+dSzSv6o8aB/9r/lTCQZGPQp\n8RYGnepgP6R5KGc+vo8M8WubxSYh1RfwBjve1ZPYr8lBWXMk24g2zD4M2OfgzXtn\nbmrQs+ZF5FYvSdFzbDpb+GZD8marPrDxBzj7Gl6pL8cbl96WJWc=\n-----END RSA PRIVATE KEY-----"
}
+28
View File
@@ -0,0 +1,28 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABAS8H9Cyk
rueA/Ue6tOb1MOAAAAEAAAAAEAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC8hCiCPnRs
0ucZeyn3pNYKN63dVoxbMB4Yzjs7gvo7XKDby/6GXoU/CFQ/Q9zXRxRZmFglMYh2pOD8iW
dwpLBdd+GmHb4a6xxKtoPpz1+yCPYvi6nXzKPO3B9Wbg8dtTpV23l8MZDxSRUQ9HIkYHQO
oOjJx/AaMdZyHZP+eYK7UqmX1+dtCzr5vvLyEABxrsoFxH/oW/iKO6cDmTxoMyFl9DfUhD
TS7cL1OVBulSBav3aJPxjsCEIs6OE94wLJfFtZAPe4GqWWcC7uG1uUL5Muy2N+SfXHOHLa
I5n1vozt7lIO5TqvykcqTxipKblMW4Y7Iwlhh0YKJxzH3KJ+Qkn7AAAD4GeinUMcN5H0RP
KnXzIsYGq4rG+pEYNL0WyXCOFnyHzr6cASFYa/ViRVRN5H2dDoc0i2tcQStvDt2AfBxP97
xbTEmRhLkKW7Sxif+bRRpNt2sO1y7ThufOZ8ZSJdbUYf9nc++k5GMZZUTtkFGhFIyhdyl+
ZReuQFrc1Fv0/JV0K72uLSMSSMvunFjnGchch98Z1t0jEuiym8AIAwFtlvRpbOOySJhHun
fClEOahNvgzkgpqvviged7Gl9Kh3Fpp57ke1087WUF4hdgG2wuLqRq3Jq2kNvTKVi6+PMv
Kz5cLl6beqAJpbkJCpujzrmffo5NHh94R/v8DbAWCyrkjB6NHjOPIVnKaDmXixkcJ489W3
PQF0kZ9kLrNU2yP1hBLjikr1zollw6xXC5eEpUsIrNcAHrofTMCMsGKuZhlEgTNe0cEATp
ycxi4gHdA6kNSDnMPwOv9rLDZDkgqCqIzxjZCWabqRHwiyoN3CrdDsJNrk8jSqF5epuzXA
EjrPUvu+sgFHIWDJOij+HQCvCgmdO/W7NkL/xCEx6QagjoJhapGICnq6CXPO5vBQeK7AMV
KWUPB1jdxxlHdrSUYU9v11j0SPUM51AMpWA89GZmuQbe/tK14W35VjtL9aGKsz9Ubio029
O23HJXMxM9Dd6EYXAR9xMLFDTcLT03kjRlL/4XFS4fJqbTGDtuQNqRO3QK/myVAYjgnXwz
X1s77WeIK3sOMwTIXaHReUiQ1Cw+WmkXOhefePT+HrkyDlJk3ikgPUy2s5QW5/d6Lmolwb
mcS9JUfaai0ysP3v1bew8go/IHiUD/X9AkjkKM2kfS1NcPSi18r2721e6RqZiIHxSoyKvq
yUmwiS1kUklSuhlTORBvbclbv4HTwp1iJfu/6zsMqVJc2E8H6WUw3kTeh9fhDMpTY5NArF
KD2aRIYHFvOKav+0vSbQ/KqmKeiTvyZaV7q6giRxVLxBddl4+ucD+FybPJZSebRQ+0QT1j
aUDSpp541zW0rX7sCiZ6sFUybCPVDM1uA5gTAP015OD/FS342gi+Y04K0jBSjlApuy6BQx
sMEQbR3weMmnodbhCtbcgDZDagSFNPlDud0GJl9IWV4hO/K1f9a+Ox3G27Jq4YC2PFgTDb
aYib4xAXPUHJpoWsstSjpMnfgKcS3AGRdJ/jxlKRWV/NXFf4DYIwpzITqFMF+4VqXCa2AS
JWOcSxOK92UqCcZEs8RED3x9dF9E2yBBwHeuwDvH3c9x/nsM/cjDY+EE9VcEUOxF6qMOhO
CiRtEihEAYM46XeFzcSOQrwWPcKu3WTv3IpnzTaofBxV065CUn
-----END OPENSSH PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8hCiCPnRs0ucZeyn3pNYKN63dVoxbMB4Yzjs7gvo7XKDby/6GXoU/CFQ/Q9zXRxRZmFglMYh2pOD8iWdwpLBdd+GmHb4a6xxKtoPpz1+yCPYvi6nXzKPO3B9Wbg8dtTpV23l8MZDxSRUQ9HIkYHQOoOjJx/AaMdZyHZP+eYK7UqmX1+dtCzr5vvLyEABxrsoFxH/oW/iKO6cDmTxoMyFl9DfUhDTS7cL1OVBulSBav3aJPxjsCEIs6OE94wLJfFtZAPe4GqWWcC7uG1uUL5Muy2N+SfXHOHLaI5n1vozt7lIO5TqvykcqTxipKblMW4Y7Iwlhh0YKJxzH3KJ+Qkn7
@@ -0,0 +1,8 @@
{
"type": "ssh-rsa",
"comment": "",
"public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvIQogj50bNLnGXsp96TW\nCjet3VaMWzAeGM47O4L6O1yg28v+hl6FPwhUP0Pc10cUWZhYJTGIdqTg/IlncKSw\nXXfhph2+GuscSraD6c9fsgj2L4up18yjztwfVm4PHbU6Vdt5fDGQ8UkVEPRyJGB0\nDqDoycfwGjHWch2T/nmCu1Kpl9fnbQs6+b7y8hAAca7KBcR/6Fv4ijunA5k8aDMh\nZfQ31IQ00u3C9TlQbpUgWr92iT8Y7AhCLOjhPeMCyXxbWQD3uBqllnAu7htblC+T\nLstjfkn1xzhy2iOZ9b6M7e5SDuU6r8pHKk8YqSm5TFuGOyMJYYdGCiccx9yifkJJ\n+wIDAQAB\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQC8hCiCPnRs0ucZeyn3pNYKN63dVoxbMB4Yzjs7gvo7XKDby/6GXoU/CFQ/Q9zXRxRZmFglMYh2pOD8iWdwpLBdd+GmHb4a6xxKtoPpz1+yCPYvi6nXzKPO3B9Wbg8dtTpV23l8MZDxSRUQ9HIkYHQOoOjJx/AaMdZyHZP+eYK7UqmX1+dtCzr5vvLyEABxrsoFxH/oW/iKO6cDmTxoMyFl9DfUhDTS7cL1OVBulSBav3aJPxjsCEIs6OE94wLJfFtZAPe4GqWWcC7uG1uUL5Muy2N+SfXHOHLaI5n1vozt7lIO5TqvykcqTxipKblMW4Y7Iwlhh0YKJxzH3KJ+Qkn7",
"private": null
}
+7
View File
@@ -0,0 +1,7 @@
{
"type": "ssh-rsa",
"comment": "new openssh format encrypted",
"public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvIQogj50bNLnGXsp96TW\nCjet3VaMWzAeGM47O4L6O1yg28v+hl6FPwhUP0Pc10cUWZhYJTGIdqTg/IlncKSw\nXXfhph2+GuscSraD6c9fsgj2L4up18yjztwfVm4PHbU6Vdt5fDGQ8UkVEPRyJGB0\nDqDoycfwGjHWch2T/nmCu1Kpl9fnbQs6+b7y8hAAca7KBcR/6Fv4ijunA5k8aDMh\nZfQ31IQ00u3C9TlQbpUgWr92iT8Y7AhCLOjhPeMCyXxbWQD3uBqllnAu7htblC+T\nLstjfkn1xzhy2iOZ9b6M7e5SDuU6r8pHKk8YqSm5TFuGOyMJYYdGCiccx9yifkJJ\n+wIDAQAB\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQC8hCiCPnRs0ucZeyn3pNYKN63dVoxbMB4Yzjs7gvo7XKDby/6GXoU/CFQ/Q9zXRxRZmFglMYh2pOD8iWdwpLBdd+GmHb4a6xxKtoPpz1+yCPYvi6nXzKPO3B9Wbg8dtTpV23l8MZDxSRUQ9HIkYHQOoOjJx/AaMdZyHZP+eYK7UqmX1+dtCzr5vvLyEABxrsoFxH/oW/iKO6cDmTxoMyFl9DfUhDTS7cL1OVBulSBav3aJPxjsCEIs6OE94wLJfFtZAPe4GqWWcC7uG1uUL5Muy2N+SfXHOHLaI5n1vozt7lIO5TqvykcqTxipKblMW4Y7Iwlhh0YKJxzH3KJ+Qkn7",
"private": "-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEAvIQogj50bNLnGXsp96TWCjet3VaMWzAeGM47O4L6O1yg28v+\nhl6FPwhUP0Pc10cUWZhYJTGIdqTg/IlncKSwXXfhph2+GuscSraD6c9fsgj2L4up\n18yjztwfVm4PHbU6Vdt5fDGQ8UkVEPRyJGB0DqDoycfwGjHWch2T/nmCu1Kpl9fn\nbQs6+b7y8hAAca7KBcR/6Fv4ijunA5k8aDMhZfQ31IQ00u3C9TlQbpUgWr92iT8Y\n7AhCLOjhPeMCyXxbWQD3uBqllnAu7htblC+TLstjfkn1xzhy2iOZ9b6M7e5SDuU6\nr8pHKk8YqSm5TFuGOyMJYYdGCiccx9yifkJJ+wIDAQABAoIBAD1UXX1p5iSVRHvk\nttWLOdsfHCA7DPSJpfD5/wkwZkozq112czqxu3WzNv1SDaG3zSYMyvhmsfevUka2\nSQG7gmkWHEIXwQYu4Qhpcmb5gS+BfN4g+MNtHwmoUUWkDqTilbTi7xX5ZicpWIIo\nlI3DF16++JzUwAc1mYeMmd4bF+3quh93xW7hhrcQ31+D9kzqt6nLG1d9+IVpMbhD\nnNB9zapkZHwnz6YYhb5waMOHr6U902TyGgKyjq3Z/PkMJ0zKg01roUtQs9oQOIZF\nvueF2hwyzHqeIgpqhWJl9HMpfdym6Lh2lwguK3KYwNIMFQg+gNBWruYlH6SGfylq\n0wB5xIECgYEA8FdyEDd4TbVBKIXzzmY6zYmN/Q9uiz0IjbeYYzuRxZ4a7stE/t8n\nM5UxxkqeD8rtRAQJyFDGPAhFeeOpIfzEVPG+5s72pI69+9aE/gCGA91+sOSnLoiJ\nPW1I7SouZfCeaaRQxSSIMjsCea2s6yraujGZJyPEWSkG5TijY8+vzDsCgYEAyMxX\nCYvqlRTaT5lAkRTFLqf0/NSpRoCnG7qSPUyJjxJsVfYFLv1FZCyyrA+SaIyufjoT\nKutKE31r7wre5bkjRRenIcTkR/tdNRdkWsB/ysZ9Cp43FIPTXS5gxTQxOaJyRGvJ\n9MW0m8N1pMvPIsagzoxxvzgU9ZOejs2NQ69qXUECgYBq7DxOgp7+0zhdsto4ZLqc\nXinQ/2CKiWiYw6kD3KiJZkFNIxla2iQyiplOQjv3gqvzqmg/uc+3PWbLR0EjYbRm\npfXr8P9BTk+vDky0Q79bUNrgD5lg1lVYApqDCFUD/Pw8u2FDk3EUB7SeNWnMZZBR\nbWdZRkw/7kSnDX+DFA59qQKBgG9v0AHxT4/LEdlJEOczYrcg6TqDfyosbhFaepxg\nZJstO0h9j6TjVGZi1AnfXn59TL2q10ZjbCni2krAerF9DNDkbpG0Joi4PKMhR0WC\nPam4fF6vLZxKCLxW58epzoPQ3p+QPnWEX1ZupFR/84W2PDpFAT+BDUi40y8nbnWY\n3WvBAoGADjh0hEkq3sy6oWt0m1NjGU1yxKV+geg48BFnu2LVSFv1rw1V7X8XFEYl\nP1B3sEpOOpPGuoz+r2E9PrsdMuYNOmVlRFRpe7pm7zyhzdFYBvLE2btJqv1PmxFu\ncEkrXJS/ETxkKdMaoUbYHcKiTIMi2pDrdJtg6oHcipm0yTBZkKs=\n-----END RSA PRIVATE KEY-----"
}
+29
View File
@@ -0,0 +1,29 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAAFmFlczEyOC1nY21Ab3BlbnNzaC5jb20AAAAGYmNyeXB0AA
AAGAAAABBJL2YVn88iqv/H9bFiyW2PAAAAEAAAAAEAAAEXAAAAB3NzaC1yc2EAAAADAQAB
AAABAQDMemjkha1c+2s58qzx4968svvvpbxt6EiLlyRHuqXCouTdBZeXGtVRlxpkqnnOE0
ETMSQSqm1d5k1EMa7VVcTeXFQaBIc2XF0S1uIoEvNV0JXpDjiIdPmjUFuUf9oGGLKKQQMf
zpymqoiHYQNhuarYd1mSb0+a+UwKxAxGeCPd95o/JfWjKO0JTr3nnEj1eTjtu0pofmchab
9HC9YbJ3JsvbdRq7Z2ZHp8uu16SflPpP2A9l+F4HN+gPOLcGxbVkVZHsLI07OpkWdxMPBU
rzPF9OnCntRWoBhQ4LFHYHllTtd+/E90QXXhe1pxj8FktJiaitiz09GU5h4IWi3isNr/AA
AD4Ktd9gUs9KHBmWTVFnDofcB6P1dZJsYHAapQgNXZtx5SjwgfBpP5aBLtSjN1iHFE+3XC
Cofc9UJ8fbytwT7LCEQIzo3KJaOhVzgJN+lrjtFouWsw0Y1q2JONHvvNJ5A9nGjIGbp3du
4TAMSgVAvxZBEYez4ajhb2NL7TE56AjOxW4n/M2ZDJLCo11F3ON3Eq6MirHZMgGKo/lbOc
SaBld7tzqknye+1fKVlnCLyu+v0KCbATBypRsMeX1+E/D8L5cMIgRSe97swqiWeG9yBhQi
xahbWDpmU34nz1cxc9H7KnL1rbbOxrr4OEdMOHNBQjbLlpJpnSJ3XvEGP74zjfd5zMocgx
rnqreMmY+eDEObkw33+XD5ROYJT+SW/zI+r3SeIjS3UPh0ucU5nipBvXfkUezek9i/FN1X
CY7xJnAZGGKU0JSqiVW3JWXp18v8lmo3ACvXeotJfUGkwvJOeO2N4Qb7RTIzivLV5Q5Plf
zHWqHE57UqDL/Ya7SrX1FaqqhOHOlS1mqPQ+/VdsOSP5fJcXN+oKoL7jPr2WlmtFjo8PKc
rpgKC3DhUzvRXnNYotG7trbPOGJbBRgoxTQ06rlChoaBp7kUKqNNBxXhFQCeN0sCb90fHV
c+X3Yy8oUsAIxxmCymuVV8gRzLD6OdqQRBthEUQktNJLhv4mSufwSfsLDluEc7YEOrsJhx
jk57TmkFFyLj++IAKi80FnSkRfSBQF3dTSrBZ4BIHWnek8V6goxhy6lRMaFoTow2foknvr
VHgiNGvimOM3ESYVcOwt3YQqbUG/7b4jRlY3nNBJcsbxGe54B8zaoLt5pQNRxUuHc3fR4R
haWHR6IWsfey7jAlRzrJAVVEEj4d6yvJ4bLqWGmoim5QlrePRuRFyV4FNb8N6hJ9gvWY9f
HUT9TwxArDIMzu4T1khwRoFU45XN0U6xHEPcT/pZ2C5jJSSQ5W/SyBudexjMMPRKf2EIeD
gjv8vIhdtkmxHv7bapaaYeYX5gtKYl+McRollDxVC8Kr48RmOVJnK4aFBQ99Wu7SXDbwas
vcvVHI+zUiRGjU01/CU/Tf4GTodAlmZIuqKmBTX/KvVj6ZiK0BsZuEl9qom+l4rlazaahY
FdL5M4u0qt7rVirWJWgWzmPXZ+MCK0Fs70ORvqRGxVMilhQcWsng3ZXnHaYiBRhk31KqF+
BEPEh79OknD0okKed2YYfg8vdUR+noENybrsIleP1aKBBmQCNbKU04N/9Su+wxX8YfGhYU
kPST35Wg45zER9gZGsREnON4sQTng9LHB5CrJCo/MowcZG/ycqL1mxemApZ9nYUrjA8HJi
zDwRHHUtkkLNG8Cmyg==
-----END OPENSSH PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMemjkha1c+2s58qzx4968svvvpbxt6EiLlyRHuqXCouTdBZeXGtVRlxpkqnnOE0ETMSQSqm1d5k1EMa7VVcTeXFQaBIc2XF0S1uIoEvNV0JXpDjiIdPmjUFuUf9oGGLKKQQMfzpymqoiHYQNhuarYd1mSb0+a+UwKxAxGeCPd95o/JfWjKO0JTr3nnEj1eTjtu0pofmchab9HC9YbJ3JsvbdRq7Z2ZHp8uu16SflPpP2A9l+F4HN+gPOLcGxbVkVZHsLI07OpkWdxMPBUrzPF9OnCntRWoBhQ4LFHYHllTtd+/E90QXXhe1pxj8FktJiaitiz09GU5h4IWi3isNr/
@@ -0,0 +1,8 @@
{
"type": "ssh-rsa",
"comment": "",
"public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzHpo5IWtXPtrOfKs8ePe\nvLL776W8behIi5ckR7qlwqLk3QWXlxrVUZcaZKp5zhNBEzEkEqptXeZNRDGu1VXE\n3lxUGgSHNlxdEtbiKBLzVdCV6Q44iHT5o1BblH/aBhiyikEDH86cpqqIh2EDYbmq\n2HdZkm9PmvlMCsQMRngj3feaPyX1oyjtCU6955xI9Xk47btKaH5nIWm/RwvWGydy\nbL23Uau2dmR6fLrtekn5T6T9gPZfheBzfoDzi3BsW1ZFWR7CyNOzqZFncTDwVK8z\nxfTpwp7UVqAYUOCxR2B5ZU7XfvxPdEF14XtacY/BZLSYmorYs9PRlOYeCFot4rDa\n/wIDAQAB\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDMemjkha1c+2s58qzx4968svvvpbxt6EiLlyRHuqXCouTdBZeXGtVRlxpkqnnOE0ETMSQSqm1d5k1EMa7VVcTeXFQaBIc2XF0S1uIoEvNV0JXpDjiIdPmjUFuUf9oGGLKKQQMfzpymqoiHYQNhuarYd1mSb0+a+UwKxAxGeCPd95o/JfWjKO0JTr3nnEj1eTjtu0pofmchab9HC9YbJ3JsvbdRq7Z2ZHp8uu16SflPpP2A9l+F4HN+gPOLcGxbVkVZHsLI07OpkWdxMPBUrzPF9OnCntRWoBhQ4LFHYHllTtd+/E90QXXhe1pxj8FktJiaitiz09GU5h4IWi3isNr/",
"private": null
}
@@ -0,0 +1,7 @@
{
"type": "ssh-rsa",
"comment": "new openssh format encrypted gcm",
"public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzHpo5IWtXPtrOfKs8ePe\nvLL776W8behIi5ckR7qlwqLk3QWXlxrVUZcaZKp5zhNBEzEkEqptXeZNRDGu1VXE\n3lxUGgSHNlxdEtbiKBLzVdCV6Q44iHT5o1BblH/aBhiyikEDH86cpqqIh2EDYbmq\n2HdZkm9PmvlMCsQMRngj3feaPyX1oyjtCU6955xI9Xk47btKaH5nIWm/RwvWGydy\nbL23Uau2dmR6fLrtekn5T6T9gPZfheBzfoDzi3BsW1ZFWR7CyNOzqZFncTDwVK8z\nxfTpwp7UVqAYUOCxR2B5ZU7XfvxPdEF14XtacY/BZLSYmorYs9PRlOYeCFot4rDa\n/wIDAQAB\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDMemjkha1c+2s58qzx4968svvvpbxt6EiLlyRHuqXCouTdBZeXGtVRlxpkqnnOE0ETMSQSqm1d5k1EMa7VVcTeXFQaBIc2XF0S1uIoEvNV0JXpDjiIdPmjUFuUf9oGGLKKQQMfzpymqoiHYQNhuarYd1mSb0+a+UwKxAxGeCPd95o/JfWjKO0JTr3nnEj1eTjtu0pofmchab9HC9YbJ3JsvbdRq7Z2ZHp8uu16SflPpP2A9l+F4HN+gPOLcGxbVkVZHsLI07OpkWdxMPBUrzPF9OnCntRWoBhQ4LFHYHllTtd+/E90QXXhe1pxj8FktJiaitiz09GU5h4IWi3isNr/",
"private": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAzHpo5IWtXPtrOfKs8ePevLL776W8behIi5ckR7qlwqLk3QWX\nlxrVUZcaZKp5zhNBEzEkEqptXeZNRDGu1VXE3lxUGgSHNlxdEtbiKBLzVdCV6Q44\niHT5o1BblH/aBhiyikEDH86cpqqIh2EDYbmq2HdZkm9PmvlMCsQMRngj3feaPyX1\noyjtCU6955xI9Xk47btKaH5nIWm/RwvWGydybL23Uau2dmR6fLrtekn5T6T9gPZf\nheBzfoDzi3BsW1ZFWR7CyNOzqZFncTDwVK8zxfTpwp7UVqAYUOCxR2B5ZU7XfvxP\ndEF14XtacY/BZLSYmorYs9PRlOYeCFot4rDa/wIDAQABAoIBAQCCb7uluxhh7gfy\niTmFfETDvrEzqFfRDJHqadm83/WJeXvg+gY/X+CgEXHGsXDN4j5qzbgjKBBoC9dS\nHxdWA0Z4ShFkH2tZZAYDVIwj4CLVpR9b8bRiZ6wvX71rtzsPFIYf52Tkz1nif3pk\nUaBkoJm5SDkdTmBLjafSXkkuUskeeAV7gx+fzWqSpcKmhTqjnQfdlmD8OSIq4jjD\nagiHmmfBhZ4NOvF/E9UBydqFV8GNyfSFC6kC2LYmiQD1hvqNhMdYVjh99V1L3ZPq\nHMSQVAOv5WgpLTLKY8MFNBbqqp0eKhatRNA8q9O23jADDp3fubKV0aUQSrRZz0y9\nPmmEJnTRAoGBAPZoL+p+AbI5yTg01LdsaQL2f3Ieb3CGudesmjAVnI3QEoC6gxGX\n4cbmBSCY+vBzh2RJNJcS+Rq6VmJZA930Tb0npHiQYOohB7BFOCbBJ2L18g/JdNpi\nVb3wqFs9NG1GFOOV6iGtV/6t4CRTKtAbd695YZAJ5S6DDvMrH9pTnAKrAoGBANRw\nVuLfBTFhSKvFz+0W0yy6Sn0koXjpp1ifC0BWLwHiA/IZjAY7qmsNQZxWdleWLP28\nRNaac3vMJO/HFD4IyL59Zli+kREGKazvZM1dvOs0mgdVMTPMsT57wcJr5OSxqCvJ\nD3NkcgFuA1e3jVC5p/wUJCi/lhyFPx3z1C5vRqj9AoGBANeyYmd5wFBcp1ktXhvm\nqZIvZ2blX5X4ScyTSjHXaUD2qIvJORz4gGqVRl2/rMM5zoYqUwAAWtFb1mynEWyF\nBFwVzLLBaCTrnwhdv4alRK4rL6dEKadVt0ra1PVxgWg6leSXgenTDRli6bfCmdKs\niLuxnIbzMozhqv+Qe4Sp9gKbAoGBALWBThsEpXEtR2PL3P0atU7P0/jcJUIjkCF9\nsaVEfWFEdE6TWTmyHMbeSqKClRX8b3BTPRWGXQj2wNBE7Zya8LkgdyN3noZHF7Bz\n0VJNtq3XAYsmVKWHTCCwqDmu6aAj0iWm4ZabyXRDRIPbhdfk6AvOQZ63IlA34Fd9\nDlqmJF8ZAoGAIJzfMDT2LvlMOHqpKgelS4ZTHEmqqJZM5rXdsZwYqcyekjz25COE\nTJwme3xIt3kSZEcOauGHCgUVeBcE6GwZbQ1WoNIvazhnUXeErOeoxQ+ZqdfC8iyT\nUn/P27yx/FcwDdubQhbgxZ5M+pu+0OQ1WPu02LQZQrX7x4a6isYtTDo=\n-----END RSA PRIVATE KEY-----"
}
+12
View File
@@ -0,0 +1,12 @@
-----BEGIN DSA PRIVATE KEY-----
MIIBvQIBAAKBgQDs+n9ZKhwYNr1V2uGn0C/2MSTM4KB4puy4jR5ubRTT1yq5SbzK
RQlCjfplDN//Eqa6aiFmvGKA3RKUtPtBmD96EHW1mvr7O+Pc8z8L/4zg9tkVQR6V
WBKgBhVwZHDzzs5+Ag2j54BZfcaGMcNGhTE9DcZYeI/t6FhOxgpID3EA/QIVAMyI
czBU74xB48IMoamlEhc5Lh+3AoGBAMuy2h9K9+oQIPcTcsD/mtmhOYlw2ZPCJV2b
WFeZ3QxAujenBzEp0oqht8tdj+BE7Er+CWT2Ab/A92MrjYUaGaPjdF5+K6CSPMUX
rK8nBabSBJ+ELqTo/8vHJ2eVWIUJBwCzbw3ryitH7LD3gyEr2NuQQJE++wyWPBHK
M3SFOft6AoGBAOdrYUJ38yjc9tnrvLWsB1KlkYhc+UbTMSRKfA8Yo/Xs5QldFycz
bUtsFGdLvqPol0pww2LqeKUQ8zVIF56Aw3SxmPMnOzRVQXpUI7z2W3/Ie4/i2Lu/
xXos8ZHnIu+e7SLJRHe+RGNvISbsQhk+vnpNQP5ciuO0ltu90L9+2YvWAhUAr/vy
ahuEz4UFGhB8IIeLWQUO5FA=
-----END DSA PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
ssh-dss AAAAB3NzaC1kc3MAAACBAOz6f1kqHBg2vVXa4afQL/YxJMzgoHim7LiNHm5tFNPXKrlJvMpFCUKN+mUM3/8SprpqIWa8YoDdEpS0+0GYP3oQdbWa+vs749zzPwv/jOD22RVBHpVYEqAGFXBkcPPOzn4CDaPngFl9xoYxw0aFMT0Nxlh4j+3oWE7GCkgPcQD9AAAAFQDMiHMwVO+MQePCDKGppRIXOS4ftwAAAIEAy7LaH0r36hAg9xNywP+a2aE5iXDZk8IlXZtYV5ndDEC6N6cHMSnSiqG3y12P4ETsSv4JZPYBv8D3YyuNhRoZo+N0Xn4roJI8xResrycFptIEn4QupOj/y8cnZ5VYhQkHALNvDevKK0fssPeDISvY25BAkT77DJY8EcozdIU5+3oAAACBAOdrYUJ38yjc9tnrvLWsB1KlkYhc+UbTMSRKfA8Yo/Xs5QldFyczbUtsFGdLvqPol0pww2LqeKUQ8zVIF56Aw3SxmPMnOzRVQXpUI7z2W3/Ie4/i2Lu/xXos8ZHnIu+e7SLJRHe+RGNvISbsQhk+vnpNQP5ciuO0ltu90L9+2YvW old openssh format
+7
View File
@@ -0,0 +1,7 @@
{
"type": "ssh-dss",
"comment": "old openssh format",
"public": "-----BEGIN PUBLIC KEY-----\nMIIBuDCCASwGByqGSM44BAEwggEfAoGBAOz6f1kqHBg2vVXa4afQL/YxJMzgoHim\n7LiNHm5tFNPXKrlJvMpFCUKN+mUM3/8SprpqIWa8YoDdEpS0+0GYP3oQdbWa+vs7\n49zzPwv/jOD22RVBHpVYEqAGFXBkcPPOzn4CDaPngFl9xoYxw0aFMT0Nxlh4j+3o\nWE7GCkgPcQD9AhUAzIhzMFTvjEHjwgyhqaUSFzkuH7cCgYEAy7LaH0r36hAg9xNy\nwP+a2aE5iXDZk8IlXZtYV5ndDEC6N6cHMSnSiqG3y12P4ETsSv4JZPYBv8D3YyuN\nhRoZo+N0Xn4roJI8xResrycFptIEn4QupOj/y8cnZ5VYhQkHALNvDevKK0fssPeD\nISvY25BAkT77DJY8EcozdIU5+3oDgYUAAoGBAOdrYUJ38yjc9tnrvLWsB1KlkYhc\n+UbTMSRKfA8Yo/Xs5QldFyczbUtsFGdLvqPol0pww2LqeKUQ8zVIF56Aw3SxmPMn\nOzRVQXpUI7z2W3/Ie4/i2Lu/xXos8ZHnIu+e7SLJRHe+RGNvISbsQhk+vnpNQP5c\niuO0ltu90L9+2YvW\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAB3NzaC1kc3MAAACBAOz6f1kqHBg2vVXa4afQL/YxJMzgoHim7LiNHm5tFNPXKrlJvMpFCUKN+mUM3/8SprpqIWa8YoDdEpS0+0GYP3oQdbWa+vs749zzPwv/jOD22RVBHpVYEqAGFXBkcPPOzn4CDaPngFl9xoYxw0aFMT0Nxlh4j+3oWE7GCkgPcQD9AAAAFQDMiHMwVO+MQePCDKGppRIXOS4ftwAAAIEAy7LaH0r36hAg9xNywP+a2aE5iXDZk8IlXZtYV5ndDEC6N6cHMSnSiqG3y12P4ETsSv4JZPYBv8D3YyuNhRoZo+N0Xn4roJI8xResrycFptIEn4QupOj/y8cnZ5VYhQkHALNvDevKK0fssPeDISvY25BAkT77DJY8EcozdIU5+3oAAACBAOdrYUJ38yjc9tnrvLWsB1KlkYhc+UbTMSRKfA8Yo/Xs5QldFyczbUtsFGdLvqPol0pww2LqeKUQ8zVIF56Aw3SxmPMnOzRVQXpUI7z2W3/Ie4/i2Lu/xXos8ZHnIu+e7SLJRHe+RGNvISbsQhk+vnpNQP5ciuO0ltu90L9+2YvW",
"private": null
}
+7
View File
@@ -0,0 +1,7 @@
{
"type": "ssh-dss",
"comment": "",
"public": "-----BEGIN PUBLIC KEY-----\nMIIBuDCCASwGByqGSM44BAEwggEfAoGBAOz6f1kqHBg2vVXa4afQL/YxJMzgoHim\n7LiNHm5tFNPXKrlJvMpFCUKN+mUM3/8SprpqIWa8YoDdEpS0+0GYP3oQdbWa+vs7\n49zzPwv/jOD22RVBHpVYEqAGFXBkcPPOzn4CDaPngFl9xoYxw0aFMT0Nxlh4j+3o\nWE7GCkgPcQD9AhUAzIhzMFTvjEHjwgyhqaUSFzkuH7cCgYEAy7LaH0r36hAg9xNy\nwP+a2aE5iXDZk8IlXZtYV5ndDEC6N6cHMSnSiqG3y12P4ETsSv4JZPYBv8D3YyuN\nhRoZo+N0Xn4roJI8xResrycFptIEn4QupOj/y8cnZ5VYhQkHALNvDevKK0fssPeD\nISvY25BAkT77DJY8EcozdIU5+3oDgYUAAoGBAOdrYUJ38yjc9tnrvLWsB1KlkYhc\n+UbTMSRKfA8Yo/Xs5QldFyczbUtsFGdLvqPol0pww2LqeKUQ8zVIF56Aw3SxmPMn\nOzRVQXpUI7z2W3/Ie4/i2Lu/xXos8ZHnIu+e7SLJRHe+RGNvISbsQhk+vnpNQP5c\niuO0ltu90L9+2YvW\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAB3NzaC1kc3MAAACBAOz6f1kqHBg2vVXa4afQL/YxJMzgoHim7LiNHm5tFNPXKrlJvMpFCUKN+mUM3/8SprpqIWa8YoDdEpS0+0GYP3oQdbWa+vs749zzPwv/jOD22RVBHpVYEqAGFXBkcPPOzn4CDaPngFl9xoYxw0aFMT0Nxlh4j+3oWE7GCkgPcQD9AAAAFQDMiHMwVO+MQePCDKGppRIXOS4ftwAAAIEAy7LaH0r36hAg9xNywP+a2aE5iXDZk8IlXZtYV5ndDEC6N6cHMSnSiqG3y12P4ETsSv4JZPYBv8D3YyuNhRoZo+N0Xn4roJI8xResrycFptIEn4QupOj/y8cnZ5VYhQkHALNvDevKK0fssPeDISvY25BAkT77DJY8EcozdIU5+3oAAACBAOdrYUJ38yjc9tnrvLWsB1KlkYhc+UbTMSRKfA8Yo/Xs5QldFyczbUtsFGdLvqPol0pww2LqeKUQ8zVIF56Aw3SxmPMnOzRVQXpUI7z2W3/Ie4/i2Lu/xXos8ZHnIu+e7SLJRHe+RGNvISbsQhk+vnpNQP5ciuO0ltu90L9+2YvW",
"private": "-----BEGIN DSA PRIVATE KEY-----\nMIIBvQIBAAKBgQDs+n9ZKhwYNr1V2uGn0C/2MSTM4KB4puy4jR5ubRTT1yq5SbzK\nRQlCjfplDN//Eqa6aiFmvGKA3RKUtPtBmD96EHW1mvr7O+Pc8z8L/4zg9tkVQR6V\nWBKgBhVwZHDzzs5+Ag2j54BZfcaGMcNGhTE9DcZYeI/t6FhOxgpID3EA/QIVAMyI\nczBU74xB48IMoamlEhc5Lh+3AoGBAMuy2h9K9+oQIPcTcsD/mtmhOYlw2ZPCJV2b\nWFeZ3QxAujenBzEp0oqht8tdj+BE7Er+CWT2Ab/A92MrjYUaGaPjdF5+K6CSPMUX\nrK8nBabSBJ+ELqTo/8vHJ2eVWIUJBwCzbw3ryitH7LD3gyEr2NuQQJE++wyWPBHK\nM3SFOft6AoGBAOdrYUJ38yjc9tnrvLWsB1KlkYhc+UbTMSRKfA8Yo/Xs5QldFycz\nbUtsFGdLvqPol0pww2LqeKUQ8zVIF56Aw3SxmPMnOzRVQXpUI7z2W3/Ie4/i2Lu/\nxXos8ZHnIu+e7SLJRHe+RGNvISbsQhk+vnpNQP5ciuO0ltu90L9+2YvWAhUAr/vy\nahuEz4UFGhB8IIeLWQUO5FA=\n-----END DSA PRIVATE KEY-----"
}
+15
View File
@@ -0,0 +1,15 @@
-----BEGIN DSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,3239878D1E2D496289CE9CD2CB639BE8
k8/4Ax6UcnImNvEuybHwa9OHZHeCpKmq3Cu/q29a9AkTnktAWVmU9rQFch5CweDH
TEuRN+ZHecHrrMPR0fTpjXzZTxmU3549BQ2DfMSAdikPNKtBvhJwpT2se0rJ9M98
p2xJQNhpxXT6f4Hy8m6QvjP5iTmlnQrrVBjV05ih9TLLQb4Y4NlydC08OyEcEoJV
w43G69sv2ws/tUVr7XSUtv8l+51ywSm42Pw6YOVlMZ7y+XB/uWmFNMz5gLN17tkc
wikhgvNnMWGLqb/AruuKPp5FrGRIC19DKRzDSPF5WlzLBdd2TQKDltknDj08AQMJ
bDsImbePteqhU+D7GiN2pVAD2b5kCZlFzYG43/Q8R3+O2l0Lvq5VBIqNB7LyJfTy
DL8XX0gzHk7FgG5MfLYin/qp7upnDXeSnIm8A2tlBYh9YzG3q/a53c5V2NomWjX0
zvS+C7+w5NDwDRT5t+kecMhmHWNBuE/Pbvy0DaZQ/nnsC6TlkcaROJ0fiY3Da8E6
EYvM4uKaZudsOOapwx0ZXHu2GZgLnly0p2Cd0Yf9t2UX9uySfwdL2TNw8nLVNVkh
aBE/x9LkKPWqOBV8tg/9ITGys/qgZh0A1r+RGmj/tII=
-----END DSA PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
ssh-dss AAAAB3NzaC1kc3MAAACBAP25RC69mW4t09jpaine5ZRHmOtqNJa2nbsRrSsZkvGXxbJ7ojxsybWf4kAAI4GpsGMzlrFrlMEpHQfebJAn+zJwGS+loR7T+gNz8JoVIgPF9dabXVymcygl4FB/sNAmV4XK3OjvSW1NCKdSkwZZr/gz5JBo1qAiQDKMD/ikWqq/AAAAFQC/rPmzFozpCeLbFQykOaDGFZaqaQAAAIEAw1hJAYQzn/ZboF/xXDHzP49uRpIIoyaSfUz5W3+Lpi/CBkOIGaGOuitwcpTfzBSZIDZ9ORs9fq5oBh29JJcAdBNgVXfzThSiGvBgU4UIj41MlG4PG6St88VXCy0niEXWmjSkdcW3hZ0ai0SOlVxxEkYneg7RH9Seh+U3rRacrh4AAACAOX41OCxx8mTuxpON/uZn6GwvK/m0K9fr/UmIX8D4Mp8PgnPLC71AOwLy1HrCVi3ohCqeSY2C1uf1VWUVlSqMH85Pxc7pLtuULoQdCgiYt1agVrioFSP6bEyFdV8vGxA4YGh6cUSkeFZBJBrdNM4VmYBeT+3n/IO5uUbWoPK5iAo=
@@ -0,0 +1,8 @@
{
"type": "ssh-dss",
"comment": "",
"public": "-----BEGIN PUBLIC KEY-----\nMIIBtzCCASwGByqGSM44BAEwggEfAoGBAP25RC69mW4t09jpaine5ZRHmOtqNJa2\nnbsRrSsZkvGXxbJ7ojxsybWf4kAAI4GpsGMzlrFrlMEpHQfebJAn+zJwGS+loR7T\n+gNz8JoVIgPF9dabXVymcygl4FB/sNAmV4XK3OjvSW1NCKdSkwZZr/gz5JBo1qAi\nQDKMD/ikWqq/AhUAv6z5sxaM6Qni2xUMpDmgxhWWqmkCgYEAw1hJAYQzn/ZboF/x\nXDHzP49uRpIIoyaSfUz5W3+Lpi/CBkOIGaGOuitwcpTfzBSZIDZ9ORs9fq5oBh29\nJJcAdBNgVXfzThSiGvBgU4UIj41MlG4PG6St88VXCy0niEXWmjSkdcW3hZ0ai0SO\nlVxxEkYneg7RH9Seh+U3rRacrh4DgYQAAoGAOX41OCxx8mTuxpON/uZn6GwvK/m0\nK9fr/UmIX8D4Mp8PgnPLC71AOwLy1HrCVi3ohCqeSY2C1uf1VWUVlSqMH85Pxc7p\nLtuULoQdCgiYt1agVrioFSP6bEyFdV8vGxA4YGh6cUSkeFZBJBrdNM4VmYBeT+3n\n/IO5uUbWoPK5iAo=\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAB3NzaC1kc3MAAACBAP25RC69mW4t09jpaine5ZRHmOtqNJa2nbsRrSsZkvGXxbJ7ojxsybWf4kAAI4GpsGMzlrFrlMEpHQfebJAn+zJwGS+loR7T+gNz8JoVIgPF9dabXVymcygl4FB/sNAmV4XK3OjvSW1NCKdSkwZZr/gz5JBo1qAiQDKMD/ikWqq/AAAAFQC/rPmzFozpCeLbFQykOaDGFZaqaQAAAIEAw1hJAYQzn/ZboF/xXDHzP49uRpIIoyaSfUz5W3+Lpi/CBkOIGaGOuitwcpTfzBSZIDZ9ORs9fq5oBh29JJcAdBNgVXfzThSiGvBgU4UIj41MlG4PG6St88VXCy0niEXWmjSkdcW3hZ0ai0SOlVxxEkYneg7RH9Seh+U3rRacrh4AAACAOX41OCxx8mTuxpON/uZn6GwvK/m0K9fr/UmIX8D4Mp8PgnPLC71AOwLy1HrCVi3ohCqeSY2C1uf1VWUVlSqMH85Pxc7pLtuULoQdCgiYt1agVrioFSP6bEyFdV8vGxA4YGh6cUSkeFZBJBrdNM4VmYBeT+3n/IO5uUbWoPK5iAo=",
"private": null
}
+7
View File
@@ -0,0 +1,7 @@
{
"type": "ssh-dss",
"comment": "",
"public": "-----BEGIN PUBLIC KEY-----\nMIIBtzCCASwGByqGSM44BAEwggEfAoGBAP25RC69mW4t09jpaine5ZRHmOtqNJa2\nnbsRrSsZkvGXxbJ7ojxsybWf4kAAI4GpsGMzlrFrlMEpHQfebJAn+zJwGS+loR7T\n+gNz8JoVIgPF9dabXVymcygl4FB/sNAmV4XK3OjvSW1NCKdSkwZZr/gz5JBo1qAi\nQDKMD/ikWqq/AhUAv6z5sxaM6Qni2xUMpDmgxhWWqmkCgYEAw1hJAYQzn/ZboF/x\nXDHzP49uRpIIoyaSfUz5W3+Lpi/CBkOIGaGOuitwcpTfzBSZIDZ9ORs9fq5oBh29\nJJcAdBNgVXfzThSiGvBgU4UIj41MlG4PG6St88VXCy0niEXWmjSkdcW3hZ0ai0SO\nlVxxEkYneg7RH9Seh+U3rRacrh4DgYQAAoGAOX41OCxx8mTuxpON/uZn6GwvK/m0\nK9fr/UmIX8D4Mp8PgnPLC71AOwLy1HrCVi3ohCqeSY2C1uf1VWUVlSqMH85Pxc7p\nLtuULoQdCgiYt1agVrioFSP6bEyFdV8vGxA4YGh6cUSkeFZBJBrdNM4VmYBeT+3n\n/IO5uUbWoPK5iAo=\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAB3NzaC1kc3MAAACBAP25RC69mW4t09jpaine5ZRHmOtqNJa2nbsRrSsZkvGXxbJ7ojxsybWf4kAAI4GpsGMzlrFrlMEpHQfebJAn+zJwGS+loR7T+gNz8JoVIgPF9dabXVymcygl4FB/sNAmV4XK3OjvSW1NCKdSkwZZr/gz5JBo1qAiQDKMD/ikWqq/AAAAFQC/rPmzFozpCeLbFQykOaDGFZaqaQAAAIEAw1hJAYQzn/ZboF/xXDHzP49uRpIIoyaSfUz5W3+Lpi/CBkOIGaGOuitwcpTfzBSZIDZ9ORs9fq5oBh29JJcAdBNgVXfzThSiGvBgU4UIj41MlG4PG6St88VXCy0niEXWmjSkdcW3hZ0ai0SOlVxxEkYneg7RH9Seh+U3rRacrh4AAACAOX41OCxx8mTuxpON/uZn6GwvK/m0K9fr/UmIX8D4Mp8PgnPLC71AOwLy1HrCVi3ohCqeSY2C1uf1VWUVlSqMH85Pxc7pLtuULoQdCgiYt1agVrioFSP6bEyFdV8vGxA4YGh6cUSkeFZBJBrdNM4VmYBeT+3n/IO5uUbWoPK5iAo=",
"private": "-----BEGIN DSA PRIVATE KEY-----\nMIIBvAIBAAKBgQD9uUQuvZluLdPY6Wop3uWUR5jrajSWtp27Ea0rGZLxl8Wye6I8\nbMm1n+JAACOBqbBjM5axa5TBKR0H3myQJ/sycBkvpaEe0/oDc/CaFSIDxfXWm11c\npnMoJeBQf7DQJleFytzo70ltTQinUpMGWa/4M+SQaNagIkAyjA/4pFqqvwIVAL+s\n+bMWjOkJ4tsVDKQ5oMYVlqppAoGBAMNYSQGEM5/2W6Bf8Vwx8z+PbkaSCKMmkn1M\n+Vt/i6YvwgZDiBmhjrorcHKU38wUmSA2fTkbPX6uaAYdvSSXAHQTYFV3804Uohrw\nYFOFCI+NTJRuDxukrfPFVwstJ4hF1po0pHXFt4WdGotEjpVccRJGJ3oO0R/Unofl\nN60WnK4eAoGAOX41OCxx8mTuxpON/uZn6GwvK/m0K9fr/UmIX8D4Mp8PgnPLC71A\nOwLy1HrCVi3ohCqeSY2C1uf1VWUVlSqMH85Pxc7pLtuULoQdCgiYt1agVrioFSP6\nbEyFdV8vGxA4YGh6cUSkeFZBJBrdNM4VmYBeT+3n/IO5uUbWoPK5iAoCFQCdYU1l\nO1pCZ3Jhf/YDAAnfQHAtMxAQEBAQEBAQEBAQEBAQEBA=\n-----END DSA PRIVATE KEY-----"
}
+5
View File
@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIJx7zPcbJg1zUAsBhKbmN0eOjbr+/W2qGSZTCP/c0mz4oAoGCCqGSM49
AwEHoUQDQgAELN85t86lbEONGsyPNDxD/P2f9D9/ePBT3ZpAeVYUdyrVO00jO4JE
FPfKlVc4htC9oZbDaNeW1ssAIbn4uzigMQ==
-----END EC PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCzfObfOpWxDjRrMjzQ8Q/z9n/Q/f3jwU92aQHlWFHcq1TtNIzuCRBT3ypVXOIbQvaGWw2jXltbLACG5+Ls4oDE= old openssh format
+7
View File
@@ -0,0 +1,7 @@
{
"type": "ecdsa-sha2-nistp256",
"comment": "old openssh format",
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELN85t86lbEONGsyPNDxD/P2f9D9/\nePBT3ZpAeVYUdyrVO00jO4JEFPfKlVc4htC9oZbDaNeW1ssAIbn4uzigMQ==\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCzfObfOpWxDjRrMjzQ8Q/z9n/Q/f3jwU92aQHlWFHcq1TtNIzuCRBT3ypVXOIbQvaGWw2jXltbLACG5+Ls4oDE=",
"private": null
}
+7
View File
@@ -0,0 +1,7 @@
{
"type": "ecdsa-sha2-nistp256",
"comment": "",
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELN85t86lbEONGsyPNDxD/P2f9D9/\nePBT3ZpAeVYUdyrVO00jO4JEFPfKlVc4htC9oZbDaNeW1ssAIbn4uzigMQ==\n-----END PUBLIC KEY-----",
"publicSSH": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCzfObfOpWxDjRrMjzQ8Q/z9n/Q/f3jwU92aQHlWFHcq1TtNIzuCRBT3ypVXOIbQvaGWw2jXltbLACG5+Ls4oDE=",
"private": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIJx7zPcbJg1zUAsBhKbmN0eOjbr+/W2qGSZTCP/c0mz4oAoGCCqGSM49\nAwEHoUQDQgAELN85t86lbEONGsyPNDxD/P2f9D9/ePBT3ZpAeVYUdyrVO00jO4JE\nFPfKlVc4htC9oZbDaNeW1ssAIbn4uzigMQ==\n-----END EC PRIVATE KEY-----"
}
+8
View File
@@ -0,0 +1,8 @@
-----BEGIN EC PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,4BE217089AE8B7311672C159E0690AB4
AkqjOP53cDHrdkJFRVLHYS7fSPVcIa4BgKegLwqRUqJOvEOnn5j6RYCh2CMdPjwN
rdw26Gc0V++xeMISAbrX4TGAQPWyDyiuoCffTIAfbkNq8YQR/sNJjNmZEgtCs6+O
4iBQ8TMXO+7oWRC221FDbTIhB6k4lXXph/HzdW0/Y2A=
-----END EC PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBA4KgjqWJj9PR55PeF7t7PTXdx7cvMDqNkq4UTMjoXA5WtQYdoC2sxJnI5Psqvtrfa13C31gY8TlFAZ1cClnoBk=

Some files were not shown because too many files have changed in this diff Show More