Files
weibo_signin/backend/shared/crypto.py

45 lines
1.4 KiB
Python
Raw Normal View History

2026-03-09 14:05:00 +08:00
"""
AES-256-GCM Cookie encryption / decryption utilities.
"""
import base64
import hashlib
from Crypto.Cipher import AES
def derive_key(raw_key: str) -> bytes:
"""Derive a 32-byte key from an arbitrary string using SHA-256."""
return hashlib.sha256(raw_key.encode("utf-8")).digest()
def encrypt_cookie(plaintext: str, key: bytes) -> tuple[str, str]:
"""
Encrypt a cookie string with AES-256-GCM.
Returns:
(ciphertext_b64, iv_b64) both base64-encoded strings.
"""
cipher = AES.new(key, AES.MODE_GCM)
ciphertext, tag = cipher.encrypt_and_digest(plaintext.encode("utf-8"))
# Append the 16-byte tag to the ciphertext so decryption can verify it
ciphertext_with_tag = ciphertext + tag
ciphertext_b64 = base64.b64encode(ciphertext_with_tag).decode("utf-8")
iv_b64 = base64.b64encode(cipher.nonce).decode("utf-8")
return ciphertext_b64, iv_b64
def decrypt_cookie(ciphertext_b64: str, iv_b64: str, key: bytes) -> str:
"""
Decrypt a cookie string previously encrypted with encrypt_cookie.
Raises ValueError on decryption failure (wrong key, corrupted data, etc.).
"""
raw = base64.b64decode(ciphertext_b64)
nonce = base64.b64decode(iv_b64)
# Last 16 bytes are the GCM tag
ciphertext, tag = raw[:-16], raw[-16:]
cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
plaintext = cipher.decrypt_and_verify(ciphertext, tag)
return plaintext.decode("utf-8")