@gqb333/based 2.7.79 → 2.7.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/lib/Utils/crypto.js +198 -81
  2. package/package.json +1 -1
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
+
2
3
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
4
  if (k2 === undefined) k2 = k;
4
5
  var desc = Object.getOwnPropertyDescriptor(m, k);
5
6
  if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
8
  }
8
9
  Object.defineProperty(o, k2, desc);
9
10
  }) : (function(o, m, k, k2) {
@@ -32,162 +33,278 @@ var __importStar = (this && this.__importStar) || (function () {
32
33
  return result;
33
34
  };
34
35
  })();
36
+
35
37
  Object.defineProperty(exports, "__esModule", { value: true });
36
38
  exports.signedKeyPair = exports.Curve = exports.generateSignalPubKey = void 0;
37
- exports.aesEncryptGCM = aesEncryptGCM;
38
- exports.aesDecryptGCM = aesDecryptGCM;
39
- exports.aesEncryptCTR = aesEncryptCTR;
40
- exports.aesDecryptCTR = aesDecryptCTR;
41
- exports.aesDecrypt = aesDecrypt;
39
+ exports.aesEncryptGCM = aesEncryptGCM;
40
+ exports.aesDecryptGCM = aesDecryptGCM;
41
+ exports.aesEncryptCTR = aesEncryptCTR;
42
+ exports.aesDecryptCTR = aesDecryptCTR;
43
+ exports.aesDecrypt = aesDecrypt;
42
44
  exports.aesDecryptWithIV = aesDecryptWithIV;
43
- exports.aesEncrypt = aesEncrypt;
44
- exports.aesEncrypWithIV = aesEncrypWithIV;
45
- exports.hmacSign = hmacSign;
46
- exports.sha256 = sha256;
47
- exports.md5 = md5;
48
- exports.hkdf = hkdf;
45
+ exports.aesEncrypt = aesEncrypt;
46
+ exports.aesEncrypWithIV = aesEncrypWithIV;
47
+ exports.hmacSign = hmacSign;
48
+ exports.sha256 = sha256;
49
+ exports.sha512 = sha512;
50
+ exports.md5 = md5;
51
+ exports.hkdf = hkdf;
49
52
  exports.derivePairingCodeKey = derivePairingCodeKey;
50
- const crypto_1 = require("crypto");
51
- const libsignal = __importStar(require("libsignal"));
53
+ exports.randomBytes = safeRandomBytes;
54
+ exports.timingSafeEqual = timingSafeEqual;
55
+
56
+ const crypto_1 = require("crypto");
57
+ const libsignal = __importStar(require("libsignal"));
52
58
  const Defaults_1 = require("../Defaults");
53
- // insure browser & node compatibility
59
+
60
+ // ─── Costanti ────────────────────────────────────────────────────────────────
61
+
62
+ const GCM_TAG_LENGTH = 16; // 128 bit
63
+ const IV_LENGTH = 16; // 128 bit
64
+ const AES_KEY_LENGTH = 32; // 256 bit
65
+ const PBKDF2_ITER = 2 << 16; // 131.072 iterazioni
66
+
54
67
  const { subtle } = globalThis.crypto;
55
- /** prefix version byte to the pub keys, required for some curve crypto functions */
56
- const generateSignalPubKey = (pubKey) => (pubKey.length === 33
57
- ? pubKey
58
- : Buffer.concat([Defaults_1.KEY_BUNDLE_TYPE, pubKey]));
68
+
69
+ // ─── Helpers interni ─────────────────────────────────────────────────────────
70
+
71
+ /** Genera bytes casuali sicuri */
72
+ function safeRandomBytes(size) {
73
+ if (!Number.isInteger(size) || size <= 0) throw new TypeError(`randomBytes: size non valida (${size})`);
74
+ return (0, crypto_1.randomBytes)(size);
75
+ }
76
+
77
+ /** Confronto a tempo costante per prevenire timing attacks */
78
+ function timingSafeEqual(a, b) {
79
+ if (!Buffer.isBuffer(a)) a = Buffer.from(a);
80
+ if (!Buffer.isBuffer(b)) b = Buffer.from(b);
81
+ if (a.length !== b.length) return false;
82
+ return (0, crypto_1.timingSafeEqual)(a, b);
83
+ }
84
+
85
+ /** Valida che una chiave AES sia della lunghezza corretta */
86
+ function validateAESKey(key) {
87
+ if (!key || key.length !== AES_KEY_LENGTH) {
88
+ throw new RangeError(`Chiave AES non valida: attesi ${AES_KEY_LENGTH} byte, ricevuti ${key?.length ?? 0}`);
89
+ }
90
+ }
91
+
92
+ /** Valida che un IV sia della lunghezza corretta */
93
+ function validateIV(iv, expected = IV_LENGTH) {
94
+ if (!iv || iv.length !== expected) {
95
+ throw new RangeError(`IV non valido: attesi ${expected} byte, ricevuti ${iv?.length ?? 0}`);
96
+ }
97
+ }
98
+
99
+ // ─── Signal / Curve ──────────────────────────────────────────────────────────
100
+
101
+ /**
102
+ * Aggiunge il byte di versione alla chiave pubblica Signal se mancante
103
+ */
104
+ const generateSignalPubKey = (pubKey) => (
105
+ pubKey.length === 33
106
+ ? pubKey
107
+ : Buffer.concat([Defaults_1.KEY_BUNDLE_TYPE, pubKey])
108
+ );
59
109
  exports.generateSignalPubKey = generateSignalPubKey;
110
+
60
111
  exports.Curve = {
61
112
  generateKeyPair: () => {
62
113
  const { pubKey, privKey } = libsignal.curve.generateKeyPair();
63
114
  return {
64
115
  private: Buffer.from(privKey),
65
- // remove version byte
66
- public: Buffer.from(pubKey.slice(1))
116
+ public: Buffer.from(pubKey.slice(1)) // rimuove byte versione
67
117
  };
68
118
  },
119
+
69
120
  sharedKey: (privateKey, publicKey) => {
70
- const shared = libsignal.curve.calculateAgreement((0, exports.generateSignalPubKey)(publicKey), privateKey);
121
+ const shared = libsignal.curve.calculateAgreement(
122
+ generateSignalPubKey(publicKey),
123
+ privateKey
124
+ );
71
125
  return Buffer.from(shared);
72
126
  },
73
- sign: (privateKey, buf) => (libsignal.curve.calculateSignature(privateKey, buf)),
127
+
128
+ sign: (privateKey, buf) => (
129
+ libsignal.curve.calculateSignature(privateKey, buf)
130
+ ),
131
+
74
132
  verify: (pubKey, message, signature) => {
75
133
  try {
76
- libsignal.curve.verifySignature((0, exports.generateSignalPubKey)(pubKey), message, signature);
134
+ libsignal.curve.verifySignature(generateSignalPubKey(pubKey), message, signature);
77
135
  return true;
78
- }
79
- catch (error) {
136
+ } catch {
80
137
  return false;
81
138
  }
82
139
  }
83
140
  };
141
+
84
142
  const signedKeyPair = (identityKeyPair, keyId) => {
85
- const preKey = exports.Curve.generateKeyPair();
86
- const pubKey = (0, exports.generateSignalPubKey)(preKey.public);
143
+ const preKey = exports.Curve.generateKeyPair();
144
+ const pubKey = generateSignalPubKey(preKey.public);
87
145
  const signature = exports.Curve.sign(identityKeyPair.private, pubKey);
88
146
  return { keyPair: preKey, signature, keyId };
89
147
  };
90
148
  exports.signedKeyPair = signedKeyPair;
91
- const GCM_TAG_LENGTH = 128 >> 3;
149
+
150
+ // ─── AES-256-GCM ─────────────────────────────────────────────────────────────
151
+
92
152
  /**
93
- * encrypt AES 256 GCM;
94
- * where the tag tag is suffixed to the ciphertext
95
- * */
153
+ * Cifra con AES-256-GCM.
154
+ * L'auth tag (16 byte) è suffisso al ciphertext.
155
+ */
96
156
  function aesEncryptGCM(plaintext, key, iv, additionalData) {
157
+ validateAESKey(key);
97
158
  const cipher = (0, crypto_1.createCipheriv)('aes-256-gcm', key, iv);
98
- cipher.setAAD(additionalData);
99
- return Buffer.concat([cipher.update(plaintext), cipher.final(), cipher.getAuthTag()]);
159
+ if (additionalData) cipher.setAAD(additionalData);
160
+ const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()]);
161
+ return Buffer.concat([encrypted, cipher.getAuthTag()]);
100
162
  }
