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_MIN_MODULUS_SIZE = 512 16 17 18def generate_parameters(generator, key_size, backend=None): 19 backend = _get_backend(backend) 20 return backend.generate_dh_parameters(generator, key_size) 21 22 23class DHPrivateNumbers(object): 24 def __init__(self, x, public_numbers): 25 if not isinstance(x, six.integer_types): 26 raise TypeError("x must be an integer.") 27 28 if not isinstance(public_numbers, DHPublicNumbers): 29 raise TypeError( 30 "public_numbers must be an instance of " "DHPublicNumbers." 31 ) 32 33 self._x = x 34 self._public_numbers = public_numbers 35 36 def __eq__(self, other): 37 if not isinstance(other, DHPrivateNumbers): 38 return NotImplemented 39 40 return ( 41 self._x == other._x 42 and self._public_numbers == other._public_numbers 43 ) 44 45 def __ne__(self, other): 46 return not self == other 47 48 def private_key(self, backend=None): 49 backend = _get_backend(backend) 50 return backend.load_dh_private_numbers(self) 51 52 public_numbers = utils.read_only_property("_public_numbers") 53 x = utils.read_only_property("_x") 54 55 56class DHPublicNumbers(object): 57 def __init__(self, y, parameter_numbers): 58 if not isinstance(y, six.integer_types): 59 raise TypeError("y must be an integer.") 60 61 if not isinstance(parameter_numbers, DHParameterNumbers): 62 raise TypeError( 63 "parameters must be an instance of DHParameterNumbers." 64 ) 65 66 self._y = y 67 self._parameter_numbers = parameter_numbers 68 69 def __eq__(self, other): 70 if not isinstance(other, DHPublicNumbers): 71 return NotImplemented 72 73 return ( 74 self._y == other._y 75 and self._parameter_numbers == other._parameter_numbers 76 ) 77 78 def __ne__(self, other): 79 return not self == other 80 81 def public_key(self, backend=None): 82 backend = _get_backend(backend) 83 return backend.load_dh_public_numbers(self) 84 85 y = utils.read_only_property("_y") 86 parameter_numbers = utils.read_only_property("_parameter_numbers") 87 88 89class DHParameterNumbers(object): 90 def __init__(self, p, g, q=None): 91 if not isinstance(p, six.integer_types) or not isinstance( 92 g, six.integer_types 93 ): 94 raise TypeError("p and g must be integers") 95 if q is not None and not isinstance(q, six.integer_types): 96 raise TypeError("q must be integer or None") 97 98 if g < 2: 99 raise ValueError("DH generator must be 2 or greater") 100 101 if p.bit_length() < _MIN_MODULUS_SIZE: 102 raise ValueError( 103 "p (modulus) must be at least {}-bit".format(_MIN_MODULUS_SIZE) 104 ) 105 106 self._p = p 107 self._g = g 108 self._q = q 109 110 def __eq__(self, other): 111 if not isinstance(other, DHParameterNumbers): 112 return NotImplemented 113 114 return ( 115 self._p == other._p and self._g == other._g and self._q == other._q 116 ) 117 118 def __ne__(self, other): 119 return not self == other 120 121 def parameters(self, backend=None): 122 backend = _get_backend(backend) 123 return backend.load_dh_parameter_numbers(self) 124 125 p = utils.read_only_property("_p") 126 g = utils.read_only_property("_g") 127 q = utils.read_only_property("_q") 128 129 130@six.add_metaclass(abc.ABCMeta) 131class DHParameters(object): 132 @abc.abstractmethod 133 def generate_private_key(self): 134 """ 135 Generates and returns a DHPrivateKey. 136 """ 137 138 @abc.abstractmethod 139 def parameter_bytes(self, encoding, format): 140 """ 141 Returns the parameters serialized as bytes. 142 """ 143 144 @abc.abstractmethod 145 def parameter_numbers(self): 146 """ 147 Returns a DHParameterNumbers. 148 """ 149 150 151DHParametersWithSerialization = DHParameters 152 153 154@six.add_metaclass(abc.ABCMeta) 155class DHPrivateKey(object): 156 @abc.abstractproperty 157 def key_size(self): 158 """ 159 The bit length of the prime modulus. 160 """ 161 162 @abc.abstractmethod 163 def public_key(self): 164 """ 165 The DHPublicKey associated with this private key. 166 """ 167 168 @abc.abstractmethod 169 def parameters(self): 170 """ 171 The DHParameters object associated with this private key. 172 """ 173 174 @abc.abstractmethod 175 def exchange(self, peer_public_key): 176 """ 177 Given peer's DHPublicKey, carry out the key exchange and 178 return shared key as bytes. 179 """ 180 181 182@six.add_metaclass(abc.ABCMeta) 183class DHPrivateKeyWithSerialization(DHPrivateKey): 184 @abc.abstractmethod 185 def private_numbers(self): 186 """ 187 Returns a DHPrivateNumbers. 188 """ 189 190 @abc.abstractmethod 191 def private_bytes(self, encoding, format, encryption_algorithm): 192 """ 193 Returns the key serialized as bytes. 194 """ 195 196 197@six.add_metaclass(abc.ABCMeta) 198class DHPublicKey(object): 199 @abc.abstractproperty 200 def key_size(self): 201 """ 202 The bit length of the prime modulus. 203 """ 204 205 @abc.abstractmethod 206 def parameters(self): 207 """ 208 The DHParameters object associated with this public key. 209 """ 210 211 @abc.abstractmethod 212 def public_numbers(self): 213 """ 214 Returns a DHPublicNumbers. 215 """ 216 217 @abc.abstractmethod 218 def public_bytes(self, encoding, format): 219 """ 220 Returns the key serialized as bytes. 221 """ 222 223 224DHPublicKeyWithSerialization = DHPublicKey 225