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.
4
5from __future__ import annotations
6
7from cryptography import utils
8from cryptography.hazmat.primitives.ciphers import (
9 BlockCipherAlgorithm,
10 CipherAlgorithm,
11)
12
13
14def _verify_key_size(algorithm: CipherAlgorithm, key: bytes) -> bytes:
15 # Verify that the key is instance of bytes
16 utils._check_byteslike("key", key)
17
18 # Verify that the key size matches the expected key size
19 if len(key) * 8 not in algorithm.key_sizes:
20 raise ValueError(
21 f"Invalid key size ({len(key) * 8}) for {algorithm.name}."
22 )
23 return key
24
25
26class AES(BlockCipherAlgorithm):
27 name = "AES"
28 block_size = 128
29 # 512 added to support AES-256-XTS, which uses 512-bit keys
30 key_sizes = frozenset([128, 192, 256, 512])
31
32 def __init__(self, key: bytes):
33 self.key = _verify_key_size(self, key)
34
35 @property
36 def key_size(self) -> int:
37 return len(self.key) * 8
38
39
40class AES128(BlockCipherAlgorithm):
41 name = "AES"
42 block_size = 128
43 key_sizes = frozenset([128])
44 key_size = 128
45
46 def __init__(self, key: bytes):
47 self.key = _verify_key_size(self, key)
48
49
50class AES256(BlockCipherAlgorithm):
51 name = "AES"
52 block_size = 128
53 key_sizes = frozenset([256])
54 key_size = 256
55
56 def __init__(self, key: bytes):
57 self.key = _verify_key_size(self, key)
58
59
60class Camellia(BlockCipherAlgorithm):
61 name = "camellia"
62 block_size = 128
63 key_sizes = frozenset([128, 192, 256])
64
65 def __init__(self, key: bytes):
66 self.key = _verify_key_size(self, key)
67
68 @property
69 def key_size(self) -> int:
70 return len(self.key) * 8
71
72
73class TripleDES(BlockCipherAlgorithm):
74 name = "3DES"
75 block_size = 64
76 key_sizes = frozenset([64, 128, 192])
77
78 def __init__(self, key: bytes):
79 if len(key) == 8:
80 key += key + key
81 elif len(key) == 16:
82 key += key[:8]
83 self.key = _verify_key_size(self, key)
84
85 @property
86 def key_size(self) -> int:
87 return len(self.key) * 8
88
89
90class Blowfish(BlockCipherAlgorithm):
91 name = "Blowfish"
92 block_size = 64
93 key_sizes = frozenset(range(32, 449, 8))
94
95 def __init__(self, key: bytes):
96 self.key = _verify_key_size(self, key)
97
98 @property
99 def key_size(self) -> int:
100 return len(self.key) * 8
101
102
103_BlowfishInternal = Blowfish
104utils.deprecated(
105 Blowfish,
106 __name__,
107 "Blowfish has been deprecated and will be removed in a future release",
108 utils.DeprecatedIn37,
109 name="Blowfish",
110)
111
112
113class CAST5(BlockCipherAlgorithm):
114 name = "CAST5"
115 block_size = 64
116 key_sizes = frozenset(range(40, 129, 8))
117
118 def __init__(self, key: bytes):
119 self.key = _verify_key_size(self, key)
120
121 @property
122 def key_size(self) -> int:
123 return len(self.key) * 8
124
125
126_CAST5Internal = CAST5
127utils.deprecated(
128 CAST5,
129 __name__,
130 "CAST5 has been deprecated and will be removed in a future release",
131 utils.DeprecatedIn37,
132 name="CAST5",
133)
134
135
136class ARC4(CipherAlgorithm):
137 name = "RC4"
138 key_sizes = frozenset([40, 56, 64, 80, 128, 160, 192, 256])
139
140 def __init__(self, key: bytes):
141 self.key = _verify_key_size(self, key)
142
143 @property
144 def key_size(self) -> int:
145 return len(self.key) * 8
146
147
148class IDEA(BlockCipherAlgorithm):
149 name = "IDEA"
150 block_size = 64
151 key_sizes = frozenset([128])
152
153 def __init__(self, key: bytes):
154 self.key = _verify_key_size(self, key)
155
156 @property
157 def key_size(self) -> int:
158 return len(self.key) * 8
159
160
161_IDEAInternal = IDEA
162utils.deprecated(
163 IDEA,
164 __name__,
165 "IDEA has been deprecated and will be removed in a future release",
166 utils.DeprecatedIn37,
167 name="IDEA",
168)
169
170
171class SEED(BlockCipherAlgorithm):
172 name = "SEED"
173 block_size = 128
174 key_sizes = frozenset([128])
175
176 def __init__(self, key: bytes):
177 self.key = _verify_key_size(self, key)
178
179 @property
180 def key_size(self) -> int:
181 return len(self.key) * 8
182
183
184_SEEDInternal = SEED
185utils.deprecated(
186 SEED,
187 __name__,
188 "SEED has been deprecated and will be removed in a future release",
189 utils.DeprecatedIn37,
190 name="SEED",
191)
192
193
194class ChaCha20(CipherAlgorithm):
195 name = "ChaCha20"
196 key_sizes = frozenset([256])
197
198 def __init__(self, key: bytes, nonce: bytes):
199 self.key = _verify_key_size(self, key)
200 utils._check_byteslike("nonce", nonce)
201
202 if len(nonce) != 16:
203 raise ValueError("nonce must be 128-bits (16 bytes)")
204
205 self._nonce = nonce
206
207 @property
208 def nonce(self) -> bytes:
209 return self._nonce
210
211 @property
212 def key_size(self) -> int:
213 return len(self.key) * 8
214
215
216class SM4(BlockCipherAlgorithm):
217 name = "SM4"
218 block_size = 128
219 key_sizes = frozenset([128])
220
221 def __init__(self, key: bytes):
222 self.key = _verify_key_size(self, key)
223
224 @property
225 def key_size(self) -> int:
226 return len(self.key) * 8