• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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