Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py: 60%
135 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 07:26 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 07:26 +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.hazmat.bindings._rust import openssl as rust_openssl
11from cryptography.hazmat.primitives import _serialization, hashes
12from cryptography.hazmat.primitives.asymmetric import utils as asym_utils
15class DSAParameters(metaclass=abc.ABCMeta):
16 @abc.abstractmethod
17 def generate_private_key(self) -> DSAPrivateKey:
18 """
19 Generates and returns a DSAPrivateKey.
20 """
22 @abc.abstractmethod
23 def parameter_numbers(self) -> DSAParameterNumbers:
24 """
25 Returns a DSAParameterNumbers.
26 """
29DSAParametersWithNumbers = DSAParameters
30DSAParameters.register(rust_openssl.dsa.DSAParameters)
33class DSAPrivateKey(metaclass=abc.ABCMeta):
34 @property
35 @abc.abstractmethod
36 def key_size(self) -> int:
37 """
38 The bit length of the prime modulus.
39 """
41 @abc.abstractmethod
42 def public_key(self) -> DSAPublicKey:
43 """
44 The DSAPublicKey associated with this private key.
45 """
47 @abc.abstractmethod
48 def parameters(self) -> DSAParameters:
49 """
50 The DSAParameters object associated with this private key.
51 """
53 @abc.abstractmethod
54 def sign(
55 self,
56 data: bytes,
57 algorithm: asym_utils.Prehashed | hashes.HashAlgorithm,
58 ) -> bytes:
59 """
60 Signs the data
61 """
63 @abc.abstractmethod
64 def private_numbers(self) -> DSAPrivateNumbers:
65 """
66 Returns a DSAPrivateNumbers.
67 """
69 @abc.abstractmethod
70 def private_bytes(
71 self,
72 encoding: _serialization.Encoding,
73 format: _serialization.PrivateFormat,
74 encryption_algorithm: _serialization.KeySerializationEncryption,
75 ) -> bytes:
76 """
77 Returns the key serialized as bytes.
78 """
81DSAPrivateKeyWithSerialization = DSAPrivateKey
82DSAPrivateKey.register(rust_openssl.dsa.DSAPrivateKey)
85class DSAPublicKey(metaclass=abc.ABCMeta):
86 @property
87 @abc.abstractmethod
88 def key_size(self) -> int:
89 """
90 The bit length of the prime modulus.
91 """
93 @abc.abstractmethod
94 def parameters(self) -> DSAParameters:
95 """
96 The DSAParameters object associated with this public key.
97 """
99 @abc.abstractmethod
100 def public_numbers(self) -> DSAPublicNumbers:
101 """
102 Returns a DSAPublicNumbers.
103 """
105 @abc.abstractmethod
106 def public_bytes(
107 self,
108 encoding: _serialization.Encoding,
109 format: _serialization.PublicFormat,
110 ) -> bytes:
111 """
112 Returns the key serialized as bytes.
113 """
115 @abc.abstractmethod
116 def verify(
117 self,
118 signature: bytes,
119 data: bytes,
120 algorithm: asym_utils.Prehashed | hashes.HashAlgorithm,
121 ) -> None:
122 """
123 Verifies the signature of the data.
124 """
126 @abc.abstractmethod
127 def __eq__(self, other: object) -> bool:
128 """
129 Checks equality.
130 """
133DSAPublicKeyWithSerialization = DSAPublicKey
134DSAPublicKey.register(rust_openssl.dsa.DSAPublicKey)
137class DSAParameterNumbers:
138 def __init__(self, p: int, q: int, g: int):
139 if (
140 not isinstance(p, int)
141 or not isinstance(q, int)
142 or not isinstance(g, int)
143 ):
144 raise TypeError(
145 "DSAParameterNumbers p, q, and g arguments must be integers."
146 )
148 self._p = p
149 self._q = q
150 self._g = g
152 @property
153 def p(self) -> int:
154 return self._p
156 @property
157 def q(self) -> int:
158 return self._q
160 @property
161 def g(self) -> int:
162 return self._g
164 def parameters(self, backend: typing.Any = None) -> DSAParameters:
165 _check_dsa_parameters(self)
166 return rust_openssl.dsa.from_parameter_numbers(self)
168 def __eq__(self, other: object) -> bool:
169 if not isinstance(other, DSAParameterNumbers):
170 return NotImplemented
172 return self.p == other.p and self.q == other.q and self.g == other.g
174 def __repr__(self) -> str:
175 return f"<DSAParameterNumbers(p={self.p}, q={self.q}, " f"g={self.g})>"
178class DSAPublicNumbers:
179 def __init__(self, y: int, parameter_numbers: DSAParameterNumbers):
180 if not isinstance(y, int):
181 raise TypeError("DSAPublicNumbers y argument must be an integer.")
183 if not isinstance(parameter_numbers, DSAParameterNumbers):
184 raise TypeError(
185 "parameter_numbers must be a DSAParameterNumbers instance."
186 )
188 self._y = y
189 self._parameter_numbers = parameter_numbers
191 @property
192 def y(self) -> int:
193 return self._y
195 @property
196 def parameter_numbers(self) -> DSAParameterNumbers:
197 return self._parameter_numbers
199 def public_key(self, backend: typing.Any = None) -> DSAPublicKey:
200 _check_dsa_parameters(self.parameter_numbers)
201 return rust_openssl.dsa.from_public_numbers(self)
203 def __eq__(self, other: object) -> bool:
204 if not isinstance(other, DSAPublicNumbers):
205 return NotImplemented
207 return (
208 self.y == other.y
209 and self.parameter_numbers == other.parameter_numbers
210 )
212 def __repr__(self) -> str:
213 return (
214 f"<DSAPublicNumbers(y={self.y}, "
215 f"parameter_numbers={self.parameter_numbers})>"
216 )
219class DSAPrivateNumbers:
220 def __init__(self, x: int, public_numbers: DSAPublicNumbers):
221 if not isinstance(x, int):
222 raise TypeError("DSAPrivateNumbers x argument must be an integer.")
224 if not isinstance(public_numbers, DSAPublicNumbers):
225 raise TypeError(
226 "public_numbers must be a DSAPublicNumbers instance."
227 )
228 self._public_numbers = public_numbers
229 self._x = x
231 @property
232 def x(self) -> int:
233 return self._x
235 @property
236 def public_numbers(self) -> DSAPublicNumbers:
237 return self._public_numbers
239 def private_key(self, backend: typing.Any = None) -> DSAPrivateKey:
240 _check_dsa_private_numbers(self)
241 return rust_openssl.dsa.from_private_numbers(self)
243 def __eq__(self, other: object) -> bool:
244 if not isinstance(other, DSAPrivateNumbers):
245 return NotImplemented
247 return (
248 self.x == other.x and self.public_numbers == other.public_numbers
249 )
252def generate_parameters(
253 key_size: int, backend: typing.Any = None
254) -> DSAParameters:
255 if key_size not in (1024, 2048, 3072, 4096):
256 raise ValueError("Key size must be 1024, 2048, 3072, or 4096 bits.")
258 return rust_openssl.dsa.generate_parameters(key_size)
261def generate_private_key(
262 key_size: int, backend: typing.Any = None
263) -> DSAPrivateKey:
264 parameters = generate_parameters(key_size)
265 return parameters.generate_private_key()
268def _check_dsa_parameters(parameters: DSAParameterNumbers) -> None:
269 if parameters.p.bit_length() not in [1024, 2048, 3072, 4096]:
270 raise ValueError(
271 "p must be exactly 1024, 2048, 3072, or 4096 bits long"
272 )
273 if parameters.q.bit_length() not in [160, 224, 256]:
274 raise ValueError("q must be exactly 160, 224, or 256 bits long")
276 if not (1 < parameters.g < parameters.p):
277 raise ValueError("g, p don't satisfy 1 < g < p.")
280def _check_dsa_private_numbers(numbers: DSAPrivateNumbers) -> None:
281 parameters = numbers.public_numbers.parameter_numbers
282 _check_dsa_parameters(parameters)
283 if numbers.x <= 0 or numbers.x >= parameters.q:
284 raise ValueError("x must be > 0 and < q.")
286 if numbers.public_numbers.y != pow(parameters.g, numbers.x, parameters.p):
287 raise ValueError("y must be equal to (g ** x % p).")