summaryrefslogtreecommitdiffstats
path: root/g4f/Provider/openai/crypt.py
blob: e7f351900d970a743468b03dfa7bd7a421a53f52 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import json
import base64
import hashlib
import random
from Crypto.Cipher import AES

def pad(data: str) -> bytes:
    # Convert the string to bytes and calculate the number of bytes to pad
    data_bytes = data.encode()
    padding = 16 - (len(data_bytes) % 16)
    # Append the padding bytes with their value
    return data_bytes + bytes([padding] * padding)

def encrypt(data, key):
    salt = ""
    salted = ""
    dx = bytes()

    # Generate salt, as 8 random lowercase letters
    salt = "".join(random.choice("abcdefghijklmnopqrstuvwxyz") for _ in range(8))

    # Our final key and IV come from the key and salt being repeatedly hashed
    for x in range(3):
        dx = hashlib.md5(dx + key.encode() + salt.encode()).digest()
        salted += dx.hex()

    # Pad the data before encryption
    data = pad(data)

    aes = AES.new(
        bytes.fromhex(salted[:64]), AES.MODE_CBC, bytes.fromhex(salted[64:96])
    )

    return json.dumps(
        {
            "ct": base64.b64encode(aes.encrypt(data)).decode(),
            "iv": salted[64:96],
            "s": salt.encode().hex(),
        }
    )

def unpad(data: bytes) -> bytes:
    # Extract the padding value from the last byte and remove padding
    padding_value = data[-1]
    return data[:-padding_value]

def decrypt(data: str, key: str):
    # Parse JSON data
    parsed_data = json.loads(base64.b64decode(data))
    ct = base64.b64decode(parsed_data["ct"])
    iv = bytes.fromhex(parsed_data["iv"])
    salt = bytes.fromhex(parsed_data["s"])

    salted = ''
    dx = b''
    for x in range(3):
        dx = hashlib.md5(dx + key.encode() + salt).digest()
        salted += dx.hex()
        
    aes = AES.new(
        bytes.fromhex(salted[:64]), AES.MODE_CBC, iv
    )

    data = aes.decrypt(ct)
    if data.startswith(b'[{"key":'):
        return unpad(data).decode()