UNPKG

@microsoft/dev-tunnels-ssh

Version:
110 lines 5.2 kB
"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=webKeyExchange.js.map