163
+
101
164
  /**
102
- * decrypt AES 256 GCM;
103
- * where the auth tag is suffixed to the ciphertext
104
- * */
165
+ * Decifra con AES-256-GCM.
166
+ * L'auth tag (16 byte) è suffisso al ciphertext.
167
+ */
105
168
  function aesDecryptGCM(ciphertext, key, iv, additionalData) {
169
+ validateAESKey(key);
170
+ if (ciphertext.length < GCM_TAG_LENGTH) throw new RangeError('Ciphertext GCM troppo corto');
106
171
  const decipher = (0, crypto_1.createDecipheriv)('aes-256-gcm', key, iv);
107
- // decrypt additional adata
108
172
  const enc = ciphertext.slice(0, ciphertext.length - GCM_TAG_LENGTH);
109
173
  const tag = ciphertext.slice(ciphertext.length - GCM_TAG_LENGTH);
110
- // set additional data
111
- decipher.setAAD(additionalData);
174
+ if (additionalData) decipher.setAAD(additionalData);
112
175
  decipher.setAuthTag(tag);
113
176
  return Buffer.concat([decipher.update(enc), decipher.final()]);
114
177
  }
178
+
179
+ // ─── AES-256-CTR ─────────────────────────────────────────────────────────────
180
+
115
181
  function aesEncryptCTR(plaintext, key, iv) {
182
+ validateAESKey(key);
116
183
  const cipher = (0, crypto_1.createCipheriv)('aes-256-ctr', key, iv);
117
184
  return Buffer.concat([cipher.update(plaintext), cipher.final()]);
118
185
  }
