Source Code

/ src / blog / crypto.py

from Crypto.Cipher import AES
from Crypto.Hash import MD5
from Crypto.Random import get_random_bytes
import base64

def evp_bytes_to_key(password: bytes, salt: bytes, key_len: int, iv_len: int):
    """
    OpenSSL-compatible key derivation (MD5)
    """
    dtot = b""
    d = b""
    while len(dtot) < key_len + iv_len:
        d = MD5.new(d + password + salt).digest()
        dtot += d
    return dtot[:key_len], dtot[key_len:key_len + iv_len]

def encrypt_for_cryptojs(plaintext: str, password: str) -> str:
    plaintext_bytes = plaintext.encode("utf-8")
    salt = get_random_bytes(8)  # OpenSSL salt

    key, iv = evp_bytes_to_key(password.encode("utf-8"), salt, 32, 16)
    cipher = AES.new(key, AES.MODE_CBC, iv)

    pad_len = 16 - (len(plaintext_bytes) % 16)
    padded = plaintext_bytes + bytes([pad_len]) * pad_len

    ciphertext = cipher.encrypt(padded)

    openssl_bytes = b"Salted__" + salt + ciphertext
    return base64.b64encode(openssl_bytes).decode("utf-8")