123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- # This file is dual licensed under the terms of the Apache License, Version
- # 2.0, and the BSD License. See the LICENSE file in the root of this repository
- # for complete details.
- from __future__ import annotations
- import abc
- from cryptography import utils
- from cryptography.hazmat.primitives.hashes import HashAlgorithm
- # This exists to break an import cycle. These classes are normally accessible
- # from the serialization module.
- class PBES(utils.Enum):
- PBESv1SHA1And3KeyTripleDESCBC = "PBESv1 using SHA1 and 3-Key TripleDES"
- PBESv2SHA256AndAES256CBC = "PBESv2 using SHA256 PBKDF2 and AES256 CBC"
- class Encoding(utils.Enum):
- PEM = "PEM"
- DER = "DER"
- OpenSSH = "OpenSSH"
- Raw = "Raw"
- X962 = "ANSI X9.62"
- SMIME = "S/MIME"
- class PrivateFormat(utils.Enum):
- PKCS8 = "PKCS8"
- TraditionalOpenSSL = "TraditionalOpenSSL"
- Raw = "Raw"
- OpenSSH = "OpenSSH"
- PKCS12 = "PKCS12"
- def encryption_builder(self) -> KeySerializationEncryptionBuilder:
- if self not in (PrivateFormat.OpenSSH, PrivateFormat.PKCS12):
- raise ValueError(
- "encryption_builder only supported with PrivateFormat.OpenSSH"
- " and PrivateFormat.PKCS12"
- )
- return KeySerializationEncryptionBuilder(self)
- class PublicFormat(utils.Enum):
- SubjectPublicKeyInfo = "X.509 subjectPublicKeyInfo with PKCS#1"
- PKCS1 = "Raw PKCS#1"
- OpenSSH = "OpenSSH"
- Raw = "Raw"
- CompressedPoint = "X9.62 Compressed Point"
- UncompressedPoint = "X9.62 Uncompressed Point"
- class ParameterFormat(utils.Enum):
- PKCS3 = "PKCS3"
- class KeySerializationEncryption(metaclass=abc.ABCMeta):
- pass
- class BestAvailableEncryption(KeySerializationEncryption):
- def __init__(self, password: bytes):
- if not isinstance(password, bytes) or len(password) == 0:
- raise ValueError("Password must be 1 or more bytes.")
- self.password = password
- class NoEncryption(KeySerializationEncryption):
- pass
- class KeySerializationEncryptionBuilder:
- def __init__(
- self,
- format: PrivateFormat,
- *,
- _kdf_rounds: int | None = None,
- _hmac_hash: HashAlgorithm | None = None,
- _key_cert_algorithm: PBES | None = None,
- ) -> None:
- self._format = format
- self._kdf_rounds = _kdf_rounds
- self._hmac_hash = _hmac_hash
- self._key_cert_algorithm = _key_cert_algorithm
- def kdf_rounds(self, rounds: int) -> KeySerializationEncryptionBuilder:
- if self._kdf_rounds is not None:
- raise ValueError("kdf_rounds already set")
- if not isinstance(rounds, int):
- raise TypeError("kdf_rounds must be an integer")
- if rounds < 1:
- raise ValueError("kdf_rounds must be a positive integer")
- return KeySerializationEncryptionBuilder(
- self._format,
- _kdf_rounds=rounds,
- _hmac_hash=self._hmac_hash,
- _key_cert_algorithm=self._key_cert_algorithm,
- )
- def hmac_hash(
- self, algorithm: HashAlgorithm
- ) -> KeySerializationEncryptionBuilder:
- if self._format is not PrivateFormat.PKCS12:
- raise TypeError(
- "hmac_hash only supported with PrivateFormat.PKCS12"
- )
- if self._hmac_hash is not None:
- raise ValueError("hmac_hash already set")
- return KeySerializationEncryptionBuilder(
- self._format,
- _kdf_rounds=self._kdf_rounds,
- _hmac_hash=algorithm,
- _key_cert_algorithm=self._key_cert_algorithm,
- )
- def key_cert_algorithm(
- self, algorithm: PBES
- ) -> KeySerializationEncryptionBuilder:
- if self._format is not PrivateFormat.PKCS12:
- raise TypeError(
- "key_cert_algorithm only supported with "
- "PrivateFormat.PKCS12"
- )
- if self._key_cert_algorithm is not None:
- raise ValueError("key_cert_algorithm already set")
- return KeySerializationEncryptionBuilder(
- self._format,
- _kdf_rounds=self._kdf_rounds,
- _hmac_hash=self._hmac_hash,
- _key_cert_algorithm=algorithm,
- )
- def build(self, password: bytes) -> KeySerializationEncryption:
- if not isinstance(password, bytes) or len(password) == 0:
- raise ValueError("Password must be 1 or more bytes.")
- return _KeySerializationEncryption(
- self._format,
- password,
- kdf_rounds=self._kdf_rounds,
- hmac_hash=self._hmac_hash,
- key_cert_algorithm=self._key_cert_algorithm,
- )
- class _KeySerializationEncryption(KeySerializationEncryption):
- def __init__(
- self,
- format: PrivateFormat,
- password: bytes,
- *,
- kdf_rounds: int | None,
- hmac_hash: HashAlgorithm | None,
- key_cert_algorithm: PBES | None,
- ):
- self._format = format
- self.password = password
- self._kdf_rounds = kdf_rounds
- self._hmac_hash = hmac_hash
- self._key_cert_algorithm = key_cert_algorithm
|