|
from __future__ import annotations |
|
|
|
import json |
|
import base64 |
|
import hashlib |
|
import random |
|
from Crypto.Cipher import AES |
|
|
|
def pad(data: str) -> bytes: |
|
|
|
data_bytes = data.encode() |
|
padding = 16 - (len(data_bytes) % 16) |
|
|
|
return data_bytes + bytes([padding] * padding) |
|
|
|
def encrypt(data, key): |
|
salt = "" |
|
salted = "" |
|
dx = bytes() |
|
|
|
|
|
salt = "".join(random.choice("abcdefghijklmnopqrstuvwxyz") for _ in range(8)) |
|
|
|
|
|
for x in range(3): |
|
dx = hashlib.md5(dx + key.encode() + salt.encode()).digest() |
|
salted += dx.hex() |
|
|
|
|
|
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: |
|
|
|
padding_value = data[-1] |
|
return data[:-padding_value] |
|
|
|
def decrypt(data: str, key: str): |
|
|
|
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() |