Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py: 54%

125 statements  

« prev     ^ index     » next       coverage.py v7.0.1, created at 2022-12-25 06:11 +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. 

4 

5 

6import abc 

7import typing 

8 

9from cryptography.hazmat.primitives import _serialization, hashes 

10from cryptography.hazmat.primitives.asymmetric import ( 

11 utils as asym_utils, 

12) 

13 

14 

15class DSAParameters(metaclass=abc.ABCMeta): 

16 @abc.abstractmethod 

17 def generate_private_key(self) -> "DSAPrivateKey": 

18 """ 

19 Generates and returns a DSAPrivateKey. 

20 """ 

21 

22 @abc.abstractmethod 

23 def parameter_numbers(self) -> "DSAParameterNumbers": 

24 """ 

25 Returns a DSAParameterNumbers. 

26 """ 

27 

28 

29DSAParametersWithNumbers = DSAParameters 

30 

31 

32class DSAPrivateKey(metaclass=abc.ABCMeta): 

33 @abc.abstractproperty 

34 def key_size(self) -> int: 

35 """ 

36 The bit length of the prime modulus. 

37 """ 

38 

39 @abc.abstractmethod 

40 def public_key(self) -> "DSAPublicKey": 

41 """ 

42 The DSAPublicKey associated with this private key. 

43 """ 

44 

45 @abc.abstractmethod 

46 def parameters(self) -> DSAParameters: 

47 """ 

48 The DSAParameters object associated with this private key. 

49 """ 

50 

51 @abc.abstractmethod 

52 def sign( 

53 self, 

54 data: bytes, 

55 algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], 

56 ) -> bytes: 

57 """ 

58 Signs the data 

59 """ 

60 

61 @abc.abstractmethod 

62 def private_numbers(self) -> "DSAPrivateNumbers": 

63 """ 

64 Returns a DSAPrivateNumbers. 

65 """ 

66 

67 @abc.abstractmethod 

68 def private_bytes( 

69 self, 

70 encoding: _serialization.Encoding, 

71 format: _serialization.PrivateFormat, 

72 encryption_algorithm: _serialization.KeySerializationEncryption, 

73 ) -> bytes: 

74 """ 

75 Returns the key serialized as bytes. 

76 """ 

77 

78 

79DSAPrivateKeyWithSerialization = DSAPrivateKey 

80 

81 

82class DSAPublicKey(metaclass=abc.ABCMeta): 

83 @abc.abstractproperty 

84 def key_size(self) -> int: 

85 """ 

86 The bit length of the prime modulus. 

87 """ 

88 

89 @abc.abstractmethod 

90 def parameters(self) -> DSAParameters: 

91 """ 

92 The DSAParameters object associated with this public key. 

93 """ 

94 

95 @abc.abstractmethod 

96 def public_numbers(self) -> "DSAPublicNumbers": 

97 """ 

98 Returns a DSAPublicNumbers. 

99 """ 

100 

101 @abc.abstractmethod 

102 def public_bytes( 

103 self, 

104 encoding: _serialization.Encoding, 

105 format: _serialization.PublicFormat, 

106 ) -> bytes: 

107 """ 

108 Returns the key serialized as bytes. 

109 """ 

110 

111 @abc.abstractmethod 

112 def verify( 

113 self, 

114 signature: bytes, 

115 data: bytes, 

116 algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], 

117 ) -> None: 

118 """ 

119 Verifies the signature of the data. 

120 """ 

121 

122 

123DSAPublicKeyWithSerialization = DSAPublicKey 

124 

125 

126class DSAParameterNumbers: 

127 def __init__(self, p: int, q: int, g: int): 

128 if ( 

129 not isinstance(p, int) 

130 or not isinstance(q, int) 

131 or not isinstance(g, int) 

132 ): 

133 raise TypeError( 

134 "DSAParameterNumbers p, q, and g arguments must be integers." 

135 ) 

136 

137 self._p = p 

138 self._q = q 

139 self._g = g 

140 

141 @property 

142 def p(self) -> int: 

143 return self._p 

144 

145 @property 

146 def q(self) -> int: 

147 return self._q 

148 

149 @property 

150 def g(self) -> int: 

151 return self._g 

152 

153 def parameters(self, backend: typing.Any = None) -> DSAParameters: 

154 from cryptography.hazmat.backends.openssl.backend import ( 

155 backend as ossl, 

156 ) 

157 

158 return ossl.load_dsa_parameter_numbers(self) 

159 

160 def __eq__(self, other: object) -> bool: 

161 if not isinstance(other, DSAParameterNumbers): 

162 return NotImplemented 

163 