186
+
119
187
  function aesDecryptCTR(ciphertext, key, iv) {
188
+ validateAESKey(key);
120
189
  const decipher = (0, crypto_1.createDecipheriv)('aes-256-ctr', key, iv);
121
190
  return Buffer.concat([decipher.update(ciphertext), decipher.final()]);
122
191
  }
123
- /** decrypt AES 256 CBC; where the IV is prefixed to the buffer */
192
+
193
+ // ─── AES-256-CBC ─────────────────────────────────────────────────────────────
194
+
195
+ /**
196
+ * Decifra AES-256-CBC dove l'IV (16 byte) è prefisso al buffer.
197
+ */
124
198
  function aesDecrypt(buffer, key) {
125
- return aesDecryptWithIV(buffer.slice(16, buffer.length), key, buffer.slice(0, 16));
199
+ if (buffer.length < IV_LENGTH) throw new RangeError('Buffer CBC troppo corto per contenere IV');
200
+ return aesDecryptWithIV(
201
+ buffer.slice(IV_LENGTH),
202
+ key,
203
+ buffer.slice(0, IV_LENGTH)
204
+ );
126
205
  }
127
- /** decrypt AES 256 CBC */
206
+
207
+ /** Decifra AES-256-CBC con IV esplicito */
128
208
  function aesDecryptWithIV(buffer, key, IV) {
209
+ validateAESKey(key);
210
+ validateIV(IV);
129
211
  const aes = (0, crypto_1.createDecipheriv)('aes-256-cbc', key, IV);
130
212
  return Buffer.concat([aes.update(buffer), aes.final()]);
131
213
  }
132
- // encrypt AES 256 CBC; where a random IV is prefixed to the buffer
214
+
215
+ /**
216
+ * Cifra AES-256-CBC con IV casuale (prefissato al risultato).
217
+ */
133
218
  function aesEncrypt(buffer, key) {
134
- const IV = (0, crypto_1.randomBytes)(16);
219
+ validateAESKey(key);
220
+ const IV = safeRandomBytes(IV_LENGTH);
135
221
  const aes = (0, crypto_1.createCipheriv)('aes-256-cbc', key, IV);
136
- return Buffer.concat([IV, aes.update(buffer), aes.final()]); // prefix IV to the buffer
222
+ return Buffer.concat([IV, aes.update(buffer), aes.final()]);
137
223
  }
138
- // encrypt AES 256 CBC with a given IV
224
+
225
+ /** Cifra AES-256-CBC con IV esplicito */
139
226
  function aesEncrypWithIV(buffer, key, IV) {
227
+ validateAESKey(key);
228
+ validateIV(IV);
140
229
  const aes = (0, crypto_1.createCipheriv)('aes-256-cbc', key, IV);
141
- return Buffer.concat([aes.update(buffer), aes.final()]); // prefix IV to the buffer
230
+ return Buffer.concat([aes.update(buffer), aes.final()]);
142
231
  }
143
- // sign HMAC using SHA 256
232
+
233
+ // ─── Hash / HMAC ─────────────────────────────────────────────────────────────
234
+
235
+ /** HMAC-SHA256 (o altra variante) */
144
236
  function hmacSign(buffer, key, variant = 'sha256') {
145
237
  return (0, crypto_1.createHmac)(variant, key).update(buffer).digest();
146
238
  }
239
+
240
+ /** SHA-256 */
147
241
  function sha256(buffer) {
148
242
  return (0, crypto_1.createHash)('sha256').update(buffer).digest();
149
243
  }
244
+
245
+ /** SHA-512 (aggiunto per completezza) */
246
+ function sha512(buffer) {
247
+ return (0, crypto_1.createHash)('sha512').update(buffer).digest();
248
+ }
249
+
250
+ /** MD5 — usare solo dove strettamente necessario (non per sicurezza) */
150
251
  function md5(buffer) {
151
252
  return (0, crypto_1.createHash)('md5').update(buffer).digest();
152
253
  }
