import os
import sqlite3
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import base64
import win32crypt  # Only available on Windows platforms
from datetime import datetime
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes

# Function to get all Chrome profile paths containing cookies
def get_chrome_profiles_paths():
    local_app_data = os.getenv('LOCALAPPDATA')
    chrome_profiles_path = os.path.join(local_app_data, 'Google', 'Chrome', 'User Data')
    profile_paths = []
    
    for profile_dir in os.listdir(chrome_profiles_path):
        profile_path = os.path.join(chrome_profiles_path, profile_dir)
        network_cookies_path = os.path.join(profile_path, 'Network', 'Cookies')
        
        if os.path.isdir(profile_path) and os.path.exists(network_cookies_path):
            profile_paths.append(network_cookies_path)
    
    return profile_paths

# Function to load RSA private key from PEM file
def load_private_key(private_key_path):
    with open(private_key_path, 'rb') as f:
        private_key = serialization.load_pem_private_key(
            f.read(),
            password=None,  # No password protection
            backend=default_backend()
        )
    return private_key

# Function to decrypt Chrome cookies using RSA private key
def decrypt_cookie(encrypted_value, private_key):
    try:
        decrypted_cookie = private_key.decrypt(
            encrypted_value,
            padding.OAEP(
                mgf=padding.MGF1(algorithm=hashes.SHA256()),
                algorithm=hashes.SHA256(),
                label=None
            )
        )
    except Exception as e:
        print(f"Error decrypting with RSA: {e}")
        decrypted_cookie = encrypted_value
    return decrypted_cookie

# Function to convert expiration time from Chrome format to Unix timestamp
def chrome_time_to_unix(chrome_time):
    return (chrome_time - 11644473600000000) / 1000000

# Function to extract and save cookies in Netscape format to a file
def extract_and_save_cookies(private_key):
    profile_paths = get_chrome_profiles_paths()
    with open('cookies.txt', 'w', encoding='utf-8') as file:
        file.write("# Netscape HTTP Cookie File\n")
        for profile_path in profile_paths:
            try:
                conn = sqlite3.connect(profile_path)
                cursor = conn.cursor()
                
                # Check if the 'secure' and 'httponly' columns exist in the cookies table
                cursor.execute("PRAGMA table_info(cookies)")
                columns = [col[1] for col in cursor.fetchall()]
                secure_exists = 'secure' in columns
                httponly_exists = 'httponly' in columns
                
                if secure_exists and httponly_exists:
                    cursor.execute("SELECT host_key, name, encrypted_value, path, expires_utc, secure, httponly, creation_utc FROM cookies")
                elif secure_exists:
                    cursor.execute("SELECT host_key, name, encrypted_value, path, expires_utc, secure, creation_utc FROM cookies")
                elif httponly_exists:
                    cursor.execute("SELECT host_key, name, encrypted_value, path, expires_utc, httponly, creation_utc FROM cookies")
                else:
                    cursor.execute("SELECT host_key, name, encrypted_value, path, expires_utc, creation_utc FROM cookies")
                
                for row in cursor.fetchall():
                    try:
                        host_key, name, encrypted_value, path, expires_utc, *others = row
                        secure = bool(others[0]) if secure_exists and others else False
                        httponly = bool(others[1]) if httponly_exists and len(others) > 1 else False
                        
                        decrypted_value = decrypt_cookie(encrypted_value, private_key)
                        # Ensure proper decoding and ignore errors if any
                        decoded_value = decrypted_value.decode('utf-8', 'ignore') if isinstance(decrypted_value, bytes) else decrypted_value
                        expires = chrome_time_to_unix(expires_utc) if expires_utc else None
                        creation_time = chrome_time_to_unix(row[-1])
                        
                        # Building the Netscape cookie string
                        cookie_str = f"{host_key}\t{secure}\t{path}\t{httponly}\t{expires}\t{name}\t{decoded_value}\n"
                        file.write(cookie_str)
                    except Exception as e:
                        print(f"Error processing cookie in profile {profile_path}: {e}")
                
                conn.close()
            except sqlite3.Error as e:
                print(f"Error accessing cookies database in profile {profile_path}: {e}")

if __name__ == "__main__":
    try:
        private_key_path = 'path/to/private_key.pem'  # Update with your private key file path
        private_key = load_private_key(private_key_path)
        
        extract_and_save_cookies(private_key)
        print("Cookies have been extracted to cookies.txt in Netscape format")
    
    except FileNotFoundError as e:
        print(f"Error: {e}")
    
    except Exception as e:
        print(f"Unexpected error occurred: {e}")



find error in the code , if no error tell us