72 lines
2.2 KiB
Python
72 lines
2.2 KiB
Python
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 |