153
- // HKDF key expansion
254
+
255
+ // ─── KDF ─────────────────────────────────────────────────────────────────────
256
+
257
+ /**
258
+ * HKDF (RFC 5869) tramite Web Crypto API.
259
+ * @param {Buffer|Uint8Array} buffer - Input Key Material
260
+ * @param {number} expandedLength - Byte da derivare
261
+ * @param {{ salt?: Buffer, info?: string }} info
262
+ */
154
263
  async function hkdf(buffer, expandedLength, info) {
155
- // Ensure we have a Uint8Array for the key material
156
- const inputKeyMaterial = buffer instanceof Uint8Array
157
- ? buffer
158
- : new Uint8Array(buffer);
159
- // Set default values if not provided
160
- const salt = info.salt ? new Uint8Array(info.salt) : new Uint8Array(0);
161
- const infoBytes = info.info
162
- ? new TextEncoder().encode(info.info)
163
- : new Uint8Array(0);
164
- // Import the input key material
165
- const importedKey = await subtle.importKey('raw', inputKeyMaterial, { name: 'HKDF' }, false, ['deriveBits']);
166
- // Derive bits using HKDF
167
- const derivedBits = await subtle.deriveBits({
168
- name: 'HKDF',
169
- hash: 'SHA-256',
170
- salt: salt,
171
- info: infoBytes
172
- }, importedKey, expandedLength * 8 // Convert bytes to bits
264
+ if (expandedLength <= 0) throw new RangeError('expandedLength deve essere > 0');
265
+
266
+ const inputKeyMaterial = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
267
+ const salt = info.salt ? new Uint8Array(info.salt) : new Uint8Array(0);
268
+ const infoBytes = info.info ? new TextEncoder().encode(info.info) : new Uint8Array(0);
269
+
270
+ const importedKey = await subtle.importKey(
271
+ 'raw', inputKeyMaterial,
272
+ { name: 'HKDF' },
273
+ false, ['deriveBits']
274
+ );
275
+
276
+ const derivedBits = await subtle.deriveBits(
277
+ { name: 'HKDF', hash: 'SHA-256', salt, info: infoBytes },
278
+ importedKey,
279
+ expandedLength * 8
173
280
  );
281
+
174
282
  return Buffer.from(derivedBits);
175
283
  }
284
+
285
+ /**
286
+ * Deriva una chiave dal pairing code tramite PBKDF2.
287
+ * @param {string} pairingCode
288
+ * @param {Buffer|Uint8Array} salt
289
+ */
176
290
  async function derivePairingCodeKey(pairingCode, salt) {
177
- // Convert inputs to formats Web Crypto API can work with
178
- const encoder = new TextEncoder();
179
- const pairingCodeBuffer = encoder.encode(pairingCode);
291
+ if (!pairingCode || typeof pairingCode !== 'string') throw new TypeError('pairingCode deve essere una stringa');
292
+
293
+ const encoder = new TextEncoder();
294
+ const codeBuffer = encoder.encode(pairingCode);
180
295
  const saltBuffer = salt instanceof Uint8Array ? salt : new Uint8Array(salt);
181
- // Import the pairing code as key material
182
- const keyMaterial = await subtle.importKey('raw', pairingCodeBuffer, { name: 'PBKDF2' }, false, ['deriveBits']);
183
- // Derive bits using PBKDF2 with the same parameters
184
- // 2 << 16 = 131,072 iterations
185
- const derivedBits = await subtle.deriveBits({
186
- name: 'PBKDF2',
187
- salt: saltBuffer,
188
- iterations: 2 << 16,
189
- hash: 'SHA-256'
190
- }, keyMaterial, 32 * 8 // 32 bytes * 8 = 256 bits
296
+
297
+ const keyMaterial = await subtle.importKey(
298
+ 'raw', codeBuffer,
299
+ { name: 'PBKDF2' },
300
+ false, ['deriveBits']
301
+ );
302
+
303
+ const derivedBits = await subtle.deriveBits(
304
+ { name: 'PBKDF2', salt: saltBuffer, iterations: PBKDF2_ITER, hash: 'SHA-256' },
305
+ keyMaterial,
306
+ 256 // 32 byte
191
307
  );
308
+
192
309
  return Buffer.from(derivedBits);
193
310
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gqb333/based",
3
- "version": "2.7.79",
3
+ "version": "2.7.80",
4
4
  "description": "Whatsapp api by GabWT333",
5
5
  "keywords": [
6
6
  "baileys",