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.
package/dist/core/request.js
CHANGED
|
@@ -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
|
|
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/
|
|
52
|
-
form:
|
|
53
|
-
|
|
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
|
-
|
|
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