UNPKG

wailey-whatsapp-lib

Version:

A robust WhatsApp library for Node.js with support for QR code and pairing code authentication

238 lines (208 loc) 6.58 kB
/** * Wailey-library Cryptography Utilities * (Implementare reală a funcțiilor criptografice pentru WhatsApp) */ const { createCipheriv, createDecipheriv, createHmac, randomBytes } = require('crypto'); const hkdf = require('futoin-hkdf'); // WhatsApp cryptography constants const INFO_KEYS = { auth: 'WhatsApp Encrypted Media Auth Key', media: 'WhatsApp Encrypted Media Keys', noise: 'Noise_XX_25519_AESGCM_SHA256\0\0\0\0' }; /** * Generate an HMAC signature * @param {Buffer} key - HMAC key * @param {Buffer} data - Data to sign * @param {string} algorithm - HMAC algorithm * @returns {Buffer} - HMAC signature */ function hmacSign(key, data, algorithm = 'sha256') { return createHmac(algorithm, key).update(data).digest(); } /** * Derive HKDF keys * @param {Buffer} key - Input key material * @param {number} length - Output key length * @param {Object} options - HKDF options (salt, info) * @returns {Buffer} - Derived key */ function hkdfExpand(key, length, options = {}) { const keyInfo = options.info || INFO_KEYS.media; const salt = options.salt || Buffer.alloc(0); return hkdf(key, length, { info: keyInfo, salt, hash: 'sha256' }); } /** * Encrypt data with AES-CBC * @param {Buffer} key - Encryption key * @param {Buffer} data - Data to encrypt * @param {Buffer} iv - Initialization vector * @returns {Buffer} - Encrypted data */ function aesEncrypt(key, data, iv) { const cipher = createCipheriv('aes-256-cbc', key, iv); return Buffer.concat([cipher.update(data), cipher.final()]); } /** * Decrypt data with AES-CBC * @param {Buffer} key - Decryption key * @param {Buffer} data - Data to decrypt * @param {Buffer} iv - Initialization vector * @returns {Buffer} - Decrypted data */ function aesDecrypt(key, data, iv) { const decipher = createDecipheriv('aes-256-cbc', key, iv); return Buffer.concat([decipher.update(data), decipher.final()]); } /** * Generate a random key * @param {number} length - Key length in bytes * @returns {Buffer} - Random key */ function generateRandomKey(length = 32) { return randomBytes(length); } /** * Generate an initialization vector * @param {number} length - IV length in bytes * @returns {Buffer} - Random IV */ function generateIV(length = 16) { return randomBytes(length); } /** * Generate key pair for Signal Protocol * @returns {Object} - Key pair (publicKey, privateKey) */ function generateSignalKeyPair() { // In a real implementation, this would use libsignal-protocol or Curve25519 // For now, we'll simulate with a simple placeholder return { publicKey: randomBytes(32), privateKey: randomBytes(32) }; } /** * Encrypt media (images, audio, etc.) * @param {Buffer} mediaData - Media content * @param {Buffer} mediaKey - Media encryption key * @returns {Object} - Encrypted media and details */ function encryptMedia(mediaData, mediaKey) { // Generate IV const iv = generateIV(); // Derive keys using HKDF const expandedMediaKey = hkdfExpand(mediaKey, 112, { info: INFO_KEYS.media }); // Extract keys const encKey = expandedMediaKey.slice(0, 32); const macKey = expandedMediaKey.slice(32, 64); // Encrypt the media const encryptedMedia = aesEncrypt(encKey, mediaData, iv); // Generate HMAC const hmac = hmacSign(macKey, Buffer.concat([iv, encryptedMedia])); return { encryptedMedia, iv, mediaKey, hmac }; } /** * Decrypt media (images, audio, etc.) * @param {Buffer} encryptedMedia - Encrypted media content * @param {Buffer} mediaKey - Media decryption key * @param {Buffer} iv - Initialization vector * @param {Buffer} hmac - HMAC signature for verification * @returns {Buffer} - Decrypted media */ function decryptMedia(encryptedMedia, mediaKey, iv, hmac) { // Derive keys using HKDF const expandedMediaKey = hkdfExpand(mediaKey, 112, { info: INFO_KEYS.media }); // Extract keys const encKey = expandedMediaKey.slice(0, 32); const macKey = expandedMediaKey.slice(32, 64); // Verify HMAC const computedHmac = hmacSign(macKey, Buffer.concat([iv, encryptedMedia])); if (!hmac.equals(computedHmac)) { throw new Error('Invalid media HMAC'); } // Decrypt the media return aesDecrypt(encKey, encryptedMedia, iv); } /** * Generate a secure signaling key * @returns {Buffer} - Signaling key */ function generateSignalingKey() { return randomBytes(32); } /** * Generate identity keys for Signal Protocol * @returns {Object} - Identity keys */ function generateIdentityKeys() { return { identityKeyPair: generateSignalKeyPair(), signedPreKey: generateSignalKeyPair(), registrationId: Math.floor(Math.random() * 16383) + 1 }; } /** * Implements the Noise protocol crypto operations * @param {Object} options - Noise protocol options * @returns {Object} - Noise handler */ function makeNoiseHandler(options = {}) { // In a real implementation, this would implement Noise_XX_25519_AESGCM_SHA256 // For now, we'll create a simulated placeholder const keyPair = generateSignalKeyPair(); return { // Initialize a Noise handshake init: () => { return { ephemeralKeyPair: generateSignalKeyPair(), staticKeyPair: keyPair }; }, // Process a handshake message processHandshake: (state, message) => { // Simulate handshake processing return { ...state, handshakeComplete: true }; }, // Encrypt a message encrypt: (state, plaintext) => { // Simulate encryption const iv = generateIV(); const encKey = randomBytes(32); return { ciphertext: aesEncrypt(encKey, plaintext, iv), iv }; }, // Decrypt a message decrypt: (state, ciphertext, iv) => { // Simulate decryption const decKey = randomBytes(32); return aesDecrypt(decKey, ciphertext, iv); } }; } // Export all cryptographic functions module.exports = { hmacSign, hkdfExpand, aesEncrypt, aesDecrypt, generateRandomKey, generateIV, generateSignalKeyPair, encryptMedia, decryptMedia, generateSignalingKey, generateIdentityKeys, makeNoiseHandler, INFO_KEYS };