123
This commit is contained in:
44
backend/shared/crypto.py
Normal file
44
backend/shared/crypto.py
Normal file
@@ -0,0 +1,44 @@
|
||||
"""
|
||||
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")
|
||||
Reference in New Issue
Block a user