You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gpt4free/g4f/Provider/openai/crypt.py

66 lines
1.8 KiB
Python

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()