""" Signatures numériques pour authentification et non-répudiation. """ from cryptography.hazmat.primitives.asymmetric import rsa, padding, utils from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.backends import default_backend import os from typing import Tuple class DigitalSignature: """ Signatures RSA-PSS pour authentification et non-répudiation. Propriétés: - Non-répudiation (l'auteur ne peut pas nier) - Authentification de l'origine - Intégrité des données """ def __init__(self, key_size: int = 2048): self.key_size = key_size self.backend = default_backend() def generate_keypair(self) -> Tuple[bytes, bytes]: """ Générer une paire de clés RSA. Returns: (private_key_pem, public_key_pem) """ private_key = rsa.generate_private_key( public_exponent=65537, key_size=self.key_size, backend=self.backend ) private_pem = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption() ) public_pem = private_key.public_key().public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo ) return private_pem, public_pem def sign(self, private_key_pem: bytes, message: bytes) -> bytes: """ Signer un message avec la clé privée. """ private_key = serialization.load_pem_private_key( private_key_pem, password=None, backend=self.backend ) signature = private_key.sign( message, padding.PSS( mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH ), hashes.SHA256() ) return signature def verify(self, public_key_pem: bytes, message: bytes, signature: bytes) -> bool: """ Vérifier la signature d'un message. Returns: True si la signature est valide, False sinon """ try: public_key = serialization.load_pem_public_key( public_key_pem, backend=self.backend ) public_key.verify( signature, message, padding.PSS( mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH ), hashes.SHA256() ) return True except Exception: return False