Skip to content

Instantly share code, notes, and snippets.

@lorenzodifuccia
Created December 22, 2020 02:12
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save lorenzodifuccia/c857afa47ede66db852e6a25c0a1a027 to your computer and use it in GitHub Desktop.
Save lorenzodifuccia/c857afa47ede66db852e6a25c0a1a027 to your computer and use it in GitHub Desktop.
Encryption function used by Instagram (Browser App) to generate the 'enc_password' from PubKey (AES-GCM + SealedBox)
import base64
import struct
import datetime
import binascii
from urllib.parse import quote_plus
# pip install pycryptodomex
from Cryptodome import Random
from Cryptodome.Cipher import AES
# pip install PyNaCl
from nacl.public import PublicKey, SealedBox
def encrypt_password(key_id, pub_key, password, version=10):
key = Random.get_random_bytes(32)
iv = bytes([0] * 12)
time = int(datetime.datetime.now().timestamp())
aes = AES.new(key, AES.MODE_GCM, nonce=iv, mac_len=16)
aes.update(str(time).encode('utf-8'))
encrypted_password, cipher_tag = aes.encrypt_and_digest(password.encode('utf-8'))
pub_key_bytes = binascii.unhexlify(pub_key)
seal_box = SealedBox(PublicKey(pub_key_bytes))
encrypted_key = seal_box.encrypt(key)
encrypted = bytes([1,
key_id,
*list(struct.pack('<h', len(encrypted_key))),
*list(encrypted_key),
*list(cipher_tag),
*list(encrypted_password)])
encrypted = base64.b64encode(encrypted).decode('utf-8')
return quote_plus(f'#PWD_INSTAGRAM_BROWSER:{version}:{time}:{encrypted}')
print(encrypt_password(72, "b3a328ff28b785092af6a578767877514c93a690a11b9d92ba0ce614c9d5db57", "CHANGE_PASSWORD_HERE"))
@lorenzodifuccia
Copy link
Author

NodeJS version: https://github.com/unoemon/instagram-enc_passowrd-generator/blob/master/enc_passowrd-generator.js

Patch the JS script:

1,2c1
< const WebCrypto = require("node-webcrypto-ossl");
< const webcrypto = new WebCrypto();
---
> const webcrypto = new (require("node-webcrypto-ossl")).Crypto();
6,10c5,9
< exports.handler = async (event) => {
<   const APP_ID = '6';
<   const KEY_ID = '191';
<   const PUBLIC_KEY = '47c741b21d867bf5909ec70f86da86b9adcdff119c365f44f19d2f222f60260b';
<   const PASSWORD = 'passwrod123';
---
> generatePassword = async (appId, keyId, pubKey, password) => {
>   const APP_ID = appId;
>   const KEY_ID = keyId;
>   const PUBLIC_KEY = pubKey;
>   const PASSWORD = password;
32c31
<   return "#PWD_INSTAGRAM_BROWSER" + ':' + app_id + ':' + time + ':' + enc_password
---
>   return encodeURIComponent("#PWD_INSTAGRAM_BROWSER" + ':' + app_id + ':' + time + ':' + enc_password)
96,99c95
<   var t, o = [], c = str.length;
<   for (t = 0; t < c; t++)
<     o.push(String.fromCharCode(str[t]));
<   return btoa(o.join(''))
---
>   return Buffer.from(str, "binary").toString("base64");
107a104,106
> 
> // MAIN
> generatePassword("10", 72, "b3a328ff28b785092af6a578767877514c93a690a11b9d92ba0ce614c9d5db57", "CHANGE_PASSWORD_HERE")

@Mubelotix
Copy link

Rust version
use aes_gcm::{aead::NewAead, AeadInPlace, Aes256Gcm, Key, Nonce};
use chrono::Utc;
use rand::Rng;
use rust_sodium::crypto::{box_::PublicKey, sealedbox::curve25519blake2bxsalsa20poly1305::seal};

const VERSION: u8 = 10;

fn read_hex_array(hex_array: &str) -> Vec<u8> {
    let hex_array = hex_array.as_bytes();
    let mut result = Vec::new();
    for i in (0..hex_array.len()).step_by(2) {
        let first = hex_array[i];
        let second = hex_array.get(i + 1).unwrap_or(&0);
        let mut number = match first {
            b'a'..=b'f' => 10 + (first - b'a'),
            b'A'..=b'F' => 10 + (first - b'A'),
            b'0'..=b'9' => first - b'0',
            _ => 0,
        };
        number <<= 4;
        number += match second {
            b'a'..=b'f' => 10 + (second - b'a'),
            b'A'..=b'F' => 10 + (second - b'A'),
            b'0'..=b'9' => second - b'0',
            _ => 0,
        };
        result.push(number);
    }
    result
}

fn generate_enc_password(public_key: &str, key_id: u8, password: &str) -> String {
    let public_key = read_hex_array(public_key);
    let iv = [0; 12];
    let mut key: [u8; 32] = [0; 32];
    rand::thread_rng().fill(&mut key);
    let time = Utc::now().timestamp().to_string();

    // Encrypt the password
    let aes = Aes256Gcm::new(Key::from_slice(&key));
    let mut encrypted_password = password.as_bytes().to_vec();
    let cipher_tag = aes
        .encrypt_in_place_detached(
            Nonce::from_slice(&iv),
            time.as_ref(),
            encrypted_password.as_mut_slice(),
        )
        .unwrap();
    
    // Seal the key with the public key
    let mut encrypted_key = seal(&key, &PublicKey::from_slice(&public_key).unwrap());

    let mut result = vec![1, key_id];
    result.extend_from_slice(&(encrypted_key.len() as u16).to_le_bytes());
    result.append(&mut encrypted_key);
    result.extend_from_slice(&cipher_tag);
    result.append(&mut encrypted_password);

    format!(
        "#PWD_INSTAGRAM_BROWSER:{}:{}:{}",
        VERSION,
        time,
        base64::encode(result)
    )
}

@suyashjawale
Copy link

suyashjawale commented Dec 1, 2022

@lorenzodifuccia
Not working.

image

@lorenzodifuccia
Copy link
Author

@suyashjawale, maybe key_id, pub_key are changed...

@cdsuicideboy
Copy link

@suyashjawale, maybe key_id, pub_key are changed...

do you know how solve this problem ?

@CupKido
Copy link

CupKido commented Apr 29, 2023

any update on why it might not work? I'm entering my password yet it still responds that the password is incorrect.
b'{"message":"Sorry, your password was incorrect. Please double-check your password.","status":"fail"}'
(for sure its the right password, also i made sure to receive the current public key and key id from 'https://www.instagram.com/data/shared_data/' using the code:

    data = json.loads(requests.get('https://www.instagram.com/data/shared_data/').text)
    publicKey = data['encryption']['public_key']
    keyId     = data['encryption']['key_id']
    result = encrypt_password(int(keyId), publicKey, password)

)

@godxgamer
Copy link

yep this not working i changed the keys still getting this error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment