import os import base64 import ascon import hashlib import secrets from cryptography.hazmat.primitives.asymmetric import x25519 from cryptography.hazmat.primitives.kdf.hkdf import HKDF from cryptography.hazmat.primitives import hashes from typing import Tuple def ascon_key_generator() -> str: key = os.urandom(16) return key.hex() def encrypt(key_hex: str, plaintext: str) -> str: key = bytes.fromhex(key_hex) nonce = os.urandom(16) ad = b'' ciphertext = ascon.encrypt(key, nonce, ad, plaintext.encode(), variant="Ascon-AEAD128") combined = nonce + ciphertext data_b64 = base64.b64encode(combined).decode() return data_b64 def decrypt(key_hex: str, data_b64: str) -> str: key = bytes.fromhex(key_hex) combined = base64.b64decode(data_b64) nonce = combined[:16] ciphertext = combined[16:] plaintext = ascon.decrypt(key, nonce, b'', ciphertext, variant="Ascon-AEAD128") return plaintext.decode() def hash_password(password: str) -> str: salt = secrets.token_hex(16) hashed = hashlib.pbkdf2_hmac('sha256', password.encode(), salt.encode(), 100_000) return f"{salt}${hashed.hex()}" def check_password(password: str, stored: str) -> bool: salt, hashed = stored.split('$') new_hash = hashlib.pbkdf2_hmac('sha256', password.encode(), salt.encode(), 100_000) return new_hash.hex() == hashed def salt_randomizer() -> bytes: return secrets.token_bytes(32) def hkdf_sha256(salt: bytes, shared_secret_raw: str) -> str: hkdf = HKDF( algorithm=hashes.SHA256(), length=32, salt=salt, info=b'', ) key_material = hkdf.derive(shared_secret_raw) return key_material def compute_shared_secret(secret_key: bytes, public_key: bytes) -> bytes: secret_key_bytes = x25519.X25519PrivateKey.from_private_bytes(secret_key) public_key_bytes = x25519.X25519PublicKey.from_public_bytes(public_key) shared_secret_raw = secret_key_bytes.exchange(public_key_bytes) return shared_secret_raw def generate_keypair() -> Tuple[x25519.X25519PrivateKey, x25519.X25519PublicKey]: secret_key_bytes = x25519.X25519PrivateKey.generate() public_key_bytes = secret_key_bytes.public_key() return secret_key_bytes, public_key_bytes