#!/usr/bin/env python3
"""
AES Decryption Script for IBO APK
=================================
This script decrypts AES-encrypted data extracted from IBO APK
"""

import base64
import json
import sys
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad

# AES Keys found in libhax.so
KEYS = {
    'key1': b'EsySxALGhVMgDldp',  # 16 bytes - AES-128
    'key2': b'Al4mK7AwxtYS1yC7',  # 16 bytes - AES-128
}

# Potential encryption identifiers found
IDENTIFIERS = [
    'cca582f0481060e5a7ef0b2e2831bcdf',
    'b6372d3d8214118f5071db1f11e05f88',
    'ec9185cd7749d321309ed013e4069f5905bdd0f1a0e5a252b127e1806f493cfd',
]

def decrypt_aes_cbc(encrypted_data, key, iv=None):
    """
    Decrypt AES/CBC/PKCS5Padding encrypted data

    Args:
        encrypted_data: Base64 encoded encrypted data
        key: AES key (16 bytes for AES-128)
        iv: Initialization Vector (16 bytes). If None, will extract from data

    Returns:
        Decrypted string or None if failed
    """
    try:
        # Decode base64
        encrypted_bytes = base64.b64decode(encrypted_data)

        # If IV is None, assume it's prepended to the encrypted data (first 16 bytes)
        if iv is None:
            iv = encrypted_bytes[:16]
            ciphertext = encrypted_bytes[16:]
        else:
            ciphertext = encrypted_bytes

        # Create cipher
        cipher = AES.new(key, AES.MODE_CBC, iv)

        # Decrypt and remove padding
        decrypted = unpad(cipher.decrypt(ciphertext), AES.block_size)

        # Try to decode as UTF-8
        return decrypted.decode('utf-8')

    except Exception as e:
        return None

def decrypt_with_all_keys(encrypted_data):
    """
    Try to decrypt with all available keys

    Args:
        encrypted_data: Base64 encoded encrypted data

    Returns:
        Tuple of (key_name, decrypted_data) or (None, None) if failed
    """
    for key_name, key in KEYS.items():
        # Try with IV extracted from data
        result = decrypt_aes_cbc(encrypted_data, key, iv=None)
        if result:
            return (key_name, result)

        # Try with zero IV
        result = decrypt_aes_cbc(encrypted_data, key, iv=b'\x00' * 16)
        if result:
            return (key_name + " (zero IV)", result)

    return (None, None)

def decrypt_json_array(json_file_path):
    """
    Decrypt a JSON file containing array of encrypted strings

    Args:
        json_file_path: Path to JSON file

    Returns:
        List of decrypted items with metadata
    """
    try:
        with open(json_file_path, 'r') as f:
            data = json.load(f)

        # Extract the data array
        if isinstance(data, dict) and 'data' in data:
            encrypted_array = json.loads(data['data'])
        elif isinstance(data, list):
            encrypted_array = data
        else:
            print("❌ Invalid JSON format")
            return []

        results = []

        print(f"🔍 Found {len(encrypted_array)} encrypted items\n")
        print("=" * 80)

        for idx, encrypted_item in enumerate(encrypted_array, 1):
            print(f"\n[{idx}/{len(encrypted_array)}] Processing...")

            key_name, decrypted = decrypt_with_all_keys(encrypted_item)

            if decrypted:
                print(f"✅ SUCCESS with {key_name}")
                print(f"📝 Encrypted: {encrypted_item[:60]}...")
                print(f"🔓 Decrypted: {decrypted[:200]}")

                results.append({
                    'index': idx,
                    'key': key_name,
                    'encrypted': encrypted_item,
                    'decrypted': decrypted,
                    'success': True
                })
            else:
                print(f"❌ FAILED - Could not decrypt with any key")
                results.append({
                    'index': idx,
                    'encrypted': encrypted_item,
                    'success': False
                })

        print("\n" + "=" * 80)
        print(f"\n📊 Summary:")
        success_count = sum(1 for r in results if r.get('success'))
        print(f"   ✅ Successfully decrypted: {success_count}/{len(results)}")
        print(f"   ❌ Failed to decrypt: {len(results) - success_count}/{len(results)}")

        return results

    except Exception as e:
        print(f"❌ Error reading JSON file: {e}")
        return []

def decrypt_single_string(encrypted_string):
    """
    Decrypt a single encrypted string

    Args:
        encrypted_string: Base64 encoded encrypted string
    """
    print("🔍 Attempting to decrypt single string...")
    print(f"📝 Encrypted: {encrypted_string}\n")

    key_name, decrypted = decrypt_with_all_keys(encrypted_string)

    if decrypted:
        print(f"✅ SUCCESS with {key_name}")
        print(f"🔓 Decrypted: {decrypted}")
    else:
        print("❌ FAILED - Could not decrypt with any key")
        print("\n💡 Keys tried:")
        for name in KEYS.keys():
            print(f"   - {name}")

def save_results(results, output_file):
    """
    Save decryption results to a JSON file

    Args:
        results: List of decryption results
        output_file: Output file path
    """
    try:
        with open(output_file, 'w', encoding='utf-8') as f:
            json.dump(results, f, indent=2, ensure_ascii=False)
        print(f"\n💾 Results saved to: {output_file}")
    except Exception as e:
        print(f"❌ Error saving results: {e}")

if __name__ == "__main__":
    print("""
╔══════════════════════════════════════════════════════════════╗
║           AES Decryption Tool for IBO APK                    ║
║                                                              ║
║  Found Keys:                                                 ║
║    • EsySxALGhVMgDldp (AES-128)                             ║
║    • Al4mK7AwxtYS1yC7 (AES-128)                             ║
║                                                              ║
║  Algorithm: AES/CBC/PKCS5Padding                            ║
╚══════════════════════════════════════════════════════════════╝
""")

    if len(sys.argv) < 2:
        print("Usage:")
        print("  python3 aes_decrypt.py <json_file>        - Decrypt JSON array")
        print("  python3 aes_decrypt.py <encrypted_string> - Decrypt single string")
        print("\nExample:")
        print("  python3 aes_decrypt.py encrypted_data.json")
        print('  python3 aes_decrypt.py "dQlkxubHvTWp3iPODKTk9I9pnmt9PrvLej..."')
        sys.exit(1)

    input_data = sys.argv[1]

    # Check if input is a file
    if input_data.endswith('.json'):
        results = decrypt_json_array(input_data)

        if results:
            # Ask if user wants to save results
            output_file = input_data.replace('.json', '_decrypted.json')
            save_results(results, output_file)
    else:
        # Treat as single encrypted string
        decrypt_single_string(input_data)

    print("\n✨ Done!\n")
