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