trouble-in-terror-town/node_modules/sshpk/lib/formats/pkcs8.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

631 lines
14 KiB
JavaScript

// Copyright 2018 Joyent, Inc.
module.exports = {
read: read,
readPkcs8: readPkcs8,
write: write,
writePkcs8: writePkcs8,
pkcs8ToBuffer: pkcs8ToBuffer,
readECDSACurve: readECDSACurve,
writeECDSACurve: writeECDSACurve
};
var assert = require('assert-plus');
var asn1 = require('asn1');
var Buffer = require('safer-buffer').Buffer;
var algs = require('../algs');
var utils = require('../utils');
var Key = require('../key');
var PrivateKey = require('../private-key');
var pem = require('./pem');
function read(buf, options) {
return (pem.read(buf, options, 'pkcs8'));
}
function write(key, options) {
return (pem.write(key, options, 'pkcs8'));
}
/* Helper to read in a single mpint */
function readMPInt(der, nm) {
assert.strictEqual(der.peek(), asn1.Ber.Integer,
nm + ' is not an Integer');
return (utils.mpNormalize(der.readString(asn1.Ber.Integer, true)));
}
function readPkcs8(alg, type, der) {
/* Private keys in pkcs#8 format have a weird extra int */
if (der.peek() === asn1.Ber.Integer) {
assert.strictEqual(type, 'private',
'unexpected Integer at start of public key');
der.readString(asn1.Ber.Integer, true);
}
der.readSequence();
var next = der.offset + der.length;
var oid = der.readOID();
switch (oid) {
case '1.2.840.113549.1.1.1':
der._offset = next;
if (type === 'public')
return (readPkcs8RSAPublic(der));
else
return (readPkcs8RSAPrivate(der));
case '1.2.840.10040.4.1':
if (type === 'public')
return (readPkcs8DSAPublic(der));
else
return (readPkcs8DSAPrivate(der));
case '1.2.840.10045.2.1':
if (type === 'public')
return (readPkcs8ECDSAPublic(der));
else
return (readPkcs8ECDSAPrivate(der));
case '1.3.101.112':
if (type === 'public') {
return (readPkcs8EdDSAPublic(der));
} else {
return (readPkcs8EdDSAPrivate(der));
}
case '1.3.101.110':
if (type === 'public') {
return (readPkcs8X25519Public(der));
} else {
return (readPkcs8X25519Private(der));
}
default:
throw (new Error('Unknown key type OID ' + oid));
}
}
function readPkcs8RSAPublic(der) {
// bit string sequence
der.readSequence(asn1.Ber.BitString);
der.readByte();
der.readSequence();
// modulus
var n = readMPInt(der, 'modulus');
var e = readMPInt(der, 'exponent');
// now, make the key
var key = {
type: 'rsa',
source: der.originalInput,
parts: [
{ name: 'e', data: e },
{ name: 'n', data: n }
]
};
return (new Key(key));
}
function readPkcs8RSAPrivate(der) {
der.readSequence(asn1.Ber.OctetString);
der.readSequence();
var ver = readMPInt(der, 'version');
assert.equal(ver[0], 0x0, 'unknown RSA private key version');
// modulus then public exponent
var n = readMPInt(der, 'modulus');
var e = readMPInt(der, 'public exponent');
var d = readMPInt(der, 'private exponent');
var p = readMPInt(der, 'prime1');
var q = readMPInt(der, 'prime2');
var dmodp = readMPInt(der, 'exponent1');
var dmodq = readMPInt(der, 'exponent2');
var iqmp = readMPInt(der, 'iqmp');
// now, make the key
var key = {
type: 'rsa',
parts: [
{ name: 'n', data: n },
{ name: 'e', data: e },
{ name: 'd', data: d },
{ name: 'iqmp', data: iqmp },
{ name: 'p', data: p },
{ name: 'q', data: q },
{ name: 'dmodp', data: dmodp },
{ name: 'dmodq', data: dmodq }
]
};
return (new PrivateKey(key));
}
function readPkcs8DSAPublic(der) {
der.readSequence();
var p = readMPInt(der, 'p');
var q = readMPInt(der, 'q');
var g = readMPInt(der, 'g');
// bit string sequence
der.readSequence(asn1.Ber.BitString);
der.readByte();
var y = readMPInt(der, 'y');
// now, make the key
var key = {
type: 'dsa',
parts: [
{ name: 'p', data: p },
{ name: 'q', data: q },
{ name: 'g', data: g },
{ name: 'y', data: y }
]
};
return (new Key(key));
}
function readPkcs8DSAPrivate(der) {
der.readSequence();
var p = readMPInt(der, 'p');
var q = readMPInt(der, 'q');
var g = readMPInt(der, 'g');
der.readSequence(asn1.Ber.OctetString);
var x = readMPInt(der, 'x');
/* The pkcs#8 format does not include the public key */
var y = utils.calculateDSAPublic(g, p, x);
var key = {
type: 'dsa',
parts: [
{ name: 'p', data: p },
{ name: 'q', data: q },
{ name: 'g', data: g },
{ name: 'y', data: y },
{ name: 'x', data: x }
]
};
return (new PrivateKey(key));
}
function readECDSACurve(der) {
var curveName, curveNames;
var j, c, cd;
if (der.peek() === asn1.Ber.OID) {
var oid = der.readOID();
curveNames = Object.keys(algs.curves);
for (j = 0; j < curveNames.length; ++j) {
c = curveNames[j];
cd = algs.curves[c];
if (cd.pkcs8oid === oid) {
curveName = c;
break;
}
}
} else {
// ECParameters sequence
der.readSequence();
var version = der.readString(asn1.Ber.Integer, true);
assert.strictEqual(version[0], 1, 'ECDSA key not version 1');
var curve = {};
// FieldID sequence
der.readSequence();
var fieldTypeOid = der.readOID();
assert.strictEqual(fieldTypeOid, '1.2.840.10045.1.1',
'ECDSA key is not from a prime-field');
var p = curve.p = utils.mpNormalize(
der.readString(asn1.Ber.Integer, true));
/*
* p always starts with a 1 bit, so count the zeros to get its
* real size.
*/
curve.size = p.length * 8 - utils.countZeros(p);
// Curve sequence
der.readSequence();
curve.a = utils.mpNormalize(
der.readString(asn1.Ber.OctetString, true));
curve.b = utils.mpNormalize(
der.readString(asn1.Ber.OctetString, true));
if (der.peek() === asn1.Ber.BitString)
curve.s = der.readString(asn1.Ber.BitString, true);
// Combined Gx and Gy
curve.G = der.readString(asn1.Ber.OctetString, true);
assert.strictEqual(curve.G[0], 0x4,
'uncompressed G is required');
curve.n = utils.mpNormalize(
der.readString(asn1.Ber.Integer, true));
curve.h = utils.mpNormalize(
der.readString(asn1.Ber.Integer, true));
assert.strictEqual(curve.h[0], 0x1, 'a cofactor=1 curve is ' +
'required');
curveNames = Object.keys(algs.curves);
var ks = Object.keys(curve);
for (j = 0; j < curveNames.length; ++j) {
c = curveNames[j];
cd = algs.curves[c];
var equal = true;
for (var i = 0; i < ks.length; ++i) {
var k = ks[i];
if (cd[k] === undefined)
continue;
if (typeof (cd[k]) === 'object' &&
cd[k].equals !== undefined) {
if (!cd[k].equals(curve[k])) {
equal = false;
break;
}
} else if (Buffer.isBuffer(cd[k])) {
if (cd[k].toString('binary')
!== curve[k].toString('binary')) {
equal = false;
break;
}
} else {
if (cd[k] !== curve[k]) {
equal = false;
break;
}
}
}
if (equal) {
curveName = c;
break;
}
}
}
return (curveName);
}
function readPkcs8ECDSAPrivate(der) {
var curveName = readECDSACurve(der);
assert.string(curveName, 'a known elliptic curve');
der.readSequence(asn1.Ber.OctetString);
der.readSequence();
var version = readMPInt(der, 'version');
assert.equal(version[0], 1, 'unknown version of ECDSA key');
var d = der.readString(asn1.Ber.OctetString, true);
var Q;
if (der.peek() == 0xa0) {
der.readSequence(0xa0);
der._offset += der.length;
}
if (der.peek() == 0xa1) {
der.readSequence(0xa1);
Q = der.readString(asn1.Ber.BitString, true);
Q = utils.ecNormalize(Q);
}
if (Q === undefined) {
var pub = utils.publicFromPrivateECDSA(curveName, d);
Q = pub.part.Q.data;
}
var key = {
type: 'ecdsa',
parts: [
{ name: 'curve', data: Buffer.from(curveName) },
{ name: 'Q', data: Q },
{ name: 'd', data: d }
]
};
return (new PrivateKey(key));
}
function readPkcs8ECDSAPublic(der) {
var curveName = readECDSACurve(der);
assert.string(curveName, 'a known elliptic curve');
var Q = der.readString(asn1.Ber.BitString, true);
Q = utils.ecNormalize(Q);
var key = {
type: 'ecdsa',
parts: [
{ name: 'curve', data: Buffer.from(curveName) },
{ name: 'Q', data: Q }
]
};
return (new Key(key));
}
function readPkcs8EdDSAPublic(der) {
if (der.peek() === 0x00)
der.readByte();
var A = utils.readBitString(der);
var key = {
type: 'ed25519',
parts: [
{ name: 'A', data: utils.zeroPadToLength(A, 32) }
]
};
return (new Key(key));
}
function readPkcs8X25519Public(der) {
var A = utils.readBitString(der);
var key = {
type: 'curve25519',
parts: [
{ name: 'A', data: utils.zeroPadToLength(A, 32) }
]
};
return (new Key(key));
}
function readPkcs8EdDSAPrivate(der) {
if (der.peek() === 0x00)
der.readByte();
der.readSequence(asn1.Ber.OctetString);
var k = der.readString(asn1.Ber.OctetString, true);
k = utils.zeroPadToLength(k, 32);
var A;
if (der.peek() === asn1.Ber.BitString) {
A = utils.readBitString(der);
A = utils.zeroPadToLength(A, 32);
} else {
A = utils.calculateED25519Public(k);
}
var key = {
type: 'ed25519',
parts: [
{ name: 'A', data: utils.zeroPadToLength(A, 32) },
{ name: 'k', data: utils.zeroPadToLength(k, 32) }
]
};
return (new PrivateKey(key));
}
function readPkcs8X25519Private(der) {
if (der.peek() === 0x00)
der.readByte();
der.readSequence(asn1.Ber.OctetString);
var k = der.readString(asn1.Ber.OctetString, true);
k = utils.zeroPadToLength(k, 32);
var A = utils.calculateX25519Public(k);
var key = {
type: 'curve25519',
parts: [
{ name: 'A', data: utils.zeroPadToLength(A, 32) },
{ name: 'k', data: utils.zeroPadToLength(k, 32) }
]
};
return (new PrivateKey(key));
}
function pkcs8ToBuffer(key) {
var der = new asn1.BerWriter();
writePkcs8(der, key);
return (der.buffer);
}
function writePkcs8(der, key) {
der.startSequence();
if (PrivateKey.isPrivateKey(key)) {
var sillyInt = Buffer.from([0]);
der.writeBuffer(sillyInt, asn1.Ber.Integer);
}
der.startSequence();
switch (key.type) {
case 'rsa':
der.writeOID('1.2.840.113549.1.1.1');
if (PrivateKey.isPrivateKey(key))
writePkcs8RSAPrivate(key, der);
else
writePkcs8RSAPublic(key, der);
break;
case 'dsa':
der.writeOID('1.2.840.10040.4.1');
if (PrivateKey.isPrivateKey(key))
writePkcs8DSAPrivate(key, der);
else
writePkcs8DSAPublic(key, der);
break;
case 'ecdsa':
der.writeOID('1.2.840.10045.2.1');
if (PrivateKey.isPrivateKey(key))
writePkcs8ECDSAPrivate(key, der);
else
writePkcs8ECDSAPublic(key, der);
break;
case 'ed25519':
der.writeOID('1.3.101.112');
if (PrivateKey.isPrivateKey(key))
throw (new Error('Ed25519 private keys in pkcs8 ' +
'format are not supported'));
writePkcs8EdDSAPublic(key, der);
break;
default:
throw (new Error('Unsupported key type: ' + key.type));
}
der.endSequence();
}
function writePkcs8RSAPrivate(key, der) {
der.writeNull();
der.endSequence();
der.startSequence(asn1.Ber.OctetString);
der.startSequence();
var version = Buffer.from([0]);
der.writeBuffer(version, asn1.Ber.Integer);
der.writeBuffer(key.part.n.data, asn1.Ber.Integer);
der.writeBuffer(key.part.e.data, asn1.Ber.Integer);
der.writeBuffer(key.part.d.data, asn1.Ber.Integer);
der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
der.writeBuffer(key.part.q.data, asn1.Ber.Integer);
if (!key.part.dmodp || !key.part.dmodq)
utils.addRSAMissing(key);
der.writeBuffer(key.part.dmodp.data, asn1.Ber.Integer);
der.writeBuffer(key.part.dmodq.data, asn1.Ber.Integer);
der.writeBuffer(key.part.iqmp.data, asn1.Ber.Integer);
der.endSequence();
der.endSequence();
}
function writePkcs8RSAPublic(key, der) {
der.writeNull();
der.endSequence();
der.startSequence(asn1.Ber.BitString);
der.writeByte(0x00);
der.startSequence();
der.writeBuffer(key.part.n.data, asn1.Ber.Integer);
der.writeBuffer(key.part.e.data, asn1.Ber.Integer);
der.endSequence();
der.endSequence();
}
function writePkcs8DSAPrivate(key, der) {
der.startSequence();
der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
der.writeBuffer(key.part.q.data, asn1.Ber.Integer);
der.writeBuffer(key.part.g.data, asn1.Ber.Integer);
der.endSequence();
der.endSequence();
der.startSequence(asn1.Ber.OctetString);
der.writeBuffer(key.part.x.data, asn1.Ber.Integer);
der.endSequence();
}
function writePkcs8DSAPublic(key, der) {
der.startSequence();
der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
der.writeBuffer(key.part.q.data, asn1.Ber.Integer);
der.writeBuffer(key.part.g.data, asn1.Ber.Integer);
der.endSequence();
der.endSequence();
der.startSequence(asn1.Ber.BitString);
der.writeByte(0x00);
der.writeBuffer(key.part.y.data, asn1.Ber.Integer);
der.endSequence();
}
function writeECDSACurve(key, der) {
var curve = algs.curves[key.curve];
if (curve.pkcs8oid) {
/* This one has a name in pkcs#8, so just write the oid */
der.writeOID(curve.pkcs8oid);
} else {
// ECParameters sequence
der.startSequence();
var version = Buffer.from([1]);
der.writeBuffer(version, asn1.Ber.Integer);
// FieldID sequence
der.startSequence();
der.writeOID('1.2.840.10045.1.1'); // prime-field
der.writeBuffer(curve.p, asn1.Ber.Integer);
der.endSequence();
// Curve sequence
der.startSequence();
var a = curve.p;
if (a[0] === 0x0)
a = a.slice(1);
der.writeBuffer(a, asn1.Ber.OctetString);
der.writeBuffer(curve.b, asn1.Ber.OctetString);
der.writeBuffer(curve.s, asn1.Ber.BitString);
der.endSequence();
der.writeBuffer(curve.G, asn1.Ber.OctetString);
der.writeBuffer(curve.n, asn1.Ber.Integer);
var h = curve.h;
if (!h) {
h = Buffer.from([1]);
}
der.writeBuffer(h, asn1.Ber.Integer);
// ECParameters
der.endSequence();
}
}
function writePkcs8ECDSAPublic(key, der) {
writeECDSACurve(key, der);
der.endSequence();
var Q = utils.ecNormalize(key.part.Q.data, true);
der.writeBuffer(Q, asn1.Ber.BitString);
}
function writePkcs8ECDSAPrivate(key, der) {
writeECDSACurve(key, der);
der.endSequence();
der.startSequence(asn1.Ber.OctetString);
der.startSequence();
var version = Buffer.from([1]);
der.writeBuffer(version, asn1.Ber.Integer);
der.writeBuffer(key.part.d.data, asn1.Ber.OctetString);
der.startSequence(0xa1);
var Q = utils.ecNormalize(key.part.Q.data, true);
der.writeBuffer(Q, asn1.Ber.BitString);
der.endSequence();
der.endSequence();
der.endSequence();
}
function writePkcs8EdDSAPublic(key, der) {
der.endSequence();
utils.writeBitString(der, key.part.A.data);
}
function writePkcs8EdDSAPrivate(key, der) {
der.endSequence();
var k = utils.mpNormalize(key.part.k.data, true);
der.startSequence(asn1.Ber.OctetString);
der.writeBuffer(k, asn1.Ber.OctetString);
der.endSequence();
}