trouble-in-terror-town/node_modules/sshpk/lib/formats/rfc4253.js
Mikolaj 2bbacbea09 did some more work on networking and removed EOS in favor of LRM
did some more work on networking and removed EOS in favor of Light Reflective Mirror
2022-05-31 15:04:31 +02:00

166 lines
4.1 KiB
JavaScript

// Copyright 2015 Joyent, Inc.
module.exports = {
read: read.bind(undefined, false, undefined),
readType: read.bind(undefined, false),
write: write,
/* semi-private api, used by sshpk-agent */
readPartial: read.bind(undefined, true),
/* shared with ssh format */
readInternal: read,
keyTypeToAlg: keyTypeToAlg,
algToKeyType: algToKeyType
};
var assert = require('assert-plus');
var Buffer = require('safer-buffer').Buffer;
var algs = require('../algs');
var utils = require('../utils');
var Key = require('../key');
var PrivateKey = require('../private-key');
var SSHBuffer = require('../ssh-buffer');
function algToKeyType(alg) {
assert.string(alg);
if (alg === 'ssh-dss')
return ('dsa');
else if (alg === 'ssh-rsa')
return ('rsa');
else if (alg === 'ssh-ed25519')
return ('ed25519');
else if (alg === 'ssh-curve25519')
return ('curve25519');
else if (alg.match(/^ecdsa-sha2-/))
return ('ecdsa');
else
throw (new Error('Unknown algorithm ' + alg));
}
function keyTypeToAlg(key) {
assert.object(key);
if (key.type === 'dsa')
return ('ssh-dss');
else if (key.type === 'rsa')
return ('ssh-rsa');
else if (key.type === 'ed25519')
return ('ssh-ed25519');
else if (key.type === 'curve25519')
return ('ssh-curve25519');
else if (key.type === 'ecdsa')
return ('ecdsa-sha2-' + key.part.curve.data.toString());
else
throw (new Error('Unknown key type ' + key.type));
}
function read(partial, type, buf, options) {
if (typeof (buf) === 'string')
buf = Buffer.from(buf);
assert.buffer(buf, 'buf');
var key = {};
var parts = key.parts = [];
var sshbuf = new SSHBuffer({buffer: buf});
var alg = sshbuf.readString();
assert.ok(!sshbuf.atEnd(), 'key must have at least one part');
key.type = algToKeyType(alg);
var partCount = algs.info[key.type].parts.length;
if (type && type === 'private')
partCount = algs.privInfo[key.type].parts.length;
while (!sshbuf.atEnd() && parts.length < partCount)
parts.push(sshbuf.readPart());
while (!partial && !sshbuf.atEnd())
parts.push(sshbuf.readPart());
assert.ok(parts.length >= 1,
'key must have at least one part');
assert.ok(partial || sshbuf.atEnd(),
'leftover bytes at end of key');
var Constructor = Key;
var algInfo = algs.info[key.type];
if (type === 'private' || algInfo.parts.length !== parts.length) {
algInfo = algs.privInfo[key.type];
Constructor = PrivateKey;
}
assert.strictEqual(algInfo.parts.length, parts.length);
if (key.type === 'ecdsa') {
var res = /^ecdsa-sha2-(.+)$/.exec(alg);
assert.ok(res !== null);
assert.strictEqual(res[1], parts[0].data.toString());
}
var normalized = true;
for (var i = 0; i < algInfo.parts.length; ++i) {
var p = parts[i];
p.name = algInfo.parts[i];
/*
* OpenSSH stores ed25519 "private" keys as seed + public key
* concat'd together (k followed by A). We want to keep them
* separate for other formats that don't do this.
*/
if (key.type === 'ed25519' && p.name === 'k')
p.data = p.data.slice(0, 32);
if (p.name !== 'curve' && algInfo.normalize !== false) {
var nd;
if (key.type === 'ed25519') {
nd = utils.zeroPadToLength(p.data, 32);
} else {
nd = utils.mpNormalize(p.data);
}
if (nd.toString('binary') !==
p.data.toString('binary')) {
p.data = nd;
normalized = false;
}
}
}
if (normalized)
key._rfc4253Cache = sshbuf.toBuffer();
if (partial && typeof (partial) === 'object') {
partial.remainder = sshbuf.remainder();
partial.consumed = sshbuf._offset;
}
return (new Constructor(key));
}
function write(key, options) {
assert.object(key);
var alg = keyTypeToAlg(key);
var i;
var algInfo = algs.info[key.type];
if (PrivateKey.isPrivateKey(key))
algInfo = algs.privInfo[key.type];
var parts = algInfo.parts;
var buf = new SSHBuffer({});
buf.writeString(alg);
for (i = 0; i < parts.length; ++i) {
var data = key.part[parts[i]].data;
if (algInfo.normalize !== false) {
if (key.type === 'ed25519')
data = utils.zeroPadToLength(data, 32);
else
data = utils.mpNormalize(data);
}
if (key.type === 'ed25519' && parts[i] === 'k')
data = Buffer.concat([data, key.part.A.data]);
buf.writeBuffer(data);
}
return (buf.toBuffer());
}