Path: blob/master/node_modules/@adiwajshing/baileys/lib/Utils/noise-handler.js
1129 views
"use strict";1Object.defineProperty(exports, "__esModule", { value: true });2exports.makeNoiseHandler = void 0;3const boom_1 = require("@hapi/boom");4const WAProto_1 = require("../../WAProto");5const Defaults_1 = require("../Defaults");6const WABinary_1 = require("../WABinary");7const crypto_1 = require("./crypto");8const generateIV = (counter) => {9const iv = new ArrayBuffer(12);10new DataView(iv).setUint32(8, counter);11return new Uint8Array(iv);12};13const makeNoiseHandler = ({ public: publicKey, private: privateKey }, logger) => {14logger = logger.child({ class: 'ns' });15const authenticate = (data) => {16if (!isFinished) {17hash = (0, crypto_1.sha256)(Buffer.concat([hash, data]));18}19};20const encrypt = (plaintext) => {21const result = (0, crypto_1.aesEncryptGCM)(plaintext, encKey, generateIV(writeCounter), hash);22writeCounter += 1;23authenticate(result);24return result;25};26const decrypt = (ciphertext) => {27// before the handshake is finished, we use the same counter28// after handshake, the counters are different29const iv = generateIV(isFinished ? readCounter : writeCounter);30const result = (0, crypto_1.aesDecryptGCM)(ciphertext, decKey, iv, hash);31if (isFinished) {32readCounter += 1;33}34else {35writeCounter += 1;36}37authenticate(ciphertext);38return result;39};40const localHKDF = (data) => {41const key = (0, crypto_1.hkdf)(Buffer.from(data), 64, { salt, info: '' });42return [key.slice(0, 32), key.slice(32)];43};44const mixIntoKey = (data) => {45const [write, read] = localHKDF(data);46salt = write;47encKey = read;48decKey = read;49readCounter = 0;50writeCounter = 0;51};52const finishInit = () => {53const [write, read] = localHKDF(new Uint8Array(0));54encKey = write;55decKey = read;56hash = Buffer.from([]);57readCounter = 0;58writeCounter = 0;59isFinished = true;60};61const data = Buffer.from(Defaults_1.NOISE_MODE);62let hash = Buffer.from(data.byteLength === 32 ? data : (0, crypto_1.sha256)(Buffer.from(data)));63let salt = hash;64let encKey = hash;65let decKey = hash;66let readCounter = 0;67let writeCounter = 0;68let isFinished = false;69let sentIntro = false;70let inBytes = Buffer.alloc(0);71authenticate(Defaults_1.NOISE_WA_HEADER);72authenticate(publicKey);73return {74encrypt,75decrypt,76authenticate,77mixIntoKey,78finishInit,79processHandshake: ({ serverHello }, noiseKey) => {80authenticate(serverHello.ephemeral);81mixIntoKey(crypto_1.Curve.sharedKey(privateKey, serverHello.ephemeral));82const decStaticContent = decrypt(serverHello.static);83mixIntoKey(crypto_1.Curve.sharedKey(privateKey, decStaticContent));84const certDecoded = decrypt(serverHello.payload);85const { intermediate: certIntermediate } = WAProto_1.proto.CertChain.decode(certDecoded);86const { issuerSerial } = WAProto_1.proto.CertChain.NoiseCertificate.Details.decode(certIntermediate.details);87if (issuerSerial !== Defaults_1.WA_CERT_DETAILS.SERIAL) {88throw new boom_1.Boom('certification match failed', { statusCode: 400 });89}90const keyEnc = encrypt(noiseKey.public);91mixIntoKey(crypto_1.Curve.sharedKey(noiseKey.private, serverHello.ephemeral));92return keyEnc;93},94encodeFrame: (data) => {95if (isFinished) {96data = encrypt(data);97}98const introSize = sentIntro ? 0 : Defaults_1.NOISE_WA_HEADER.length;99const frame = Buffer.alloc(introSize + 3 + data.byteLength);100if (!sentIntro) {101frame.set(Defaults_1.NOISE_WA_HEADER);102sentIntro = true;103}104frame.writeUInt8(data.byteLength >> 16, introSize);105frame.writeUInt16BE(65535 & data.byteLength, introSize + 1);106frame.set(data, introSize + 3);107return frame;108},109decodeFrame: (newData, onFrame) => {110var _a;111// the binary protocol uses its own framing mechanism112// on top of the WS frames113// so we get this data and separate out the frames114const getBytesSize = () => {115if (inBytes.length >= 3) {116return (inBytes.readUInt8() << 16) | inBytes.readUInt16BE(1);117}118};119inBytes = Buffer.concat([inBytes, newData]);120logger.trace(`recv ${newData.length} bytes, total recv ${inBytes.length} bytes`);121let size = getBytesSize();122while (size && inBytes.length >= size + 3) {123let frame = inBytes.slice(3, size + 3);124inBytes = inBytes.slice(size + 3);125if (isFinished) {126const result = decrypt(frame);127frame = (0, WABinary_1.decodeBinaryNode)(result);128}129logger.trace({ msg: (_a = frame === null || frame === void 0 ? void 0 : frame.attrs) === null || _a === void 0 ? void 0 : _a.id }, 'recv frame');130onFrame(frame);131size = getBytesSize();132}133}134};135};136exports.makeNoiseHandler = makeNoiseHandler;137138139