nodejs-insta-private-api-mqt 1.3.74 → 1.3.75

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.
@@ -264,7 +264,7 @@ class Request {
264
264
  if (!url) return;
265
265
  const path = url.toLowerCase();
266
266
 
267
- if (path.includes('/accounts/login/') || path.includes('/launcher/sync/')) {
267
+ if (path.includes('/accounts/login/') || path.includes('/launcher/sync/') || path.includes('/bloks/async_action/com.bloks.www.bloks.caa.login')) {
268
268
  this.navChain.simulateAppOpen();
269
269
  return;
270
270
  }
@@ -45,22 +45,84 @@ class AccountRepository extends Repository {
45
45
  const { encrypted, time } = this.encryptPassword(password);
46
46
 
47
47
  return this.requestWithRetry(async () => {
48
- const countryCode = this.client.state.countryCode || 1;
48
+ const aacInitTimestamp = Math.floor(Date.now() / 1000) - Math.floor(Math.random() * 50);
49
+ const aacjid = crypto.randomUUID ? crypto.randomUUID() : require('uuid').v4();
50
+ const aaccs = crypto.randomBytes(32).toString('base64url');
51
+
52
+ const clientInputParams = {
53
+ aac: JSON.stringify({
54
+ aac_init_timestamp: aacInitTimestamp,
55
+ aacjid: aacjid,
56
+ aaccs: aaccs,
57
+ }),
58
+ sim_phones: [],
59
+ aymh_accounts: [],
60
+ network_bssid: null,
61
+ secure_family_device_id: '',
62
+ has_granted_read_contacts_permissions: 0,
63
+ auth_secure_device_id: '',
64
+ has_whatsapp_installed: 1,
65
+ password: `#PWD_INSTAGRAM:4:${time}:${encrypted}`,
66
+ sso_token_map_json_string: '{}',
67
+ block_store_machine_id: '',
68
+ ig_vetted_device_nonces: '{}',
69
+ contact_point: username,
70
+ machine_id: this.client.state.mid || '',
71
+ login_attempt_count: '0',
72
+ reg_flow_taken: 'phone',
73
+ device_id: this.client.state.uuid,
74
+ phone_id: this.client.state.phoneId,
75
+ family_device_id: this.client.state.phoneId,
76
+ encryption_enabled: '1',
77
+ has_dbl_tap_login: 0,
78
+ jazoest: AccountRepository.createJazoest(this.client.state.phoneId),
79
+ openid_tokens: '{}',
80
+ };
81
+
82
+ const serverParams = {
83
+ credential_type: 'password',
84
+ device_id: this.client.state.uuid,
85
+ };
86
+
87
+ const paramsJson = JSON.stringify({
88
+ client_input_params: clientInputParams,
89
+ server_params: serverParams,
90
+ });
91
+
92
+ const attestParams = AccountRepository.generateAttestParams(this.client.state);
93
+
94
+ const bloksHeaders = {
95
+ 'X-Bloks-Prism-Ax-Base-Colors-Enabled': 'false',
96
+ 'X-Bloks-Prism-Button-Version': 'CONTROL',
97
+ 'X-Bloks-Prism-Colors-Enabled': 'true',
98
+ 'X-Bloks-Prism-Font-Enabled': 'false',
99
+ 'X-Bloks-Prism-Indigo-Link-Version': '0',
100
+ 'X-FB-Friendly-Name': 'IgApi: bloks/async_action/com.bloks.www.bloks.caa.login.async.send_login_request/',
101
+ 'X-FB-Request-Analytics-Tags': JSON.stringify({
102
+ network_tags: {
103
+ product: this.client.state.fbAnalyticsApplicationId,
104
+ purpose: 'fetch',
105
+ surface: 'undefined',
106
+ request_category: 'api',
107
+ retry_attempt: '0',
108
+ },
109
+ }),
110
+ 'X-IG-Client-Endpoint': 'com.bloks.www.caa.login.aymh_single_profile_screen_entry',
111
+ 'X-Tigon-Is-Retry': 'False',
112
+ 'X-FB-RMD': 'state=URL_ELIGIBLE',
113
+ 'X-IG-Attest-Params': JSON.stringify(attestParams),
114
+ 'X-FB-Connection-Type': 'MOBILE.LTE',
115
+ 'X-FB-Network-Properties': 'VPN;Metered;Validated;LocalAddrs=/10.0.0.2,;',
116
+ 'X-FB-Conn-UUID-Client': crypto.randomBytes(16).toString('hex'),
117
+ 'Accept-Encoding': 'zstd',
118
+ 'X-FB-HTTP-Engine': 'MNS/TCP',
119
+ };
120
+
49
121
  const response = await this.client.request.send({
50
122
  method: 'POST',
51
- url: '/api/v1/accounts/login/',
52
- form: this.client.request.sign({
53
- jazoest: AccountRepository.createJazoest(this.client.state.phoneId),
54
- country_codes: JSON.stringify([{ country_code: String(countryCode), source: ['default'] }]),
55
- phone_id: this.client.state.phoneId,
56
- enc_password: `#PWD_INSTAGRAM:4:${time}:${encrypted}`,
57
- username,
58
- adid: this.client.state.adid,
59
- guid: this.client.state.uuid,
60
- device_id: this.client.state.deviceId,
61
- google_tokens: '[]',
62
- login_attempt_count: '0',
63
- }),
123
+ url: '/api/v1/bloks/async_action/com.bloks.www.bloks.caa.login.async.send_login_request/',
124
+ form: { params: paramsJson },
125
+ headers: bloksHeaders,
64
126
  });
65
127
 
66
128
  const body = response.body;
@@ -88,7 +150,51 @@ class AccountRepository extends Repository {
88
150
  throw err;
89
151
  }
90
152
 
91
- return body.logged_in_user;
153
+ if (body.layout) {
154
+ const layoutStr = typeof body.layout === 'string' ? body.layout : JSON.stringify(body.layout);
155
+
156
+ if (layoutStr.includes('two_factor_required') || layoutStr.includes('"two_factor_info"')) {
157
+ let twoFactorInfo = null;
158
+ try {
159
+ const match = layoutStr.match(/"two_factor_info"\s*:\s*(\{[^}]+\})/);
160
+ if (match) twoFactorInfo = JSON.parse(match[1]);
161
+ } catch (e) {}
162
+ const err = new Error('Two factor authentication required');
163
+ err.name = 'IgLoginTwoFactorRequiredError';
164
+ err.twoFactorInfo = twoFactorInfo;
165
+ throw err;
166
+ }
167
+
168
+ if (layoutStr.includes('bad_password') || layoutStr.includes('incorrect_password')) {
169
+ const err = new Error('Bad password');
170
+ err.name = 'IgLoginBadPasswordError';
171
+ throw err;
172
+ }
173
+
174
+ if (layoutStr.includes('invalid_user') || layoutStr.includes('user_not_found')) {
175
+ const err = new Error('Invalid user');
176
+ err.name = 'IgLoginInvalidUserError';
177
+ throw err;
178
+ }
179
+
180
+ if (layoutStr.includes('challenge_required')) {
181
+ const err = new Error('Challenge required');
182
+ err.name = 'IgCheckpointError';
183
+ err.challengeInfo = body.challenge || null;
184
+ throw err;
185
+ }
186
+ }
187
+
188
+ if (body.logged_in_user) {
189
+ return body.logged_in_user;
190
+ }
191
+
192
+ try {
193
+ const userInfo = await this.currentUser();
194
+ return userInfo.user || userInfo;
195
+ } catch (e) {
196
+ return body;
197
+ }
92
198
  });
93
199
  }
94
200
 
@@ -459,6 +565,96 @@ class AccountRepository extends Repository {
459
565
  });
