Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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 import utils 

10from cryptography.hazmat.backends import _get_backend 

11from cryptography.hazmat.primitives import _serialization, hashes 

12from cryptography.hazmat.primitives.asymmetric import ( 

13 AsymmetricSignatureContext, 

14 AsymmetricVerificationContext, 

15 utils as asym_utils, 

16) 

17 

18 

19class DSAParameters(metaclass=abc.ABCMeta): 

20 @abc.abstractmethod 

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

22 """ 

23 Generates and returns a DSAPrivateKey. 

24 """ 

25 

26 @abc.abstractmethod 

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

28 """ 

29 Returns a DSAParameterNumbers. 

30 """ 

31 

32 

33DSAParametersWithNumbers = DSAParameters 

34 

35 

36class DSAPrivateKey(metaclass=abc.ABCMeta): 

37 @abc.abstractproperty 

38 def key_size(self) -> int: 

39 """ 

40 The bit length of the prime modulus. 

41 """ 

42 

43 @abc.abstractmethod 

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

45 """ 

46 The DSAPublicKey associated with this private key. 

47 """ 

48 

49 @abc.abstractmethod 

50 def parameters(self) -> DSAParameters: 

51 """ 

52 The DSAParameters object associated with this private key. 

53 """ 

54 

55 @abc.abstractmethod 

56 def signer( 

57 self, 

58 signature_algorithm: hashes.HashAlgorithm, 

59 ) -> AsymmetricSignatureContext: 

60 """ 

61 Returns an AsymmetricSignatureContext used for signing data. 

62 """ 

63 

64 @abc.abstractmethod 

65 def sign( 

66 self, 

67 data: bytes, 

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

69 ) -> bytes: 

70 """ 

71 Signs the data 

72 """ 

73 

74 @abc.abstractmethod 

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

76 """ 

77 Returns a DSAPrivateNumbers. 

78 """ 

79 

80 @abc.abstractmethod 

81 def private_bytes( 

82 self, 

83 encoding: _serialization.Encoding, 

84 format: _serialization.PrivateFormat, 

85 encryption_algorithm: _serialization.KeySerializationEncryption, 

86 ) -> bytes: 

87 """ 

88 Returns the key serialized as bytes. 

89 """ 

90 

91 

92DSAPrivateKeyWithSerialization = DSAPrivateKey 

93 

94 

95class DSAPublicKey(metaclass=abc.ABCMeta): 

96 @abc.abstractproperty 

97 def key_size(self) -> int: 

98 """ 

99 The bit length of the prime modulus. 

100 """ 

101 

102 @abc.abstractmethod 

103 def parameters(self) -> DSAParameters: 

104 """ 

105 The DSAParameters object associated with this public key. 

106 """ 

107 

108 @abc.abstractmethod 

109 def verifier( 

110 self, 

111 signature: bytes, 

112 signature_algorithm: hashes.HashAlgorithm, 

113 ) -> AsymmetricVerificationContext: 

114 """ 

115 Returns an AsymmetricVerificationContext used for signing data. 

116 """ 

117 

118 @abc.abstractmethod 

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

120 """ 

121 Returns a DSAPublicNumbers. 

122 """ 

123 

124 @abc.abstractmethod 

125 def public_bytes( 

126 self, 

127 encoding: _serialization.Encoding, 

128 format: _serialization.PublicFormat, 

129 ) -> bytes: 

130 """ 

131 Returns the key serialized as bytes. 

132 """ 

133 

134 @abc.abstractmethod 

135 def verify( 

136 self, 

137 signature: bytes, 

138 data: bytes, 

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

140 ): 

141 """ 

142 Verifies the signature of the data. 

143 """ 

144 

145 

146DSAPublicKeyWithSerialization = DSAPublicKey 

147 

148 

149class DSAParameterNumbers(object): 

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

151 if ( 

152 not isinstance(p, int) 

153 or not isinstance(q, int) 

154 or not isinstance(g, int) 

155 ): 

156 raise TypeError( 

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

158 ) 

159 

160 self._p = p 

161 self._q = q 

162 self._g = g 

163 

164 p = utils.read_only_property("_p") 

165 q = utils.read_only_property("_q") 

166 g = utils.read_only_property("_g") 

167 

168 def parameters(self, backend=None) -> DSAParameters: 

169 backend = _get_backend(backend) 

170 return backend.load_dsa_parameter_numbers(self) 

171 

172 def __eq__(self, other): 

173 if not isinstance(other, DSAParameterNumbers): 

174 return NotImplemented 

175 

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

177 

178 def __ne__(self, other): 

179 return not self == other 

180 

181 def __repr__(self): 

182 return ( 

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

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

185 ) 

186 

187 

188class DSAPublicNumbers(object): 

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

190 if not isinstance(y, int): 

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

192 

193 if not isinstance(parameter_numbers, DSAParameterNumbers): 

194 raise TypeError( 

195 "parameter_numbers must be a DSAParameterNumbers instance." 

196 ) 

197 

198 self._y = y 

199 self._parameter_numbers = parameter_numbers 

200 

201 y = utils.read_only_property("_y") 

202 parameter_numbers = utils.read_only_property("_parameter_numbers") 

203 

204 def public_key(self, backend=None) -> DSAPublicKey: 

205 backend = _get_backend(backend) 

206 return backend.load_dsa_public_numbers(self) 

207 

208 def __eq__(self, other): 

209 if not isinstance(other, DSAPublicNumbers): 

210 return NotImplemented 

211 

212 return ( 

213 self.y == other.y 

214 and self.parameter_numbers == other.parameter_numbers 

215 ) 

216 

217 def __ne__(self, other): 

218 return not self == other 

219 

220 def __repr__(self): 

221 return ( 

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

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

224 ) 

225 

226 

227class DSAPrivateNumbers(object): 

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

229 if not isinstance(x, int): 

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

231 

232 if not isinstance(public_numbers, DSAPublicNumbers): 

233 raise TypeError( 

234 "public_numbers must be a DSAPublicNumbers instance." 

235 ) 

236 self._public_numbers = public_numbers 

237 self._x = x 

238 

239 x = utils.read_only_property("_x") 

240 public_numbers = utils.read_only_property("_public_numbers") 

241 

242 def private_key(self, backend=None) -> DSAPrivateKey: 

243 backend = _get_backend(backend) 

244 return backend.load_dsa_private_numbers(self) 

245 

246 def __eq__(self, other): 

247 if not isinstance(other, DSAPrivateNumbers): 

248 return NotImplemented 

249 

250 return ( 

251 self.x == other.x and self.public_numbers == other.public_numbers 

252 ) 

253 

254 def __ne__(self, other): 

255 return not self == other 

256 

257 

258def generate_parameters(key_size: int, backend=None) -> DSAParameters: 

259 backend = _get_backend(backend) 

260 return backend.generate_dsa_parameters(key_size) 

261 

262 

263def generate_private_key(key_size: int, backend=None) -> DSAPrivateKey: 

264 backend = _get_backend(backend) 

265 return backend.generate_dsa_private_key_and_parameters(key_size) 

266 

267 

268def _check_dsa_parameters(parameters: DSAParameterNumbers): 

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") 

275 

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

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

278 

279 

280def _check_dsa_private_numbers(numbers: DSAPrivateNumbers): 

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.") 

285 

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

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