[fix] Mypy Coffre Secrets (3 erreurs) + version 2.80.2 #27
@@ -24,14 +24,19 @@ import logging
|
||||
import os
|
||||
import stat
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
logger = logging.getLogger("obsigate.coffre_crypto")
|
||||
|
||||
# Annotation explicite : sans elle, mypy refuse l'assignation de deux types
|
||||
# (la classe AESGCM importée, puis None dans le repli sans cryptography)
|
||||
# et le commentaire `type: ignore[assignment]` ne couvre pas ce code [misc].
|
||||
AESGCM: type[Any] | None
|
||||
try: # cryptography est une dépendance de la Phase 1a (requirements.txt)
|
||||
from cryptography.exceptions import InvalidTag
|
||||
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
||||
except Exception: # pragma: no cover - environnement sans cryptography
|
||||
AESGCM = None # type: ignore[assignment]
|
||||
AESGCM = None
|
||||
InvalidTag = Exception # type: ignore[assignment,misc]
|
||||
|
||||
|
||||
@@ -55,11 +60,17 @@ class CryptoIndisponibleError(CoffreCryptoError):
|
||||
"""La bibliothèque ``cryptography`` n'est pas installée."""
|
||||
|
||||
|
||||
def _require_aesgcm() -> None:
|
||||
def _require_aesgcm() -> type[Any]:
|
||||
"""Retourne la classe AESGCM, ou lève si cryptography est absent.
|
||||
|
||||
Retourner la classe (plutôt qu'un simple garde) permet à mypy de
|
||||
savoir que l'appelant détient bien un constructible, et non None.
|
||||
"""
|
||||
if AESGCM is None:
|
||||
raise CryptoIndisponibleError(
|
||||
"cryptography n'est pas installé (dépendance Phase 1a)"
|
||||
)
|
||||
return AESGCM
|
||||
|
||||
|
||||
def parse_kek(raw: str) -> bytes:
|
||||
@@ -146,17 +157,17 @@ def _unb64(value: str) -> bytes:
|
||||
|
||||
def encrypt_with_key(key: bytes, plaintext: bytes, aad: bytes) -> dict:
|
||||
"""Chiffre avec AES-256-GCM. Retourne {nonce, ciphertext} en base64."""
|
||||
_require_aesgcm()
|
||||
aesgcm = _require_aesgcm()
|
||||
nonce = os.urandom(12)
|
||||
ciphertext = AESGCM(key).encrypt(nonce, plaintext, aad)
|
||||
ciphertext = aesgcm(key).encrypt(nonce, plaintext, aad)
|
||||
return {"nonce": _b64(nonce), "ciphertext": _b64(ciphertext)}
|
||||
|
||||
|
||||
def decrypt_with_key(key: bytes, nonce_b64: str, ciphertext_b64: str, aad: bytes) -> bytes:
|
||||
"""Déchiffre avec AES-256-GCM. Tag invalide -> TagInvalideError."""
|
||||
_require_aesgcm()
|
||||
aesgcm = _require_aesgcm()
|
||||
try:
|
||||
return AESGCM(key).decrypt(_unb64(nonce_b64), _unb64(ciphertext_b64), aad)
|
||||
return aesgcm(key).decrypt(_unb64(nonce_b64), _unb64(ciphertext_b64), aad)
|
||||
except InvalidTag as exc:
|
||||
raise TagInvalideError("Tag GCM invalide : données altérées ou mauvaise clé") from exc
|
||||
except (binascii.Error, ValueError) as exc:
|
||||
|
||||
Reference in New Issue
Block a user