460
566
  }
461
567
 
568
+ static generateAttestParams(state) {
569
+ const challengeNonce = crypto.randomBytes(24).toString('base64url');
570
+
571
+ const { privateKey, publicKey } = crypto.generateKeyPairSync('ec', {
572
+ namedCurve: 'prime256v1',
573
+ });
574
+
575
+ const signedData = crypto.sign(null, Buffer.from(challengeNonce), privateKey);
576
+ const signedNonce = signedData.toString('base64');
577
+
578
+ const publicKeyDer = publicKey.export({ type: 'spki', format: 'der' });
579
+ const keyHash = crypto.createHash('sha256').update(publicKeyDer).digest('hex');
580
+
581
+ const leafCertPem = AccountRepository._generateSelfSignedCert(privateKey, publicKey, 'Android Keystore Key');
582
+ const intermediateCertPem = AccountRepository._generateSelfSignedCert(privateKey, publicKey, 'TEE');
583
+
584
+ const certificateChain = leafCertPem + '\n' + intermediateCertPem;
585
+
586
+ return {
587
+ attestation: [{
588
+ version: 2,
589
+ type: 'keystore',
590
+ errors: [0],
591
+ challenge_nonce: challengeNonce,
592
+ signed_nonce: signedNonce,
593
+ key_hash: keyHash,
594
+ certificate_chain: certificateChain,
595
+ }],
596
+ };
597
+ }
598
+
599
+ static _generateSelfSignedCert(privateKey, publicKey, cn) {
600
+ const publicKeyDer = publicKey.export({ type: 'spki', format: 'der' });
601
+ const serialNumber = crypto.randomBytes(8);
602
+ const now = new Date();
603
+ const notBefore = new Date(now.getTime() - 365 * 24 * 60 * 60 * 1000);
604
+ const notAfter = new Date(now.getTime() + 10 * 365 * 24 * 60 * 60 * 1000);
605
+
606
+ const cnBytes = Buffer.from(cn, 'utf8');
607
+ const cnSeq = Buffer.concat([
608
+ Buffer.from([0x30, cnBytes.length + 13]),
609
+ Buffer.from([0x31, cnBytes.length + 11]),
610
+ Buffer.from([0x30, cnBytes.length + 9]),
611
+ Buffer.from([0x06, 0x03, 0x55, 0x04, 0x03]),
612
+ Buffer.from([0x0c, cnBytes.length]),
613
+ cnBytes,
614
+ ]);
615
+
616
+ function encodeTime(date) {
617
+ const str = date.toISOString().replace(/[-:T]/g, '').slice(2, 14) + 'Z';
618
+ return Buffer.concat([Buffer.from([0x17, str.length]), Buffer.from(str)]);
619
+ }
620
+
621
+ const validityBuf = Buffer.concat([
622
+ encodeTime(notBefore),
623
+ encodeTime(notAfter),
624
+ ]);
625
+ const validity = Buffer.concat([Buffer.from([0x30, validityBuf.length]), validityBuf]);
626
+
627
+ const tbs = Buffer.concat([
628
+ Buffer.from([0xa0, 0x03, 0x02, 0x01, 0x02]),
629
+ Buffer.from([0x02, serialNumber.length]), serialNumber,
630
+ Buffer.from([0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02]),
631
+ cnSeq,
632
+ validity,
633
+ cnSeq,
634
+ publicKeyDer,
635
+ ]);
636
+
637
+ const tbsSeq = Buffer.concat([Buffer.from([0x30, 0x82]), Buffer.alloc(2), tbs]);
638
+ tbsSeq.writeUInt16BE(tbs.length, 2);
639
+
640
+ const signature = crypto.sign(null, tbsSeq, privateKey);
641
+
642
+ const sigBitString = Buffer.concat([
643
+ Buffer.from([0x03, signature.length + 1, 0x00]),
644
+ signature,
645
+ ]);
646
+
647
+ const algId = Buffer.from([0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02]);
648
+
649
+ const certBody = Buffer.concat([tbsSeq, algId, sigBitString]);
650
+ const cert = Buffer.concat([Buffer.from([0x30, 0x82]), Buffer.alloc(2), certBody]);
651
+ cert.writeUInt16BE(certBody.length, 2);
652
+
653
+ const b64 = cert.toString('base64');
654
+ const lines = b64.match(/.{1,76}/g) || [b64];
655
+ return '-----BEGIN CERTIFICATE-----\n' + lines.join('\n') + '\n-----END CERTIFICATE-----';
656
+ }
657
+
462
658
  static createJazoest(input) {
463
659
  const buf = Buffer.from(input, 'ascii');
464
660
  let sum = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodejs-insta-private-api-mqt",
3
- "version": "1.3.74",
3
+ "version": "1.3.75",
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": {