"use strict";
//
//  Copyright (c) Microsoft Corporation. All rights reserved.
//
Object.defineProperty(exports, "__esModule", { value: true });
exports.Sec1KeyFormatter = exports.Pkcs1KeyFormatter = exports.parsePem = exports.formatPem = void 0;
const bigInt_1 = require("../../io/bigInt");
const derData_1 = require("../../io/derData");
const ecdsaCurves_1 = require("../ecdsaCurves");
function formatPem(keyBytes, name) {
    const key = `-----BEGIN ${name}-----\n` +
        keyBytes
            .toString('base64')
            .match(/.{1,64}/g)
            .join('\n') +
        '\n' +
        `-----END ${name}-----\n`;
    return key;
}
exports.formatPem = formatPem;
function parsePem(key) {
    const keyBase64 = key.replace(/-+[^-\n]+KEY-+/g, '').replace(/\s/g, '');
    const keyBytes = Buffer.from(keyBase64, 'base64');
    return keyBytes;
}
exports.parsePem = parsePem;
/**
 * Provides *minimal* PKCS#1 import/export support for Node.js keys.
 *
 * This code is redundant with some of the PKCS#1 import/export code in the separate
 * `ssh-keys` library; that is intentional, and necessary to support a consistent
 * interface for importing/exporting key parameters in the core `ssh` library.
 */
class Pkcs1KeyFormatter {
    static formatRsaPublic(rsa) {
        const writer = new derData_1.DerWriter(Buffer.alloc(1024));
        writer.writeInteger(rsa.modulus);
        writer.writeInteger(rsa.exponent);
        return writer.toBuffer();
    }
    static formatRsaPrivate(rsa) {
        if (!(rsa.d && rsa.p && rsa.q && rsa.dp && rsa.dq && rsa.qi)) {
            throw new Error('Missing private key parameters.');
        }
        const writer = new derData_1.DerWriter(Buffer.alloc(2048));
        writer.writeInteger(bigInt_1.BigInt.fromInt32(0));
        writer.writeInteger(rsa.modulus);
        writer.writeInteger(rsa.exponent);
        writer.writeInteger(rsa.d);
        writer.writeInteger(rsa.p);
        writer.writeInteger(rsa.q);
        writer.writeInteger(rsa.dp);
        writer.writeInteger(rsa.dq);
        writer.writeInteger(rsa.qi);
        return writer.toBuffer();
    }
    static parseRsaPublic(keyBytes) {
        const reader = new derData_1.DerReader(keyBytes);
        const modulus = reader.readInteger();
        const exponent = reader.readInteger();
        return { modulus, exponent };
    }
    static parseRsaPrivate(keyBytes) {
        const reader = new derData_1.DerReader(keyBytes);
        const version = reader.readInteger();
        const modulus = reader.readInteger();
        const exponent = reader.readInteger();
        const d = reader.readInteger();
        const p = reader.readInteger();
        const q = reader.readInteger();
        const dp = reader.readInteger();
        const dq = reader.readInteger();
        const qi = reader.readInteger();
        return { modulus, exponent, d, p, q, dp, dq, qi };
    }
}
exports.Pkcs1KeyFormatter = Pkcs1KeyFormatter;
/**
 * Provides *minimal* SEC1 import/export support for Node.js keys.
 *
 * This code is redundant with some of the SEC1 import/export code in the separate
 * `ssh-keys` library; that is intentional, and necessary to support a consistent
 * interface for importing/exporting key parameters in the core `ssh` library.
 */
