|
|
|
|
|
|
|
|
|
from __future__ import annotations |
|
|
|
import abc |
|
|
|
from cryptography.hazmat.primitives import hashes |
|
from cryptography.hazmat.primitives._asymmetric import ( |
|
AsymmetricPadding as AsymmetricPadding, |
|
) |
|
from cryptography.hazmat.primitives.asymmetric import rsa |
|
|
|
|
|
class PKCS1v15(AsymmetricPadding): |
|
name = "EMSA-PKCS1-v1_5" |
|
|
|
|
|
class _MaxLength: |
|
"Sentinel value for `MAX_LENGTH`." |
|
|
|
|
|
class _Auto: |
|
"Sentinel value for `AUTO`." |
|
|
|
|
|
class _DigestLength: |
|
"Sentinel value for `DIGEST_LENGTH`." |
|
|
|
|
|
class PSS(AsymmetricPadding): |
|
MAX_LENGTH = _MaxLength() |
|
AUTO = _Auto() |
|
DIGEST_LENGTH = _DigestLength() |
|
name = "EMSA-PSS" |
|
_salt_length: int | _MaxLength | _Auto | _DigestLength |
|
|
|
def __init__( |
|
self, |
|
mgf: MGF, |
|
salt_length: int | _MaxLength | _Auto | _DigestLength, |
|
) -> None: |
|
self._mgf = mgf |
|
|
|
if not isinstance( |
|
salt_length, (int, _MaxLength, _Auto, _DigestLength) |
|
): |
|
raise TypeError( |
|
"salt_length must be an integer, MAX_LENGTH, " |
|
"DIGEST_LENGTH, or AUTO" |
|
) |
|
|
|
if isinstance(salt_length, int) and salt_length < 0: |
|
raise ValueError("salt_length must be zero or greater.") |
|
|
|
self._salt_length = salt_length |
|
|
|
@property |
|
def mgf(self) -> MGF: |
|
return self._mgf |
|
|
|
|
|
class OAEP(AsymmetricPadding): |
|
name = "EME-OAEP" |
|
|
|
def __init__( |
|
self, |
|
mgf: MGF, |
|
algorithm: hashes.HashAlgorithm, |
|
label: bytes | None, |
|
): |
|
if not isinstance(algorithm, hashes.HashAlgorithm): |
|
raise TypeError("Expected instance of hashes.HashAlgorithm.") |
|
|
|
self._mgf = mgf |
|
self._algorithm = algorithm |
|
self._label = label |
|
|
|
@property |
|
def algorithm(self) -> hashes.HashAlgorithm: |
|
return self._algorithm |
|
|
|
@property |
|
def mgf(self) -> MGF: |
|
return self._mgf |
|
|
|
|
|
class MGF(metaclass=abc.ABCMeta): |
|
_algorithm: hashes.HashAlgorithm |
|
|
|
|
|
class MGF1(MGF): |
|
MAX_LENGTH = _MaxLength() |
|
|
|
def __init__(self, algorithm: hashes.HashAlgorithm): |
|
if not isinstance(algorithm, hashes.HashAlgorithm): |
|
raise TypeError("Expected instance of hashes.HashAlgorithm.") |
|
|
|
self._algorithm = algorithm |
|
|
|
|
|
def calculate_max_pss_salt_length( |
|
key: rsa.RSAPrivateKey | rsa.RSAPublicKey, |
|
hash_algorithm: hashes.HashAlgorithm, |
|
) -> int: |
|
if not isinstance(key, (rsa.RSAPrivateKey, rsa.RSAPublicKey)): |
|
raise TypeError("key must be an RSA public or private key") |
|
|
|
emlen = (key.key_size + 6) // 8 |
|
salt_length = emlen - hash_algorithm.digest_size - 2 |
|
assert salt_length >= 0 |
|
return salt_length |
|
|