Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/cryptography/hazmat/primitives/_serialization.py: 56%
80 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:05 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:05 +0000
1# This file is dual licensed under the terms of the Apache License, Version
2# 2.0, and the BSD License. See the LICENSE file in the root of this repository
3# for complete details.
5from __future__ import annotations
7import abc
8import typing
10from cryptography import utils
11from cryptography.hazmat.primitives.hashes import HashAlgorithm
13# This exists to break an import cycle. These classes are normally accessible
14# from the serialization module.
17class PBES(utils.Enum):
18 PBESv1SHA1And3KeyTripleDESCBC = "PBESv1 using SHA1 and 3-Key TripleDES"
19 PBESv2SHA256AndAES256CBC = "PBESv2 using SHA256 PBKDF2 and AES256 CBC"
22class Encoding(utils.Enum):
23 PEM = "PEM"
24 DER = "DER"
25 OpenSSH = "OpenSSH"
26 Raw = "Raw"
27 X962 = "ANSI X9.62"
28 SMIME = "S/MIME"
31class PrivateFormat(utils.Enum):
32 PKCS8 = "PKCS8"
33 TraditionalOpenSSL = "TraditionalOpenSSL"
34 Raw = "Raw"
35 OpenSSH = "OpenSSH"
36 PKCS12 = "PKCS12"
38 def encryption_builder(self) -> KeySerializationEncryptionBuilder:
39 if self not in (PrivateFormat.OpenSSH, PrivateFormat.PKCS12):
40 raise ValueError(
41 "encryption_builder only supported with PrivateFormat.OpenSSH"
42 " and PrivateFormat.PKCS12"
43 )
44 return KeySerializationEncryptionBuilder(self)
47class PublicFormat(utils.Enum):
48 SubjectPublicKeyInfo = "X.509 subjectPublicKeyInfo with PKCS#1"
49 PKCS1 = "Raw PKCS#1"
50 OpenSSH = "OpenSSH"
51 Raw = "Raw"
52 CompressedPoint = "X9.62 Compressed Point"
53 UncompressedPoint = "X9.62 Uncompressed Point"
56class ParameterFormat(utils.Enum):
57 PKCS3 = "PKCS3"
60class KeySerializationEncryption(metaclass=abc.ABCMeta):
61 pass
64class BestAvailableEncryption(KeySerializationEncryption):
65 def __init__(self, password: bytes):
66 if not isinstance(password, bytes) or len(password) == 0:
67 raise ValueError("Password must be 1 or more bytes.")
69 self.password = password
72class NoEncryption(KeySerializationEncryption):
73 pass
76class KeySerializationEncryptionBuilder:
77 def __init__(
78 self,
79 format: PrivateFormat,
80 *,
81 _kdf_rounds: typing.Optional[int] = None,
82 _hmac_hash: typing.Optional[HashAlgorithm] = None,
83 _key_cert_algorithm: typing.Optional[PBES] = None,
84 ) -> None:
85 self._format = format
87 self._kdf_rounds = _kdf_rounds
88 self._hmac_hash = _hmac_hash
89 self._key_cert_algorithm = _key_cert_algorithm
91 def kdf_rounds(self, rounds: int) -> KeySerializationEncryptionBuilder:
92 if self._kdf_rounds is not None:
93 raise ValueError("kdf_rounds already set")
95 if not isinstance(rounds, int):
96 raise TypeError("kdf_rounds must be an integer")
98 if rounds < 1:
99 raise ValueError("kdf_rounds must be a positive integer")
101 return KeySerializationEncryptionBuilder(
102 self._format,
103 _kdf_rounds=rounds,
104 _hmac_hash=self._hmac_hash,
105 _key_cert_algorithm=self._key_cert_algorithm,
106 )
108 def hmac_hash(
109 self, algorithm: HashAlgorithm
110 ) -> KeySerializationEncryptionBuilder:
111 if self._format is not PrivateFormat.PKCS12:
112 raise TypeError(
113 "hmac_hash only supported with PrivateFormat.PKCS12"
114 )
116 if self._hmac_hash is not None:
117 raise ValueError("hmac_hash already set")
118 return KeySerializationEncryptionBuilder(
119 self._format,
120 _kdf_rounds=self._kdf_rounds,
121 _hmac_hash=algorithm,
122 _key_cert_algorithm=self._key_cert_algorithm,
123 )
125 def key_cert_algorithm(
126 self, algorithm: PBES
127 ) -> KeySerializationEncryptionBuilder:
128 if self._format is not PrivateFormat.PKCS12:
129 raise TypeError(
130 "key_cert_algorithm only supported with "
131 "PrivateFormat.PKCS12"
132 )
133 if self._key_cert_algorithm is not None:
134 raise ValueError("key_cert_algorithm already set")
135 return KeySerializationEncryptionBuilder(
136 self._format,
137 _kdf_rounds=self._kdf_rounds,
138 _hmac_hash=self._hmac_hash,
139 _key_cert_algorithm=algorithm,
140 )
142 def build(self, password: bytes) -> KeySerializationEncryption:
143 if not isinstance(password, bytes) or len(password) == 0:
144 raise ValueError("Password must be 1 or more bytes.")
146 return _KeySerializationEncryption(
147 self._format,
148 password,
149 kdf_rounds=self._kdf_rounds,
150 hmac_hash=self._hmac_hash,
151 key_cert_algorithm=self._key_cert_algorithm,
152 )
155class _KeySerializationEncryption(KeySerializationEncryption):
156 def __init__(
157 self,
158 format: PrivateFormat,
159 password: bytes,
160 *,
161 kdf_rounds: typing.Optional[int],
162 hmac_hash: typing.Optional[HashAlgorithm],
163 key_cert_algorithm: typing.Optional[PBES],
164 ):
165 self._format = format
166 self.password = password
168 self._kdf_rounds = kdf_rounds
169 self._hmac_hash = hmac_hash
170 self._key_cert_algorithm = key_cert_algorithm