Reverse Engineering the enc_password of Instagram API

virchual

Junior Member
Joined
Feb 18, 2024
Messages
149
Reaction score
68
Let's suppose, I'm creating a simple app to log in to Instagram/Facebook using the Python requests module. I know there is a working code available on the internet to do that but the thing is I want to understand how the guys have reverse-engineered the enc_password (encrypted version of the password needed to login) field needed to login to Instagram.

Here is a sample code I got from instagrapi that generates the enc_pass field when logging in to Instagram.

from Cryptodome.Cipher import AES, PKCS1_v1_5 from Cryptodome.PublicKey import RSA from Cryptodome.Random import get_random_bytes class PasswordMixin: def password_encrypt(self, password): publickeyid, publickey = self.password_publickeys() session_key = get_random_bytes(32) iv = get_random_bytes(12) timestamp = str(int(time.time())) decoded_publickey = base64.b64decode(publickey.encode()) recipient_key = RSA.import_key(decoded_publickey) cipher_rsa = PKCS1_v1_5.new(recipient_key) rsa_encrypted = cipher_rsa.encrypt(session_key) cipher_aes = AES.new(session_key, AES.MODE_GCM, iv) cipher_aes.update(timestamp.encode()) aes_encrypted, tag = cipher_aes.encrypt_and_digest(password.encode("utf8")) size_buffer = len(rsa_encrypted).to_bytes(2, byteorder="little") payload = base64.b64encode( b"".join( [ b"\x01", publickeyid.to_bytes(1, byteorder="big"), iv, size_buffer, rsa_encrypted, tag, aes_encrypted, ] ) ) return f"#PWD_INSTAGRAM:4:{timestamp}:{payload.decode()}" def password_publickeys(self): resp = self.public.get("[URL]https://i.instagram.com/api/v1/qe/sync/[/URL]") publickeyid = int(resp.headers.get("ig-set-password-encryption-key-id")) publickey = resp.headers.get("ig-set-password-encryption-pub-key") return publickeyid, publickey

Below is a sample code for logging in to Instagram using requests that are also extracted from instagrapi project and this works well

def login( self, username: str, password: str, relogin: bool = False, verification_code: str = "", ) -> bool: """ Login Parameters ---------- username: str Instagram Username password: str Instagram Password relogin: bool Whether or not to re login, default False verification_code: str 2FA verification code Returns ------- bool A boolean value """ self.username = username self.password = password if relogin: self.private.cookies.clear() if self.relogin_attempt > 1: raise ReloginAttemptExceeded() self.relogin_attempt += 1 # if self.user_id and self.last_login: # if time.time() - self.last_login < 60 * 60 * 24: # return True # already login if self.user_id and not relogin: return True # already login try: self.pre_login_flow() except (PleaseWaitFewMinutes, ClientThrottledError): self.logger.warning("Ignore 429: Continue login") # The instagram application ignores this error # and continues to log in (repeat this behavior) enc_password = self.password_encrypt(password) data = { "jazoest": generate_jazoest(self.phone_id), "country_codes": '[{"country_code":"%d","source":["default"]}]' % int(self.country_code), "phone_id": self.phone_id, "enc_password": enc_password, "username": username, "adid": self.advertising_id, "guid": self.uuid, "device_id": self.android_device_id, "google_tokens": "[]", "login_attempt_count": "0", } try: logged = self.private_request("accounts/login/", data, login=True) self.authorization_data = self.parse_authorization( self.last_response.headers.get("ig-set-authorization") ) except TwoFactorRequired as e: if not verification_code.strip(): raise TwoFactorRequired( f"{e} (you did not provide verification_code for login method)" ) two_factor_identifier = self.last_json.get("two_factor_info", {}).get( "two_factor_identifier" ) data = { "verification_code": verification_code, "phone_id": self.phone_id, "_csrftoken": self.token, "two_factor_identifier": two_factor_identifier, "username": username, "trust_this_device": "0", "guid": self.uuid, "device_id": self.android_device_id, "waterfall_id": str(uuid4()), "verification_method": "3", } logged = self.private_request( "accounts/two_factor_login/", data, login=True ) self.authorization_data = self.parse_authorization( self.last_response.headers.get("ig-set-authorization") ) if logged: self.login_flow() self.last_login = time.time() return True return False

All I want to understand is how they reverse-engineer the password_cncrypt() function to create enc_password value?
Is there any starting guide or background I'm missing?

Any help or tips to understand this would be very much appreciated.
 
Back
Top