nodejs-insta-private-api-mqt 1.3.81 → 1.3.83

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.
@@ -45,55 +45,11 @@ class AccountRepository extends Repository {
45
45
  }
46
46
  }
47
47
 
48
- // 1) Check response headers first (server may set IG-Set-Authorization)
49
- const headerCandidates = [
50
- headers['ig-set-authorization'],
51
- headers['ig-set-authorization'.toLowerCase()],
52
- headers['ig-set-authorization'.toUpperCase()],
53
- headers['ig-set-authorization'],
54
- headers['ig-set-authorization'],
55
- headers['ig-set-authorization'],
56
- headers['ig-set-authorization'],
57
- headers['ig-set-authorization'],
58
- headers['ig-set-authorization'],
59
- headers['ig-set-authorization'],
60
- headers['ig-set-authorization'],
61
- headers['ig-set-authorization'],
62
- headers['ig-set-authorization'],
63
- headers['ig-set-authorization'],
64
- headers['ig-set-authorization'],
65
- headers['ig-set-authorization'],
66
- headers['ig-set-authorization'],
67
- headers['ig-set-authorization'],
68
- headers['ig-set-authorization'],
69
- headers['ig-set-authorization'],
70
- headers['ig-set-authorization'],
71
- headers['ig-set-authorization'],
72
- headers['ig-set-authorization'],
73
- headers['ig-set-authorization'],
74
- headers['ig-set-authorization'],
75
- headers['ig-set-authorization'],
76
- headers['ig-set-authorization'],
77
- headers['ig-set-authorization'],
78
- headers['ig-set-authorization'],
79
- headers['ig-set-authorization'],
80
- headers['ig-set-authorization'],
81
- headers['ig-set-authorization'],
82
- headers['ig-set-authorization'],
83
- headers['ig-set-authorization'],
84
- headers['ig-set-authorization'],
85
- headers['ig-set-authorization'],
86
- headers['ig-set-authorization'],
87
- headers['ig-set-authorization'],
88
- headers['ig-set-authorization'],
89
- headers['ig-set-authorization'],
90
- ]; // (we'll just check the normalized header below)
91
-
92
- // Simpler: look for any header that contains 'IG-Set-Authorization' or 'ig-set-authorization'
48
+ // Simpler: look for any header that contains ig-set-authorization
93
49
  for (const key of Object.keys(headers)) {
94
50
  const val = headers[key];
95
51
  if (!val) continue;
96
- if (key.includes('ig-set-authorization') || key === 'ig-set-authorization' || key === 'ig-set-authorization'.toLowerCase()) {
52
+ if (key.includes('ig-set-authorization')) {
97
53
  const token = this._normalizeTokenString(val);
98
54
  if (token) {
99
55
  this.client.state.authorization = token;
@@ -297,7 +253,7 @@ class AccountRepository extends Repository {
297
253
  const bearerPatterns = [
298
254
  /Bearer IGT:2:[A-Za-z0-9+\/=]+/,
299
255
  /Bearer\s+IGT:2:[A-Za-z0-9+\/=]+/,
300
- /\\?"Bearer IGT:2:([A-Za-z0-9+\/=]+)\\?"/,
256
+ /\?"Bearer IGT:2:([A-Za-z0-9+\/=]+)\?"/,
301
257
  /ig-set-authorization[\\"\s:]*Bearer IGT:2:([A-Za-z0-9+\/=]+)/i,
302
258
  /"IG-Set-Authorization"\s*:\s*"(Bearer IGT:2:[A-Za-z0-9+\/=]+)"/i,
303
259
  /IG-Set-Authorization[\s:]+(Bearer IGT:2:[A-Za-z0-9+\/=]+)/i,
@@ -310,10 +266,10 @@ class AccountRepository extends Repository {
310
266
  // If capturing group present, prefer it
311
267
  if (m[1]) {
312
268
  const token = m[1].includes('Bearer IGT:2:') ? m[1] : `Bearer IGT:2:${m[1]}`;
313
- return token.replace(/\\?"/g, '').trim();
269
+ return token.replace(/\?"/g, '').trim();
314
270
  }
315
271
  // Otherwise m[0] contains the full token
316
- return m[0].replace(/\\?"/g, '').trim();
272
+ return m[0].replace(/\?"/g, '').trim();
317
273
  }
318
274
  }
319
275
 
@@ -347,7 +303,6 @@ class AccountRepository extends Repository {
347
303
  return null;
348
304
  }
349
305
 
350
-
351
306
  async login(credentialsOrUsername, passwordArg) {
352
307
  let username, password;
353
308
  if (typeof credentialsOrUsername === 'object' && credentialsOrUsername !== null) {
@@ -367,18 +322,53 @@ class AccountRepository extends Repository {
367
322
 
368
323
  const { encrypted, time } = this.encryptPassword(password);
369
324
 
370
-
371
- const csrfToken = await this.ensureCsrfToken();
372
- return this.requestWithRetry(async () => {
373
- const aacInitTimestamp = Math.floor(Date.now() / 1000) - Math.floor(Math.random() * 50);
325
+ // optional CSRF warmup (like app does before login)
326
+ await this.ensureCsrfToken();
327
+
328
+ return this.requestWithRetry(async () => {
329
+ // ====== client_input_params (oglindă după traficul real) ======
330
+ const nowSec = Math.floor(Date.now() / 1000);
331
+ const aacInitTimestamp = nowSec - Math.floor(Math.random() * 50);
374
332
  const aacjid = crypto.randomUUID ? crypto.randomUUID() : require('uuid').v4();
375
- const aaccs = crypto.randomBytes(32).toString('base64url');
333
+ const aaccs = crypto.randomBytes(32).toString('base64').replace(/=/g, '');
334
+
335
+ const androidDeviceId =
336
+ this.client.state.androidDeviceId ||
337
+ this.client.state.deviceId ||
338
+ `android-${crypto.randomBytes(8).toString('hex')}`;
339
+
340
+ const machineId =
341
+ this.client.state.mid ||
342
+ this.client.state.machineId ||
343
+ `aZ${crypto.randomBytes(8).toString('hex')}`;
344
+
345
+ const familyDeviceId =
346
+ this.client.state.phoneId ||
347
+ this.client.state.familyDeviceId ||
348
+ crypto.randomUUID
349
+ ? crypto.randomUUID()
350
+ : require('uuid').v4();
351
+
352
+ const qeDeviceId =
353
+ this.client.state.deviceId ||
354
+ this.client.state.qeDeviceId ||
355
+ crypto.randomUUID
356
+ ? crypto.randomUUID()
357
+ : require('uuid').v4();
358
+
359
+ const accountsList = this.client.state.accountsList || [];
360
+
361
+ const flashCallPermissionStatus = {
362
+ READ_PHONE_STATE: 'GRANTED',
363
+ READ_CALL_LOG: 'GRANTED',
364
+ ANSWER_PHONE_CALLS: 'GRANTED',
365
+ };
376
366
 
377
367
  const clientInputParams = {
378
368
  aac: JSON.stringify({
379
369
  aac_init_timestamp: aacInitTimestamp,
380
- aacjid: aacjid,
381
- aaccs: aaccs,
370
+ aacjid,
371
+ aaccs,
382
372
  }),
383
373
  sim_phones: [],
384
374
  aymh_accounts: [],
@@ -388,25 +378,77 @@ return this.requestWithRetry(async () => {
388
378
  auth_secure_device_id: '',
389
379
  has_whatsapp_installed: 1,
390
380
  password: `#PWD_INSTAGRAM:4:${time}:${encrypted}`,
391
- sso_token_map_json_string: '{}',
381
+ sso_token_map_json_string: JSON.stringify({
382
+ [this.client.state.cookieUserId || '0']: [],
383
+ }),
392
384
  block_store_machine_id: '',
393
- ig_vetted_device_nonces: '{}',
385
+ ig_vetted_device_nonces: JSON.stringify({}),
386
+ cloud_trust_token: null,
387
+ event_flow: 'login_manual',
388
+ password_contains_non_ascii: 'false',
389
+ client_known_key_hash: '',
390
+ encrypted_msisdn: '',
391
+ has_granted_read_phone_permissions: 0,
392
+ app_manager_id: '',
393
+ should_show_nested_nta_from_aymh: 0,
394
+ device_id: androidDeviceId,
395
+ zero_balance_state: '',
396
+ login_attempt_count: 1,
397
+ machine_id: machineId,
398
+ flash_call_permission_status: flashCallPermissionStatus,
399
+ accounts_list: accountsList,
400
+ gms_incoming_call_retriever_eligibility: 'client_not_supported',
401
+ family_device_id: familyDeviceId,
402
+ fb_ig_device_id: [],
403
+ device_emails: [],
404
+ try_num: 1,
405
+ lois_settings: { lois_token: '' },
406
+ event_step: 'home_page',
407
+ headers_infra_flow_id: '',
408
+ openid_tokens: {},
394
409
  contact_point: username,
395
- machine_id: this.client.state.mid || '',
396
- login_attempt_count: '0',
397
- reg_flow_taken: 'phone',
398
- device_id: this.client.state.uuid,
399
- phone_id: this.client.state.phoneId,
400
- family_device_id: this.client.state.phoneId,
401
- encryption_enabled: '1',
402
- has_dbl_tap_login: 0,
403
- jazoest: AccountRepository.createJazoest(this.client.state.phoneId),
404
- openid_tokens: '{}',
405
410
  };
406
411
 
412
+ // ====== server_params (oglindă după traficul real) ======
413
+ const waterfallId = crypto.randomUUID ? crypto.randomUUID() : require('uuid').v4();
414
+ const latencyMarkerId = 36707139;
415
+ const latencyInstanceId = Number(`${Date.now()}${Math.floor(Math.random() * 1000)}`);
416
+
407
417
  const serverParams = {
418
+ should_trigger_override_login_2fa_action: 0,
419
+ is_vanilla_password_page_empty_password: 0,
420
+ is_from_logged_out: 0,
421
+ should_trigger_override_login_success_action: 0,
422
+ login_credential_type: 'none',
423
+ server_login_source: 'login',
424
+ waterfall_id: waterfallId,
425
+ two_step_login_type: 'one_step_login',
426
+ login_source: 'Login',
427
+ is_platform_login: 0,
428
+ INTERNAL__latency_qpl_marker_id: latencyMarkerId,
429
+ is_from_aymh: 0,
430
+ offline_experiment_group: 'caa_iteration_v3_perf_ig_4',
431
+ is_from_landing_page: 0,
432
+ left_nav_button_action: 'NONE',
433
+ password_text_input_id: 'z0jejq:194',
434
+ is_from_empty_password: 0,
435
+ is_from_msplit_fallback: 0,
436
+ ar_event_source: 'login_home_page',
437
+ qe_device_id: qeDeviceId,
438
+ username_text_input_id: 'z0jejq:193',
439
+ layered_homepage_experiment_group: null,
440
+ device_id: androidDeviceId,
441
+ login_surface: 'switcher',
442
+ INTERNAL__latency_qpl_instance_id: latencyInstanceId,
443
+ reg_flow_source: 'login_home_native_integration_point',
444
+ is_caa_perf_enabled: 1,
408
445
  credential_type: 'password',
409
- device_id: this.client.state.uuid,
446
+ is_from_password_entry_page: 0,
447
+ caller: 'gslr',
448
+ family_device_id: familyDeviceId,
449
+ is_from_assistive_id: 0,
450
+ access_flow_version: 'pre_mt_behavior',
451
+ is_from_logged_in_switcher: 1,
410
452
  };
411
453
 
412
454
  const paramsJson = JSON.stringify({
@@ -416,75 +458,102 @@ return this.requestWithRetry(async () => {
416
458
 
417
459
  const attestParams = AccountRepository.generateAttestParams(this.client.state);
418
460
 
461
+ const bkClientContext = JSON.stringify({
462
+ bloks_version: this.client.state.bloksVersionId,
463
+ styles_id: 'instagram',
464
+ });
465
+
466
+ // ====== HEADERS – modelate după request_i.instagram.com_mlwzj8x1.txt ======
467
+ const lang = (this.client.state.language || 'ro_RO');
468
+ const acceptLanguage = `${lang.replace('_', '-')}, en-US`;
469
+
470
+ const userAgent =
471
+ this.client.state.userAgent ||
472
+ 'Instagram 371.0.0.0.23 Android (30/11; 320dpi; 720x1449; Xiaomi/Redmi; M2006C3MNG; angelican; mt6765; ro_RO; 703217507)';
473
+
419
474
  const bloksHeaders = {
420
- ...(csrfToken ? { 'X-CSRFToken': csrfToken } : {}),
421
- 'Accept-Language': `${(this.client.state.language || 'ro_RO').replace('_', '-')} , en-US`,
422
- 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
423
-
424
- 'IG-Intended-User-Id': '0',
425
-
426
- 'X-Bloks-Is-Layout-Rtl': 'false',
427
- 'X-Bloks-Prism-Ax-Base-Colors-Enabled': 'false',
428
- 'X-Bloks-Prism-Button-Version': 'CONTROL',
429
- 'X-Bloks-Prism-Colors-Enabled': 'true',
430
- 'X-Bloks-Prism-Font-Enabled': 'false',
431
- 'X-Bloks-Prism-Indigo-Link-Version': '0',
432
- 'X-Bloks-Version-Id': this.client.state.bloksVersionId,
433
-
434
- 'X-FB-Client-Ip': 'True',
435
- 'X-FB-Connection-Type': 'WIFI',
436
- 'X-FB-Friendly-Name': 'IgApi: bloks/async_action/com.bloks.www.bloks.caa.login.async.send_login_request/',
437
- 'X-FB-Network-Properties': 'VPN;Validated;LocalAddrs=/10.0.0.2,;',
438
- 'X-FB-Request-Analytics-Tags': JSON.stringify({
475
+ 'accept-language': acceptLanguage,
476
+ 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
477
+ 'ig-intended-user-id': '0',
478
+ 'priority': 'u=3',
479
+
480
+ 'x-bloks-is-layout-rtl': 'false',
481
+ 'x-bloks-prism-ax-base-colors-enabled': 'false',
482
+ 'x-bloks-prism-button-version': 'CONTROL',
483
+ 'x-bloks-prism-colors-enabled': 'true',
484
+ 'x-bloks-prism-font-enabled': 'false',
485
+ 'x-bloks-prism-indigo-link-version': '0',
486
+ 'x-bloks-version-id': this.client.state.bloksVersionId,
487
+
488
+ 'x-fb-client-ip': 'True',
489
+ 'x-fb-connection-type': 'WIFI',
490
+ 'x-fb-friendly-name': 'IgApi: bloks/async_action/com.bloks.www.bloks.caa.login.async.send_login_request/',
491
+ 'x-fb-network-properties': 'VPN;Validated;LocalAddrs=/10.0.0.2,;',
492
+ 'x-fb-request-analytics-tags': JSON.stringify({
439
493
  network_tags: {
440
- product: String(this.client.state.fbAnalyticsApplicationId || ''),
494
+ product: String(this.client.state.fbAnalyticsApplicationId || '567067343352427'),
441
495
  purpose: 'fetch',
442
496
  surface: 'undefined',
443
497
  request_category: 'api',
444
498
  retry_attempt: '0',
445
499
  },
446
500
  }),
447
- 'X-FB-Server-Cluster': 'True',
448
- 'X-FB-RMD': 'state=URL_ELIGIBLE',
449
- 'X-FB-Conn-UUID-Client': crypto.randomBytes(16).toString('hex'),
450
- 'X-FB-HTTP-Engine': 'MNS/TCP',
451
-
452
- 'X-IG-Client-Endpoint': 'com.bloks.www.caa.login.aymh_single_profile_screen_entry',
453
- 'X-IG-Connection-Type': 'WIFI',
454
- 'X-IG-Capabilities': '3brTv10=',
455
- 'X-IG-App-ID': String(this.client.state.fbAnalyticsApplicationId || ''),
456
- 'X-IG-App-Locale': (this.client.state.language || 'ro_RO'),
457
- 'X-IG-Device-Locale': (this.client.state.language || 'ro_RO'),
458
- 'X-IG-Mapped-Locale': (this.client.state.language || 'ro_RO'),
459
- 'X-IG-Android-Id': this.client.state.androidDeviceId || this.client.state.deviceId || '',
460
- 'X-IG-Device-Id': this.client.state.deviceId,
461
- 'X-IG-Family-Device-Id': this.client.state.phoneId,
462
- 'X-IG-Timezone-Offset': String(typeof this.client.state.timezoneOffset === 'number' ? this.client.state.timezoneOffset : 7200),
463
- 'X-IG-WWW-Claim': this.client.state.igWWWClaim || '0',
464
- 'X-IG-Nav-Chain': 'LockoutFragment:dogfooding_lockout:1:cold_start:...caa.login.aymh_single_profile_screen_entry:9:button:0::0',
465
-
466
- 'X-IG-Attest-Params': JSON.stringify(attestParams),
467
-
468
- 'X-Mid': this.client.state.mid || '',
469
- 'X-Pigeon-Rawclienttime': (Date.now() / 1000).toFixed(3),
470
- 'X-Pigeon-Session-Id': this.client.state.pigeonSessionId || 'UFS-' + (crypto.randomBytes(16).toString('hex')),
471
- 'X-Tigon-Is-Retry': 'False',
472
-
473
- 'X-IG-Bandwidth-Speed-KBPS': (Math.random() * 1500 + 1500).toFixed(3),
474
- 'X-IG-Bandwidth-TotalBytes-B': '0',
475
- 'X-IG-Bandwidth-TotalTime-MS': '0',
476
-
477
- 'Accept-Encoding': 'gzip, deflate',
478
- 'User-Agent': this.client.state.userAgent || 'Instagram 371.0.0.0.23 Android (30/11; 320dpi; 720x1449; Xiaomi/Redmi; M2006C3MNG; angelican; mt6765; ro_RO; 703217507)',
501
+ 'x-fb-server-cluster': 'True',
502
+
503
+ 'x-ig-android-id': androidDeviceId,
504
+ 'x-ig-app-id': String(this.client.state.fbAnalyticsApplicationId || '567067343352427'),
505
+ 'x-ig-app-locale': lang,
506
+ 'x-ig-attest-params': JSON.stringify(attestParams),
507
+ 'x-ig-bandwidth-speed-kbps': (Math.random() * 1500 + 800).toFixed(3),
508
+ 'x-ig-bandwidth-totalbytes-b': '0',
509
+ 'x-ig-bandwidth-totaltime-ms': '0',
510
+ 'x-ig-client-endpoint': 'com.bloks.www.caa.login.aymh_single_profile_screen_entry',
511
+ 'x-ig-capabilities': '3brTv10=',
512
+ 'x-ig-connection-type': 'WIFI',
513
+ 'x-ig-device-id': qeDeviceId,
514
+ 'x-ig-device-locale': lang,
515
+ 'x-ig-family-device-id': familyDeviceId,
516
+ 'x-ig-mapped-locale': lang,
517
+ 'x-ig-nav-chain':
518
+ 'LockoutFragment:dogfooding_lockout:1:cold_start:...,' +
519
+ 'com.bloks.www.caa.login.aymh_single_profile_screen_entry:com.bloks.www.caa.login.aymh_single_profile_screen_entry:14:button:0:::0',
520
+ 'x-ig-timezone-offset': String(
521
+ typeof this.client.state.timezoneOffset === 'number'
522
+ ? this.client.state.timezoneOffset
523
+ : 7200
524
+ ),
525
+ 'x-ig-www-claim': this.client.state.igWWWClaim || '0',
526
+
527
+ 'x-mid': machineId,
528
+ 'x-pigeon-rawclienttime': `${nowSec}.${Math.floor(Math.random() * 1000)
529
+ .toString()
530
+ .padStart(3, '0')}`,
531
+ 'x-pigeon-session-id':
532
+ this.client.state.pigeonSessionId ||
533
+ `UFS-${crypto.randomBytes(16).toString('hex')}-1`,
534
+ 'x-tigon-is-retry': 'False',
535
+
536
+ // ...
537
+ 'accept-encoding': 'gzip, deflate, br',
538
+ // ...
539
+ 'user-agent': userAgent,
540
+ 'x-fb-conn-uuid-client': crypto.randomBytes(16).toString('hex'),
541
+ 'x-fb-http-engine': 'MNS/TCP',
542
+ 'x-fb-rmd': 'state=URL_ELIGIBLE',
479
543
  };
480
544
 
481
545
  const response = await this.client.request.send({
482
546
  method: 'POST',
483
547
  url: '/api/v1/bloks/async_action/com.bloks.www.bloks.caa.login.async.send_login_request/',
484
- form: { params: paramsJson },
548
+ form: {
549
+ params: paramsJson,
550
+ bk_client_context: bkClientContext,
551
+ bloks_versioning_id: this.client.state.bloksVersionId,
552
+ },
485
553
  headers: bloksHeaders,
486
554
  });
487
- // === DEBUG LOGIN: salvați răspunsul brut de la server pentru analiză ===
555
+
556
+ // === DEBUG LOGIN: salvăm răspunsul pentru analiză ===
488
557
  try {
489
558
  const fs = require('fs');
490
559
  const path = require('path');
@@ -492,7 +561,6 @@ return this.requestWithRetry(async () => {
492
561
  const debugDir = path.join(process.cwd(), 'authinfo_instagram');
493
562
  const debugFile = path.join(debugDir, 'login-debug.json');
494
563
 
495
- // asigură-te că folderul există
496
564
  try {
497
565
  fs.mkdirSync(debugDir, { recursive: true });
498
566
  } catch (e) {}
@@ -508,12 +576,11 @@ return this.requestWithRetry(async () => {
508
576
  } catch (e) {
509
577
  // nu stricăm login-ul dacă nu merge debug-ul
510
578
  }
511
- // === SFÂRȘIT DEBUG LOGIN ===
579
+ // === SFÂRȘIT DEBUG LOGIN ===
512
580
 
513
581
  const body = response.body;
514
582
 
515
583
  // Immediately attempt to extract and save authorization token from the response
516
- // This covers tokens returned in headers, in layout payloads, or embedded login_response headers.
517
584
  this._extractAndSaveAuthorization(response);
518
585
 
519
586
  if (body && body.two_factor_required) {
@@ -1071,34 +1138,74 @@ return this.requestWithRetry(async () => {
1071
1138
  });
1072
1139
  }
1073
1140
 
1074
- static generateAttestParams(state) {
1141
+ static generateAttestParams(state) {
1142
+ // Emulate Instagram's keystore attestation as closely as possible:
1143
+ // - version: 2
1144
+ // - type: "keystore"
1145
+ // - errors: [0]
1146
+ // - challenge_nonce: random base64url
1147
+ // - signed_nonce: ECDSA signature over the nonce
1148
+ // - key_hash: sha256(spki(publicKey))
1149
+ // - certificate_chain: 4 PEM certificates concatenated (leaf + 2 intermediates + root)
1150
+ //
1151
+ // NOTE: This is *not* a real hardware-backed attestation chain, but it mirrors
1152
+ // the structure of the official app very closely so the server sees the same
1153
+ // shape: a single attestation object with a 4‑certificate chain.
1075
1154
  const challengeNonce = crypto.randomBytes(24).toString('base64url');
1076
1155
 
1077
1156
  const { privateKey, publicKey } = crypto.generateKeyPairSync('ec', {
1078
1157
  namedCurve: 'prime256v1',
1079
1158
  });
1080
1159
 
1160
+ // Sign the challenge nonce with the private key (simulating TEE signing).
1081
1161
  const signedData = crypto.sign(null, Buffer.from(challengeNonce), privateKey);
1082
1162
  const signedNonce = signedData.toString('base64');
1083
1163
 
1084
1164
  const publicKeyDer = publicKey.export({ type: 'spki', format: 'der' });
1085
1165
  const keyHash = crypto.createHash('sha256').update(publicKeyDer).digest('hex');
1086
1166
 
1087
- const leafCertPem = AccountRepository._generateSelfSignedCert(privateKey, publicKey, 'Android Keystore Key');
1088
- const intermediateCertPem = AccountRepository._generateSelfSignedCert(privateKey, publicKey, 'TEE');
1089
-
1090
- const certificateChain = leafCertPem + '\n' + intermediateCertPem;
1167
+ // Build a 4‑certificate chain (leaf + 2 intermediates + root), just like
1168
+ // what we saw in the captured traffic from the real Instagram app.
1169
+ const leafCertPem = AccountRepository._generateSelfSignedCert(
1170
+ privateKey,
1171
+ publicKey,
1172
+ 'Android Keystore Key'
1173
+ );
1174
+ const intermediate1Pem = AccountRepository._generateSelfSignedCert(
1175
+ privateKey,
1176
+ publicKey,
1177
+ 'Android Keystore Key Attestation'
1178
+ );
1179
+ const intermediate2Pem = AccountRepository._generateSelfSignedCert(
1180
+ privateKey,
1181
+ publicKey,
1182
+ 'Android Hardware Keystore'
1183
+ );
1184
+ const rootCertPem = AccountRepository._generateSelfSignedCert(
1185
+ privateKey,
1186
+ publicKey,
1187
+ 'Android Keystore Root'
1188
+ );
1189
+
1190
+ const certificateChain = [
1191
+ leafCertPem,
1192
+ intermediate1Pem,
1193
+ intermediate2Pem,
1194
+ rootCertPem,
1195
+ ].join('\n');
1091
1196
 
1092
1197
  return {
1093
- attestation: [{
1094
- version: 2,
1095
- type: 'keystore',
1096
- errors: [0],
1097
- challenge_nonce: challengeNonce,
1098
- signed_nonce: signedNonce,
1099
- key_hash: keyHash,
1100
- certificate_chain: certificateChain,
1101
- }],
1198
+ attestation: [
1199
+ {
1200
+ version: 2,
1201
+ type: 'keystore',
1202
+ errors: [0],
1203
+ challenge_nonce: challengeNonce,
1204
+ signed_nonce: signedNonce,
1205
+ key_hash: keyHash,
1206
+ certificate_chain: certificateChain,
1207
+ },
1208
+ ],
1102
1209
  };
1103
1210
  }
1104
1211
 
@@ -1162,7 +1269,7 @@ return this.requestWithRetry(async () => {
1162
1269
  }
1163
1270
 
1164
1271
  static createJazoest(input) {
1165
- const buf = Buffer.from(input, 'ascii');
1272
+ const buf = Buffer.from(input || '', 'ascii');
1166
1273
  let sum = 0;
1167
1274
  for (let i = 0; i < buf.byteLength; i++) {
1168
1275
  sum += buf.readUInt8(i);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodejs-insta-private-api-mqt",
3
- "version": "1.3.81",
3
+ "version": "1.3.83",
4
4
  "description": "Complete Instagram MQTT protocol with FULL Featured REALTIME And api Rest All in one project .",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {