Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: third_party/google-endpoints/Crypto/PublicKey/DSA.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # -*- coding: utf-8 -*-
2 #
3 # PublicKey/DSA.py : DSA signature primitive
4 #
5 # Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
6 #
7 # ===================================================================
8 # The contents of this file are dedicated to the public domain. To
9 # the extent that dedication to the public domain is not available,
10 # everyone is granted a worldwide, perpetual, royalty-free,
11 # non-exclusive license to exercise all rights associated with the
12 # contents of this file for any purpose whatsoever.
13 # No rights are reserved.
14 #
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 # SOFTWARE.
23 # ===================================================================
24
25 """DSA public-key signature algorithm.
26
27 DSA_ is a widespread public-key signature algorithm. Its security is
28 based on the discrete logarithm problem (DLP_). Given a cyclic
29 group, a generator *g*, and an element *h*, it is hard
30 to find an integer *x* such that *g^x = h*. The problem is believed
31 to be difficult, and it has been proved such (and therefore secure) for
32 more than 30 years.
33
34 The group is actually a sub-group over the integers modulo *p*, with *p* prime.
35 The sub-group order is *q*, which is prime too; it always holds that *(p-1)* is a multiple of *q*.
36 The cryptographic strength is linked to the magnitude of *p* and *q*.
37 The signer holds a value *x* (*0<x<q-1*) as private key, and its public
38 key (*y* where *y=g^x mod p*) is distributed.
39
40 In 2012, a sufficient size is deemed to be 2048 bits for *p* and 256 bits for *q *.
41 For more information, see the most recent ECRYPT_ report.
42
43 DSA is reasonably secure for new designs.
44
45 The algorithm can only be used for authentication (digital signature).
46 DSA cannot be used for confidentiality (encryption).
47
48 The values *(p,q,g)* are called *domain parameters*;
49 they are not sensitive but must be shared by both parties (the signer and the ve rifier).
50 Different signers can share the same domain parameters with no security
51 concerns.
52
53 The DSA signature is twice as big as the size of *q* (64 bytes if *q* is 256 bit
54 long).
55
56 This module provides facilities for generating new DSA keys and for constructing
57 them from known components. DSA keys allows you to perform basic signing and
58 verification.
59
60 >>> from Crypto.Random import random
61 >>> from Crypto.PublicKey import DSA
62 >>> from Crypto.Hash import SHA
63 >>>
64 >>> message = "Hello"
65 >>> key = DSA.generate(1024)
66 >>> h = SHA.new(message).digest()
67 >>> k = random.StrongRandom().randint(1,key.q-1)
68 >>> sig = key.sign(h,k)
69 >>> ...
70 >>> if key.verify(h,sig):
71 >>> print "OK"
72 >>> else:
73 >>> print "Incorrect signature"
74
75 .. _DSA: http://en.wikipedia.org/wiki/Digital_Signature_Algorithm
76 .. _DLP: http://www.cosic.esat.kuleuven.be/publications/talk-78.pdf
77 .. _ECRYPT: http://www.ecrypt.eu.org/documents/D.SPA.17.pdf
78 """
79
80 __revision__ = "$Id$"
81
82 __all__ = ['generate', 'construct', 'error', 'DSAImplementation', '_DSAobj']
83
84 import sys
85 if sys.version_info[0] == 2 and sys.version_info[1] == 1:
86 from Crypto.Util.py21compat import *
87
88 from Crypto.PublicKey import _DSA, _slowmath, pubkey
89 from Crypto import Random
90
91 try:
92 from Crypto.PublicKey import _fastmath
93 except ImportError:
94 _fastmath = None
95
96 class _DSAobj(pubkey.pubkey):
97 """Class defining an actual DSA key.
98
99 :undocumented: __getstate__, __setstate__, __repr__, __getattr__
100 """
101 #: Dictionary of DSA parameters.
102 #:
103 #: A public key will only have the following entries:
104 #:
105 #: - **y**, the public key.
106 #: - **g**, the generator.
107 #: - **p**, the modulus.
108 #: - **q**, the order of the sub-group.
109 #:
110 #: A private key will also have:
111 #:
112 #: - **x**, the private key.
113 keydata = ['y', 'g', 'p', 'q', 'x']
114
115 def __init__(self, implementation, key):
116 self.implementation = implementation
117 self.key = key
118
119 def __getattr__(self, attrname):
120 if attrname in self.keydata:
121 # For backward compatibility, allow the user to get (not set) the
122 # DSA key parameters directly from this object.
123 return getattr(self.key, attrname)
124 else:
125 raise AttributeError("%s object has no %r attribute" % (self.__class __.__name__, attrname,))
126
127 def sign(self, M, K):
128 """Sign a piece of data with DSA.
129
130 :Parameter M: The piece of data to sign with DSA. It may
131 not be longer in bit size than the sub-group order (*q*).
132 :Type M: byte string or long
133
134 :Parameter K: A secret number, chosen randomly in the closed
135 range *[1,q-1]*.
136 :Type K: long (recommended) or byte string (not recommended)
137
138 :attention: selection of *K* is crucial for security. Generating a
139 random number larger than *q* and taking the modulus by *q* is
140 **not** secure, since smaller values will occur more frequently.
141 Generating a random number systematically smaller than *q-1*
142 (e.g. *floor((q-1)/8)* random bytes) is also **not** secure. In general ,
143 it shall not be possible for an attacker to know the value of `any
144 bit of K`__.
145
146 :attention: The number *K* shall not be reused for any other
147 operation and shall be discarded immediately.
148
149 :attention: M must be a digest cryptographic hash, otherwise
150 an attacker may mount an existential forgery attack.
151
152 :Return: A tuple with 2 longs.
153
154 .. __: http://www.di.ens.fr/~pnguyen/pub_NgSh00.htm
155 """
156 return pubkey.pubkey.sign(self, M, K)
157
158 def verify(self, M, signature):
159 """Verify the validity of a DSA signature.
160
161 :Parameter M: The expected message.
162 :Type M: byte string or long
163
164 :Parameter signature: The DSA signature to verify.
165 :Type signature: A tuple with 2 longs as return by `sign`
166
167 :Return: True if the signature is correct, False otherwise.
168 """
169 return pubkey.pubkey.verify(self, M, signature)
170
171 def _encrypt(self, c, K):
172 raise TypeError("DSA cannot encrypt")
173
174 def _decrypt(self, c):
175 raise TypeError("DSA cannot decrypt")
176
177 def _blind(self, m, r):
178 raise TypeError("DSA cannot blind")
179
180 def _unblind(self, m, r):
181 raise TypeError("DSA cannot unblind")
182
183 def _sign(self, m, k):
184 return self.key._sign(m, k)
185
186 def _verify(self, m, sig):
187 (r, s) = sig
188 return self.key._verify(m, r, s)
189
190 def has_private(self):
191 return self.key.has_private()
192
193 def size(self):
194 return self.key.size()
195
196 def can_blind(self):
197 return False
198
199 def can_encrypt(self):
200 return False
201
202 def can_sign(self):
203 return True
204
205 def publickey(self):
206 return self.implementation.construct((self.key.y, self.key.g, self.key.p , self.key.q))
207
208 def __getstate__(self):
209 d = {}
210 for k in self.keydata:
211 try:
212 d[k] = getattr(self.key, k)
213 except AttributeError:
214 pass
215 return d
216
217 def __setstate__(self, d):
218 if not hasattr(self, 'implementation'):
219 self.implementation = DSAImplementation()
220 t = []
221 for k in self.keydata:
222 if not d.has_key(k):
223 break
224 t.append(d[k])
225 self.key = self.implementation._math.dsa_construct(*tuple(t))
226
227 def __repr__(self):
228 attrs = []
229 for k in self.keydata:
230 if k == 'p':
231 attrs.append("p(%d)" % (self.size()+1,))
232 elif hasattr(self.key, k):
233 attrs.append(k)
234 if self.has_private():
235 attrs.append("private")
236 # PY3K: This is meant to be text, do not change to bytes (data)
237 return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(at trs))
238
239 class DSAImplementation(object):
240 """
241 A DSA key factory.
242
243 This class is only internally used to implement the methods of the
244 `Crypto.PublicKey.DSA` module.
245 """
246
247 def __init__(self, **kwargs):
248 """Create a new DSA key factory.
249
250 :Keywords:
251 use_fast_math : bool
252 Specify which mathematic library to use:
253
254 - *None* (default). Use fastest math available.
255 - *True* . Use fast math.
256 - *False* . Use slow math.
257 default_randfunc : callable
258 Specify how to collect random data:
259
260 - *None* (default). Use Random.new().read().
261 - not *None* . Use the specified function direct ly.
262 :Raise RuntimeError:
263 When **use_fast_math** =True but fast math is not available.
264 """
265 use_fast_math = kwargs.get('use_fast_math', None)
266 if use_fast_math is None: # Automatic
267 if _fastmath is not None:
268 self._math = _fastmath
269 else:
270 self._math = _slowmath
271
272 elif use_fast_math: # Explicitly select fast math
273 if _fastmath is not None:
274 self._math = _fastmath
275 else:
276 raise RuntimeError("fast math module not available")
277
278 else: # Explicitly select slow math
279 self._math = _slowmath
280
281 self.error = self._math.error
282
283 # 'default_randfunc' parameter:
284 # None (default) - use Random.new().read
285 # not None - use the specified function
286 self._default_randfunc = kwargs.get('default_randfunc', None)
287 self._current_randfunc = None
288
289 def _get_randfunc(self, randfunc):
290 if randfunc is not None:
291 return randfunc
292 elif self._current_randfunc is None:
293 self._current_randfunc = Random.new().read
294 return self._current_randfunc
295
296 def generate(self, bits, randfunc=None, progress_func=None):
297 """Randomly generate a fresh, new DSA key.
298
299 :Parameters:
300 bits : int
301 Key length, or size (in bits) of the DSA modulus
302 *p*.
303 It must be a multiple of 64, in the closed
304 interval [512,1024].
305 randfunc : callable
306 Random number generation function; it should accept
307 a single integer N and return a string of random dat a
308 N bytes long.
309 If not specified, a new one will be instantiated
310 from ``Crypto.Random``.
311 progress_func : callable
312 Optional function that will be called with a short s tring
313 containing the key parameter currently being generat ed;
314 it's useful for interactive applications where a use r is
315 waiting for a key to be generated.
316
317 :attention: You should always use a cryptographically secure random numb er generator,
318 such as the one defined in the ``Crypto.Random`` module; **don't** j ust use the
319 current time and the ``random`` module.
320
321 :Return: A DSA key object (`_DSAobj`).
322
323 :Raise ValueError:
324 When **bits** is too little, too big, or not a multiple of 64.
325 """
326
327 # Check against FIPS 186-2, which says that the size of the prime p
328 # must be a multiple of 64 bits between 512 and 1024
329 for i in (0, 1, 2, 3, 4, 5, 6, 7, 8):
330 if bits == 512 + 64*i:
331 return self._generate(bits, randfunc, progress_func)
332
333 # The March 2006 draft of FIPS 186-3 also allows 2048 and 3072-bit
334 # primes, but only with longer q values. Since the current DSA
335 # implementation only supports a 160-bit q, we don't support larger
336 # values.
337 raise ValueError("Number of bits in p must be a multiple of 64 between 5 12 and 1024, not %d bits" % (bits,))
338
339 def _generate(self, bits, randfunc=None, progress_func=None):
340 rf = self._get_randfunc(randfunc)
341 obj = _DSA.generate_py(bits, rf, progress_func) # TODO: Don't use leg acy _DSA module
342 key = self._math.dsa_construct(obj.y, obj.g, obj.p, obj.q, obj.x)
343 return _DSAobj(self, key)
344
345 def construct(self, tup):
346 """Construct a DSA key from a tuple of valid DSA components.
347
348 The modulus *p* must be a prime.
349
350 The following equations must apply:
351
352 - p-1 = 0 mod q
353 - g^x = y mod p
354 - 0 < x < q
355 - 1 < g < p
356
357 :Parameters:
358 tup : tuple
359 A tuple of long integers, with 4 or 5 items
360 in the following order:
361
362 1. Public key (*y*).
363 2. Sub-group generator (*g*).
364 3. Modulus, finite field order (*p*).
365 4. Sub-group order (*q*).
366 5. Private key (*x*). Optional.
367
368 :Return: A DSA key object (`_DSAobj`).
369 """
370 key = self._math.dsa_construct(*tup)
371 return _DSAobj(self, key)
372
373 _impl = DSAImplementation()
374 generate = _impl.generate
375 construct = _impl.construct
376 error = _impl.error
377
378 # vim:set ts=4 sw=4 sts=4 expandtab:
379
OLDNEW
« no previous file with comments | « third_party/google-endpoints/Crypto/Protocol/__init__.py ('k') | third_party/google-endpoints/Crypto/PublicKey/ElGamal.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698