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 absolute_import, division, print_function 6 7import abc 8 9import six 10 11from cryptography import utils 12 13 14@six.add_metaclass(abc.ABCMeta) 15class DSAParameters(object): 16 @abc.abstractmethod 17 def generate_private_key(self): 18 """ 19 Generates and returns a DSAPrivateKey. 20 """ 21 22 23@six.add_metaclass(abc.ABCMeta) 24class DSAParametersWithNumbers(DSAParameters): 25 @abc.abstractmethod 26 def parameter_numbers(self): 27 """ 28 Returns a DSAParameterNumbers. 29 """ 30 31 32@six.add_metaclass(abc.ABCMeta) 33class DSAPrivateKey(object): 34 @abc.abstractproperty 35 def key_size(self): 36 """ 37 The bit length of the prime modulus. 38 """ 39 40 @abc.abstractmethod 41 def public_key(self): 42 """ 43 The DSAPublicKey associated with this private key. 44 """ 45 46 @abc.abstractmethod 47 def parameters(self): 48 """ 49 The DSAParameters object associated with this private key. 50 """ 51 52 @abc.abstractmethod 53 def signer(self, signature_algorithm): 54 """ 55 Returns an AsymmetricSignatureContext used for signing data. 56 """ 57 58 @abc.abstractmethod 59 def sign(self, data, algorithm): 60 """ 61 Signs the data 62 """ 63 64 65@six.add_metaclass(abc.ABCMeta) 66class DSAPrivateKeyWithSerialization(DSAPrivateKey): 67 @abc.abstractmethod 68 def private_numbers(self): 69 """ 70 Returns a DSAPrivateNumbers. 71 """ 72 73 @abc.abstractmethod 74 def private_bytes(self, encoding, format, encryption_algorithm): 75 """ 76 Returns the key serialized as bytes. 77 """ 78 79 80@six.add_metaclass(abc.ABCMeta) 81class DSAPublicKey(object): 82 @abc.abstractproperty 83 def key_size(self): 84 """ 85 The bit length of the prime modulus. 86 """ 87 88 @abc.abstractmethod 89 def parameters(self): 90 """ 91 The DSAParameters object associated with this public key. 92 """ 93 94 @abc.abstractmethod 95 def verifier(self, signature, signature_algorithm): 96 """ 97 Returns an AsymmetricVerificationContext used for signing data. 98 """ 99 100 @abc.abstractmethod 101 def public_numbers(self): 102 """ 103 Returns a DSAPublicNumbers. 104 """ 105 106 @abc.abstractmethod 107 def public_bytes(self, encoding, format): 108 """ 109 Returns the key serialized as bytes. 110 """ 111 112 @abc.abstractmethod 113 def verify(self, signature, data, algorithm): 114 """ 115 Verifies the signature of the data. 116 """ 117 118 119DSAPublicKeyWithSerialization = DSAPublicKey 120 121 122def generate_parameters(key_size, backend): 123 return backend.generate_dsa_parameters(key_size) 124 125 126def generate_private_key(key_size, backend): 127 return backend.generate_dsa_private_key_and_parameters(key_size) 128 129 130def _check_dsa_parameters(parameters): 131 if parameters.p.bit_length() not in [1024, 2048, 3072]: 132 raise ValueError("p must be exactly 1024, 2048, or 3072 bits long") 133 if parameters.q.bit_length() not in [160, 224, 256]: 134 raise ValueError("q must be exactly 160, 224, or 256 bits long") 135 136 if not (1 < parameters.g < parameters.p): 137 raise ValueError("g, p don't satisfy 1 < g < p.") 138 139 140def _check_dsa_private_numbers(numbers): 141 parameters = numbers.public_numbers.parameter_numbers 142 _check_dsa_parameters(parameters) 143 if numbers.x <= 0 or numbers.x >= parameters.q: 144 raise ValueError("x must be > 0 and < q.") 145 146 if numbers.public_numbers.y != pow(parameters.g, numbers.x, parameters.p): 147 raise ValueError("y must be equal to (g ** x % p).") 148 149 150class DSAParameterNumbers(object): 151 def __init__(self, p, q, g): 152 if ( 153 not isinstance(p, six.integer_types) or 154 not isinstance(q, six.integer_types) or 155 not isinstance(g, six.integer_types) 156 ): 157 raise TypeError( 158 "DSAParameterNumbers p, q, and g arguments must be integers." 159 ) 160 161 self._p = p 162 self._q = q 163 self._g = g 164 165 p = utils.read_only_property("_p") 166 q = utils.read_only_property("_q") 167 g = utils.read_only_property("_g") 168 169 def parameters(self, 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}, g={self.g})>".format( 184 self=self 185 ) 186 ) 187 188 189class DSAPublicNumbers(object): 190 def __init__(self, y, parameter_numbers): 191 if not isinstance(y, six.integer_types): 192 raise TypeError("DSAPublicNumbers y argument must be an integer.") 193 194 if not isinstance(parameter_numbers, DSAParameterNumbers): 195 raise TypeError( 196 "parameter_numbers must be a DSAParameterNumbers instance." 197 ) 198 199 self._y = y 200 self._parameter_numbers = parameter_numbers 201 202 y = utils.read_only_property("_y") 203 parameter_numbers = utils.read_only_property("_parameter_numbers") 204 205 def public_key(self, 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 and 214 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, public_numbers): 229 if not isinstance(x, six.integer_types): 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): 243 return backend.load_dsa_private_numbers(self) 244 245 def __eq__(self, other): 246 if not isinstance(other, DSAPrivateNumbers): 247 return NotImplemented 248 249 return ( 250 self.x == other.x and self.public_numbers == other.public_numbers 251 ) 252 253 def __ne__(self, other): 254 return not self == other 255