• 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
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