class Sec1KeyFormatter {
    static formatECPublic(ec) {
        const curve = ecdsaCurves_1.curves.find((c) => c.oid === ec.curve.oid);
        const keySizeInBytes = Math.ceil(curve.keySize / 8);
        const writer = new derData_1.DerWriter(Buffer.alloc(512));
        const oidsWriter = new derData_1.DerWriter(Buffer.alloc(100));
        oidsWriter.writeObjectIdentifier(Sec1KeyFormatter.ecPublicKeyOid);
        oidsWriter.writeObjectIdentifier(ec.curve.oid);
        writer.writeSequence(oidsWriter);
        const x = ec.x.toBytes({ unsigned: true, length: keySizeInBytes });
        const y = ec.y.toBytes({ unsigned: true, length: keySizeInBytes });
        const publicKeyData = Buffer.alloc(1 + x.length + y.length);
        publicKeyData[0] = 4; // Indicates uncompressed curve format
        x.copy(publicKeyData, 1);
        y.copy(publicKeyData, 1 + x.length);
        writer.writeBitString(publicKeyData);
        return writer.toBuffer();
    }
    static formatECPrivate(ec) {
        const curve = ecdsaCurves_1.curves.find((c) => c.oid === ec.curve.oid);
        const keySizeInBytes = Math.ceil(curve.keySize / 8);
        const writer = new derData_1.DerWriter(Buffer.alloc(512));
        writer.writeInteger(bigInt_1.BigInt.fromInt32(1)); // version
        writer.writeOctetString(ec.d.toBytes({ unsigned: true, length: keySizeInBytes }));
        const curveWriter = new derData_1.DerWriter(Buffer.alloc(100));
        curveWriter.writeObjectIdentifier(ec.curve.oid);
        writer.writeTagged(0, curveWriter);
        const x = ec.x.toBytes({ unsigned: true, length: keySizeInBytes });
        const y = ec.y.toBytes({ unsigned: true, length: keySizeInBytes });
        const publicKeyData = Buffer.alloc(1 + x.length + y.length);
        publicKeyData[0] = 4; // Indicates uncompressed curve format
        x.copy(publicKeyData, 1);
        y.copy(publicKeyData, 1 + x.length);
        const keyWriter = new derData_1.DerWriter(Buffer.alloc(512));
        keyWriter.writeBitString(publicKeyData);
        writer.writeTagged(1, keyWriter);
        return writer.toBuffer();
    }
    static parseECPublic(keyBytes) {
        var _a;
        const reader = new derData_1.DerReader(keyBytes);
        const oidsReader = reader.readSequence();
        const keyTypeOid = oidsReader.readObjectIdentifier();
        if (keyTypeOid !== Sec1KeyFormatter.ecPublicKeyOid) {
            throw new Error(`Unexpected key type OID: ${keyTypeOid}`);
        }
        const curveOid = oidsReader.readObjectIdentifier();
        const curveName = (_a = ecdsaCurves_1.curves.find((c) => c.oid === curveOid)) === null || _a === void 0 ? void 0 : _a.name;
        const xy = reader.readBitString();
        if (xy.length % 2 !== 1) {
            throw new Error(`Unexpected key data length: ${xy.length}`);
        }
        const x = bigInt_1.BigInt.fromBytes(xy.slice(1, 1 + (xy.length - 1) / 2), { unsigned: true });
        const y = bigInt_1.BigInt.fromBytes(xy.slice(1 + (xy.length - 1) / 2), { unsigned: true });
        const ec = {
            curve: { name: curveName, oid: curveOid },
            x,
            y,
        };
        return ec;
    }
    static parseECPrivate(keyBytes) {
        var _a;
        const reader = new derData_1.DerReader(keyBytes);
        const version = reader.readInteger().toInt32();
        if (version !== 1) {
            throw new Error(`Unsupported SEC1 format version: ${version}`);
        }
        const d = bigInt_1.BigInt.fromBytes(reader.readOctetString(), { unsigned: true });
        const curveReader = reader.tryReadTagged(0);
        if (!curveReader) {
            throw new Error('SEC1 curve info not found.');
        }
        const curveOid = curveReader.readObjectIdentifier();
        const curveName = (_a = ecdsaCurves_1.curves.find((c) => c.oid === curveOid)) === null || _a === void 0 ? void 0 : _a.name;
        const publicKeyReader = reader.tryReadTagged(1);
        if (!publicKeyReader) {
            throw new Error('SEC1 public key data not found.');
        }
        const xy = publicKeyReader.readBitString();
        if (xy.length % 2 !== 1) {
            throw new Error(`Unexpected key data length: ${xy.length}`);
        }
        const x = bigInt_1.BigInt.fromBytes(xy.slice(1, 1 + (xy.length - 1) / 2), { unsigned: true });
        const y = bigInt_1.BigInt.fromBytes(xy.slice(1 + (xy.length - 1) / 2), { unsigned: true });
        const ec = {
            curve: { name: curveName, oid: curveOid },
            x,
            y,
            d,
        };
        return ec;
    }
}
exports.Sec1KeyFormatter = Sec1KeyFormatter;
Sec1KeyFormatter.ecPublicKeyOid = '1.2.840.10045.2.1';
//# sourceMappingURL=https://main.vscode-cdn.net/sourcemaps/6a44c352bd24569c417e530095901b649960f9f8/node_modules/@microsoft/dev-tunnels-ssh/algorithms/node/keyFormatters.js.map