"use strict";
//
//  Copyright (c) Microsoft Corporation. All rights reserved.
//
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebECDiffieHellman = exports.WebDiffieHellman = void 0;
const buffer_1 = require("buffer");
const diffie_hellman_1 = require("diffie-hellman");
const keyExchangeAlgorithm_1 = require("../keyExchangeAlgorithm");
const webHmac_1 = require("./webHmac");
const bigInt_1 = require("../../io/bigInt");
const jsonWebKeyFormatter_1 = require("./jsonWebKeyFormatter");
class WebDiffieHellman extends keyExchangeAlgorithm_1.KeyExchangeAlgorithm {
    constructor(name, keySizeInBits, hashAlgorithmName) {
        super(name, keySizeInBits, hashAlgorithmName, webHmac_1.WebHmac.getHashDigestLength(hashAlgorithmName));
    }
    createKeyExchange() {
        return new WebDiffieHellmanKex(this.keySizeInBits, webHmac_1.WebHmac.getWebHashAlgorithmName(this.hashAlgorithmName), this.hashDigestLength);
    }
}
exports.WebDiffieHellman = WebDiffieHellman;
class WebDiffieHellmanKex {
    constructor(bitLength, hashAlgorithmName, digestLength) {
        this.hashAlgorithmName = hashAlgorithmName;
        this.digestLength = digestLength;
        switch (bitLength) {
            case 1024:
                this.dh = (0, diffie_hellman_1.getDiffieHellman)('modp2');
                break;
            case 2048:
                this.dh = (0, diffie_hellman_1.getDiffieHellman)('modp14');
                break;
            case 4096:
                this.dh = (0, diffie_hellman_1.getDiffieHellman)('modp16');
                break;
            default:
                throw new Error('Invalid DH bit length.');
        }
    }
    startKeyExchange() {
        const exchangeValueKeys = this.dh.generateKeys();
        const exchangeValue = bigInt_1.BigInt.fromBytes(exchangeValueKeys, { unsigned: true }).toBytes();
        return Promise.resolve(exchangeValue);
    }
    decryptKeyExchange(exchangeValue) {
        const key = this.dh.computeSecret(exchangeValue);
        const sharedSecret = bigInt_1.BigInt.fromBytes(key, { unsigned: true }).toBytes();
        return Promise.resolve(sharedSecret);
    }
    async sign(data) {
        const hashBuffer = await crypto.subtle.digest(this.hashAlgorithmName, data);
        return buffer_1.Buffer.from(hashBuffer);
    }
    dispose() { }
}
class WebECDiffieHellman extends keyExchangeAlgorithm_1.KeyExchangeAlgorithm {
    constructor(name, keySizeInBits, hashAlgorithmName) {
        super(name, keySizeInBits, hashAlgorithmName, webHmac_1.WebHmac.getHashDigestLength(hashAlgorithmName));
    }
    createKeyExchange() {
        return new WebECDiffieHellmanKex(this.keySizeInBits, webHmac_1.WebHmac.getWebHashAlgorithmName(this.hashAlgorithmName), this.hashDigestLength);
    }
}
exports.WebECDiffieHellman = WebECDiffieHellman;
class WebECDiffieHellmanKex {
    constructor(bitLength, hashAlgorithmName, digestLength) {
        this.bitLength = bitLength;
        this.hashAlgorithmName = hashAlgorithmName;
        this.digestLength = digestLength;
        this.algorithm = {
            name: 'ECDH',
            namedCurve: 'P-' + bitLength,
        };
    }
    async startKeyExchange() {
        if (!this.keyPair) {
            this.keyPair = await crypto.subtle.generateKey(this.algorithm, true, // exportable
            ['deriveBits']);
        }
        const jwk = await crypto.subtle.exportKey('jwk', this.keyPair.publicKey);
        const ec = jsonWebKeyFormatter_1.JsonWebKeyFormatter.parseEC(jwk);
        const length = Math.ceil(this.bitLength / 8);
        const publicKeyBytes = buffer_1.Buffer.alloc(1 + length * 2);
        publicKeyBytes[0] = 4;
        ec.x.toBytes({ unsigned: true, length }).copy(publicKeyBytes, 1);
        ec.y.toBytes({ unsigned: true, length }).copy(publicKeyBytes, 1 + length);
        return buffer_1.Buffer.from(publicKeyBytes);
    }
    async decryptKeyExchange(exchangeValue) {
        if (!this.keyPair) {
            throw new Error('Key exchange not started.');
        }
        const xy = exchangeValue;
        const jwk = jsonWebKeyFormatter_1.JsonWebKeyFormatter.formatEC({
            curve: { name: this.algorithm.namedCurve },
            x: bigInt_1.BigInt.fromBytes(xy.slice(1, 1 + (xy.length - 1) / 2), { unsigned: true }),
            y: bigInt_1.BigInt.fromBytes(xy.slice(1 + (xy.length - 1) / 2), { unsigned: true }),
        });
        const otherPublicKey = await crypto.subtle.importKey('jwk', jwk, this.algorithm, false, []);
        const sharedSecretBytes = buffer_1.Buffer.from(await crypto.subtle.deriveBits(Object.assign(Object.assign({}, this.algorithm), { public: otherPublicKey }), this.keyPair.privateKey, Math.ceil(this.bitLength / 8) * 8));
        const sharedSecret = bigInt_1.BigInt.fromBytes(sharedSecretBytes, { unsigned: true }).toBytes();
        return sharedSecret;
    }
    async sign(data) {
        const hashBuffer = await crypto.subtle.digest(this.hashAlgorithmName, data);
        return buffer_1.Buffer.from(hashBuffer);
    }
    dispose() { }
}
//# sourceMappingURL=https://github.com/VSCodium/sourcemaps/releases/download/stable-4c0b0c6cc561d2d3636d1ec250935431876ce4dc/node_modules-@microsoft-dev-tunnels-ssh-algorithms-web-webKeyExchange.js.map