164 return self.p == other.p and self.q == other.q and self.g == other.g 

165 

166 def __repr__(self) -> str: 

167 return ( 

168 "<DSAParameterNumbers(p={self.p}, q={self.q}, " 

169 "g={self.g})>".format(self=self) 

170 ) 

171 

172 

173class DSAPublicNumbers: 

174 def __init__(self, y: int, parameter_numbers: DSAParameterNumbers): 

175 if not isinstance(y, int): 

176 raise TypeError("DSAPublicNumbers y argument must be an integer.") 

177 

178 if not isinstance(parameter_numbers, DSAParameterNumbers): 

179 raise TypeError( 

180 "parameter_numbers must be a DSAParameterNumbers instance." 

181 ) 

182 

183 self._y = y 

184 self._parameter_numbers = parameter_numbers 

185 

186 @property 

187 def y(self) -> int: 

188 return self._y 

189 

190 @property 

191 def parameter_numbers(self) -> DSAParameterNumbers: 

192 return self._parameter_numbers 

193 

194 def public_key(self, backend: typing.Any = None) -> DSAPublicKey: 

195 from cryptography.hazmat.backends.openssl.backend import ( 

196 backend as ossl, 

197 ) 

198 

199 return ossl.load_dsa_public_numbers(self) 

200 

201 def __eq__(self, other: object) -> bool: 

202 if not isinstance(other, DSAPublicNumbers): 

203 return NotImplemented 

204 

205 return ( 

206 self.y == other.y 

207 and self.parameter_numbers == other.parameter_numbers 

208 ) 

209 

210 def __repr__(self) -> str: 

211 return ( 

212 "<DSAPublicNumbers(y={self.y}, " 

213 "parameter_numbers={self.parameter_numbers})>".format(self=self) 

214 ) 

215 

216 

217class DSAPrivateNumbers: 

218 def __init__(self, x: int, public_numbers: DSAPublicNumbers): 

219 if not isinstance(x, int): 

220 raise TypeError("DSAPrivateNumbers x argument must be an integer.") 

221 

222 if not isinstance(public_numbers, DSAPublicNumbers): 

223 raise TypeError( 

224 "public_numbers must be a DSAPublicNumbers instance." 

225 ) 

226 self._public_numbers = public_numbers 

227 self._x = x 

228 

229 @property 

230 def x(self) -> int: 

231 return self._x 

232 

233 @property 

234 def public_numbers(self) -> DSAPublicNumbers: 

235 return self._public_numbers 

236 

237 def private_key(self, backend: typing.Any = None) -> DSAPrivateKey: 

238 from cryptography.hazmat.backends.openssl.backend import ( 

239 backend as ossl, 

240 ) 

241 

242 return ossl.load_dsa_private_numbers(self) 

243 

244 def __eq__(self, other: object) -> bool: 

245 if not isinstance(other, DSAPrivateNumbers): 

246 return NotImplemented 

247 

248 return ( 

249 self.x == other.x and self.public_numbers == other.public_numbers 

250 ) 

251 

252 

253def generate_parameters( 

254 key_size: int, backend: typing.Any = None 

255) -> DSAParameters: 

256 from cryptography.hazmat.backends.openssl.backend import backend as ossl 

257 

258 return ossl.generate_dsa_parameters(key_size) 

259 

260 

261def generate_private_key( 

262 key_size: int, backend: typing.Any = None 

263) -> DSAPrivateKey: 

264 from cryptography.hazmat.backends.openssl.backend import backend as ossl 

265 

266 return ossl.generate_dsa_private_key_and_parameters(key_size) 

267 

268 

269def _check_dsa_parameters(parameters: DSAParameterNumbers) -> None: 

270 if parameters.p.bit_length() not in [1024, 2048, 3072, 4096]: 

271 raise ValueError( 

272 "p must be exactly 1024, 2048, 3072, or 4096 bits long" 

273 ) 

274 if parameters.q.bit_length() not in [160, 224, 256]: 

275 raise ValueError("q must be exactly 160, 224, or 256 bits long") 

276 

277 if not (1 < parameters.g < parameters.p): 

278 raise ValueError("g, p don't satisfy 1 < g < p.") 

279 

280 

281def _check_dsa_private_numbers(numbers: DSAPrivateNumbers) -> None: 

282 parameters = numbers.public_numbers.parameter_numbers 

283 _check_dsa_parameters(parameters) 

284 if numbers.x <= 0 or numbers.x >= parameters.q: 

285 raise ValueError("x must be > 0 and < q.") 

286 

287 if numbers.public_numbers.y != pow(parameters.g, numbers.x, parameters.p): 

288 raise ValueError("y must be equal to (g ** x % p).")