whalibmob 5.33.28 → 5.33.29

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.
@@ -1593,6 +1593,16 @@ function toBase64Url(buf) {
1593
1593
  return buf.toString('base64').replace(/\+/g, '-').replace(/\//g, '_');
1594
1594
  }
1595
1595
 
1596
+ // The native client encodes the Signal-key and expid wire parameters with
1597
+ // Base64.encodeToString(bytes, 11) = URL_SAFE | NO_WRAP | NO_PADDING: authkey
1598
+ // (43 chars), e_ident/e_skey_val (43), e_skey_sig (86), e_regid (6), e_keytype,
1599
+ // e_skey_id (4), expid (22) — never a trailing '='. The padded form still
1600
+ // decodes server-side, but the bare '=' is a wire tell no real device emits.
1601
+ // The ENC envelope and the vname certificate keep their own encoder above.
1602
+ function toBase64UrlNoPad(buf) {
1603
+ return toBase64Url(buf).replace(/=+$/, '');
1604
+ }
1605
+
1596
1606
  // ---------- vname: the Business verified-name certificate ----------
1597
1607
  //
1598
1608
  // A Business registration carries one extra form field, `vname`, and a consumer
@@ -1712,18 +1722,18 @@ async function buildPayload(store, waVersion, useToken, extraPairs, path) {
1712
1722
  'rc', String(RELEASE_CHANNEL),
1713
1723
  'lg', meta.lg,
1714
1724
  'lc', meta.lc,
1715
- 'authkey', toBase64Url(stripKeyPrefix(store.noiseKeyPair.public)),
1725
+ 'authkey', toBase64UrlNoPad(stripKeyPrefix(store.noiseKeyPair.public)),
1716
1726
  // Business only; buildForm drops a null, so a consumer registration sends
1717
1727
  // the same body it always has.
1718
1728
  'vname', buildVerifiedNameCertificate(store, device),
1719
- 'e_regid', toBase64Url(intToBytes(store.registrationId, 4)),
1720
- 'e_keytype', toBase64Url(Buffer.from([SIGNAL_KEY_TYPE])),
1721
- 'e_ident', toBase64Url(stripKeyPrefix(store.identityKeyPair.public)),
1722
- 'e_skey_id', toBase64Url(intToBytes(store.signedPreKey.id, 3)),
1723
- 'e_skey_val', toBase64Url(stripKeyPrefix(store.signedPreKey.public)),
1724
- 'e_skey_sig', toBase64Url(store.signedPreKey.signature),
1729
+ 'e_regid', toBase64UrlNoPad(intToBytes(store.registrationId, 4)),
1730
+ 'e_keytype', toBase64UrlNoPad(Buffer.from([SIGNAL_KEY_TYPE])),
1731
+ 'e_ident', toBase64UrlNoPad(stripKeyPrefix(store.identityKeyPair.public)),
1732
+ 'e_skey_id', toBase64UrlNoPad(intToBytes(store.signedPreKey.id, 3)),
1733
+ 'e_skey_val', toBase64UrlNoPad(stripKeyPrefix(store.signedPreKey.public)),
1734
+ 'e_skey_sig', toBase64UrlNoPad(store.signedPreKey.signature),
1725
1735
  'fdid', fdid,
1726
- 'expid', toBase64Url(store.deviceId),
1736
+ 'expid', toBase64UrlNoPad(store.deviceId),
1727
1737
  'id', toUrlHex(store.identityId),
1728
1738
  'access_session_id', getAccessSessionId(store),
1729
1739
  'token', token,
@@ -1920,7 +1930,7 @@ async function sendFunnelLog(store, waVersion, currentScreen, actionTaken, event
1920
1930
  'in', national,
1921
1931
  'lg', 'en',
1922
1932
  'lc', 'US',
1923
- 'expid', toBase64Url(store.deviceId),
1933
+ 'expid', toBase64UrlNoPad(store.deviceId),
1924
1934
  'fdid', fdid,
1925
1935
  'id', toUrlHex(store.identityId),
1926
1936
  'current_screen', currentScreen,
@@ -1952,7 +1962,7 @@ async function sendPrePnFunnelLog(store, waVersion, actionTaken, eventName) {
1952
1962
  const body = buildForm([
1953
1963
  'lg', 'en',
1954
1964
  'lc', 'US',
1955
- 'expid', toBase64Url(store.deviceId),
1965
+ 'expid', toBase64UrlNoPad(store.deviceId),
1956
1966
  'fdid', fdid,
1957
1967
  'id', toUrlHex(store.identityId),
1958
1968
  'current_screen', 'enter_number',
package/lib/Store.js CHANGED
@@ -82,7 +82,11 @@ function createNewStore(phoneNumber, opts) {
82
82
 
83
83
  const registrationId = (crypto.randomBytes(2).readUInt16BE(0) & 0x3fff) + 1;
84
84
  const fdid = uuidv4();
85
- const deviceId = crypto.randomBytes(16);
85
+ // expid goes on the wire as a UUID and WhatsApp reads its version/variant
86
+ // nibbles (the native client builds it with UUID.nameUUIDFromBytes/randomUUID).
87
+ // 16 fully random bytes land on a valid UUID shape only ~1 time in 16, so the
88
+ // server sees a malformed UUID; take the 16 bytes of a real v4 UUID instead.
89
+ const deviceId = Buffer.from(uuidv4().replace(/-/g, ''), 'hex');
86
90
  const identityId = crypto.randomBytes(16);
87
91
  // Device fingerprint fields the native client sends on /code (see
88
92
  // Registration.js): advertising id (UUID) and the 20-byte backup token.
@@ -358,7 +362,8 @@ function fromSixParts(sixParts) {
358
362
  },
359
363
  registrationId: (crypto.randomBytes(2).readUInt16BE(0) & 0x3fff) + 1,
360
364
  fdid: uuidv4(),
361
- deviceId: crypto.randomBytes(16),
365
+ // expid must be a valid UUID on the wire — see createNewStore above.
366
+ deviceId: Buffer.from(uuidv4().replace(/-/g, ''), 'hex'),
362
367
  identityId,
363
368
  advertisingId: uuidv4(),
364
369
  backupToken: crypto.randomBytes(20),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whalibmob",
3
- "version": "5.33.28",
3
+ "version": "5.33.29",
4
4
  "description": "Node.js library for WhatsApp — register a number over SMS, or link as a companion by QR. Signal E2E encryption, media, groups, channels.",
5
5
  "author": "Kunboruto20",
6
6
  "main": "index.js",