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

Side by Side Diff: third_party/google-endpoints/rsa/_version133.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 # Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # https://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 """Deprecated version of the RSA module
18
19 .. deprecated:: 2.0
20
21 This submodule is deprecated and will be completely removed as of version 4. 0.
22
23 Module for calculating large primes, and RSA encryption, decryption,
24 signing and verification. Includes generating public and private keys.
25
26 WARNING: this code implements the mathematics of RSA. It is not suitable for
27 real-world secure cryptography purposes. It has not been reviewed by a security
28 expert. It does not include padding of data. There are many ways in which the
29 output of this module, when used without any modification, can be sucessfully
30 attacked.
31 """
32
33 __author__ = "Sybren Stuvel, Marloes de Boer and Ivo Tamboer"
34 __date__ = "2010-02-05"
35 __version__ = '1.3.3'
36
37 # NOTE: Python's modulo can return negative numbers. We compensate for
38 # this behaviour using the abs() function
39
40 try:
41 import cPickle as pickle
42 except ImportError:
43 import pickle
44 from pickle import dumps, loads
45 import base64
46 import math
47 import os
48 import random
49 import sys
50 import types
51 import zlib
52
53 from rsa._compat import byte
54
55 # Display a warning that this insecure version is imported.
56 import warnings
57 warnings.warn('Insecure version of the RSA module is imported as %s, be careful'
58 % __name__)
59 warnings.warn('This submodule is deprecated and will be completely removed as of version 4.0.',
60 DeprecationWarning)
61
62
63 def gcd(p, q):
64 """Returns the greatest common divisor of p and q
65
66
67 >>> gcd(42, 6)
68 6
69 """
70 if p<q: return gcd(q, p)
71 if q == 0: return p
72 return gcd(q, abs(p%q))
73
74 def bytes2int(bytes):
75 """Converts a list of bytes or a string to an integer
76 """
77
78 if not (type(bytes) is types.ListType or type(bytes) is types.StringType):
79 raise TypeError("You must pass a string or a list")
80
81 # Convert byte stream to integer
82 integer = 0
83 for byte in bytes:
84 integer *= 256
85 if type(byte) is types.StringType: byte = ord(byte)
86 integer += byte
87
88 return integer
89
90 def int2bytes(number):
91 """Converts a number to a string of bytes
92 """
93
94 if not (type(number) is types.LongType or type(number) is types.IntType):
95 raise TypeError("You must pass a long or an int")
96
97 string = ""
98
99 while number > 0:
100 string = "%s%s" % (byte(number & 0xFF), string)
101 number /= 256
102
103 return string
104
105 def fast_exponentiation(a, p, n):
106 """Calculates r = a^p mod n
107 """
108 result = a % n
109 remainders = []
110 while p != 1:
111 remainders.append(p & 1)
112 p = p >> 1
113 while remainders:
114 rem = remainders.pop()
115 result = ((a ** rem) * result ** 2) % n
116 return result
117
118 def read_random_int(nbits):
119 """Reads a random integer of approximately nbits bits rounded up
120 to whole bytes"""
121
122 nbytes = ceil(nbits/8.)
123 randomdata = os.urandom(nbytes)
124 return bytes2int(randomdata)
125
126 def ceil(x):
127 """ceil(x) -> int(math.ceil(x))"""
128
129 return int(math.ceil(x))
130
131 def randint(minvalue, maxvalue):
132 """Returns a random integer x with minvalue <= x <= maxvalue"""
133
134 # Safety - get a lot of random data even if the range is fairly
135 # small
136 min_nbits = 32
137
138 # The range of the random numbers we need to generate
139 range = maxvalue - minvalue
140
141 # Which is this number of bytes
142 rangebytes = ceil(math.log(range, 2) / 8.)
143
144 # Convert to bits, but make sure it's always at least min_nbits*2
145 rangebits = max(rangebytes * 8, min_nbits * 2)
146
147 # Take a random number of bits between min_nbits and rangebits
148 nbits = random.randint(min_nbits, rangebits)
149
150 return (read_random_int(nbits) % range) + minvalue
151
152 def fermat_little_theorem(p):
153 """Returns 1 if p may be prime, and something else if p definitely
154 is not prime"""
155
156 a = randint(1, p-1)
157 return fast_exponentiation(a, p-1, p)
158
159 def jacobi(a, b):
160 """Calculates the value of the Jacobi symbol (a/b)
161 """
162
163 if a % b == 0:
164 return 0
165 result = 1
166 while a > 1:
167 if a & 1:
168 if ((a-1)*(b-1) >> 2) & 1:
169 result = -result
170 b, a = a, b % a
171 else:
172 if ((b ** 2 - 1) >> 3) & 1:
173 result = -result
174 a = a >> 1
175 return result
176
177 def jacobi_witness(x, n):
178 """Returns False if n is an Euler pseudo-prime with base x, and
179 True otherwise.
180 """
181
182 j = jacobi(x, n) % n
183 f = fast_exponentiation(x, (n-1)/2, n)
184
185 if j == f: return False
186 return True
187
188 def randomized_primality_testing(n, k):
189 """Calculates whether n is composite (which is always correct) or
190 prime (which is incorrect with error probability 2**-k)
191
192 Returns False if the number if composite, and True if it's
193 probably prime.
194 """
195
196 q = 0.5 # Property of the jacobi_witness function
197
198 # t = int(math.ceil(k / math.log(1/q, 2)))
199 t = ceil(k / math.log(1/q, 2))
200 for i in range(t+1):
201 x = randint(1, n-1)
202 if jacobi_witness(x, n): return False
203
204 return True
205
206 def is_prime(number):
207 """Returns True if the number is prime, and False otherwise.
208 """
209
210 """
211 if not fermat_little_theorem(number) == 1:
212 # Not prime, according to Fermat's little theorem
213 return False
214 """
215
216 if randomized_primality_testing(number, 5):
217 # Prime, according to Jacobi
218 return True
219
220 # Not prime
221 return False
222
223
224 def getprime(nbits):
225 """Returns a prime number of max. 'math.ceil(nbits/8)*8' bits. In
226 other words: nbits is rounded up to whole bytes.
227 """
228
229 nbytes = int(math.ceil(nbits/8.))
230
231 while True:
232 integer = read_random_int(nbits)
233
234 # Make sure it's odd
235 integer |= 1
236
237 # Test for primeness
238 if is_prime(integer): break
239
240 # Retry if not prime
241
242 return integer
243
244 def are_relatively_prime(a, b):
245 """Returns True if a and b are relatively prime, and False if they
246 are not.
247 """
248
249 d = gcd(a, b)
250 return (d == 1)
251
252 def find_p_q(nbits):
253 """Returns a tuple of two different primes of nbits bits"""
254
255 p = getprime(nbits)
256 while True:
257 q = getprime(nbits)
258 if not q == p: break
259
260 return (p, q)
261
262 def extended_euclid_gcd(a, b):
263 """Returns a tuple (d, i, j) such that d = gcd(a, b) = ia + jb
264 """
265
266 if b == 0:
267 return (a, 1, 0)
268
269 q = abs(a % b)
270 r = long(a / b)
271 (d, k, l) = extended_euclid_gcd(b, q)
272
273 return (d, l, k - l*r)
274
275 # Main function: calculate encryption and decryption keys
276 def calculate_keys(p, q, nbits):
277 """Calculates an encryption and a decryption key for p and q, and
278 returns them as a tuple (e, d)"""
279
280 n = p * q
281 phi_n = (p-1) * (q-1)
282
283 while True:
284 # Make sure e has enough bits so we ensure "wrapping" through
285 # modulo n
286 e = getprime(max(8, nbits/2))
287 if are_relatively_prime(e, n) and are_relatively_prime(e, phi_n): break
288
289 (d, i, j) = extended_euclid_gcd(e, phi_n)
290
291 if not d == 1:
292 raise Exception("e (%d) and phi_n (%d) are not relatively prime" % (e, p hi_n))
293
294 if not (e * i) % phi_n == 1:
295 raise Exception("e (%d) and i (%d) are not mult. inv. modulo phi_n (%d)" % (e, i, phi_n))
296
297 return (e, i)
298
299
300 def gen_keys(nbits):
301 """Generate RSA keys of nbits bits. Returns (p, q, e, d).
302
303 Note: this can take a long time, depending on the key size.
304 """
305
306 while True:
307 (p, q) = find_p_q(nbits)
308 (e, d) = calculate_keys(p, q, nbits)
309
310 # For some reason, d is sometimes negative. We don't know how
311 # to fix it (yet), so we keep trying until everything is shiny
312 if d > 0: break
313
314 return (p, q, e, d)
315
316 def gen_pubpriv_keys(nbits):
317 """Generates public and private keys, and returns them as (pub,
318 priv).
319
320 The public key consists of a dict {e: ..., , n: ....). The private
321 key consists of a dict {d: ...., p: ...., q: ....).
322 """
323
324 (p, q, e, d) = gen_keys(nbits)
325
326 return ( {'e': e, 'n': p*q}, {'d': d, 'p': p, 'q': q} )
327
328 def encrypt_int(message, ekey, n):
329 """Encrypts a message using encryption key 'ekey', working modulo
330 n"""
331
332 if type(message) is types.IntType:
333 return encrypt_int(long(message), ekey, n)
334
335 if not type(message) is types.LongType:
336 raise TypeError("You must pass a long or an int")
337
338 if message > 0 and \
339 math.floor(math.log(message, 2)) > math.floor(math.log(n, 2)):
340 raise OverflowError("The message is too long")
341
342 return fast_exponentiation(message, ekey, n)
343
344 def decrypt_int(cyphertext, dkey, n):
345 """Decrypts a cypher text using the decryption key 'dkey', working
346 modulo n"""
347
348 return encrypt_int(cyphertext, dkey, n)
349
350 def sign_int(message, dkey, n):
351 """Signs 'message' using key 'dkey', working modulo n"""
352
353 return decrypt_int(message, dkey, n)
354
355 def verify_int(signed, ekey, n):
356 """verifies 'signed' using key 'ekey', working modulo n"""
357
358 return encrypt_int(signed, ekey, n)
359
360 def picklechops(chops):
361 """Pickles and base64encodes it's argument chops"""
362
363 value = zlib.compress(dumps(chops))
364 encoded = base64.encodestring(value)
365 return encoded.strip()
366
367 def unpicklechops(string):
368 """base64decodes and unpickes it's argument string into chops"""
369
370 return loads(zlib.decompress(base64.decodestring(string)))
371
372 def chopstring(message, key, n, funcref):
373 """Splits 'message' into chops that are at most as long as n,
374 converts these into integers, and calls funcref(integer, key, n)
375 for each chop.
376
377 Used by 'encrypt' and 'sign'.
378 """
379
380 msglen = len(message)
381 mbits = msglen * 8
382 nbits = int(math.floor(math.log(n, 2)))
383 nbytes = nbits / 8
384 blocks = msglen / nbytes
385
386 if msglen % nbytes > 0:
387 blocks += 1
388
389 cypher = []
390
391 for bindex in range(blocks):
392 offset = bindex * nbytes
393 block = message[offset:offset+nbytes]
394 value = bytes2int(block)
395 cypher.append(funcref(value, key, n))
396
397 return picklechops(cypher)
398
399 def gluechops(chops, key, n, funcref):
400 """Glues chops back together into a string. calls
401 funcref(integer, key, n) for each chop.
402
403 Used by 'decrypt' and 'verify'.
404 """
405 message = ""
406
407 chops = unpicklechops(chops)
408
409 for cpart in chops:
410 mpart = funcref(cpart, key, n)
411 message += int2bytes(mpart)
412
413 return message
414
415 def encrypt(message, key):
416 """Encrypts a string 'message' with the public key 'key'"""
417
418 return chopstring(message, key['e'], key['n'], encrypt_int)
419
420 def sign(message, key):
421 """Signs a string 'message' with the private key 'key'"""
422
423 return chopstring(message, key['d'], key['p']*key['q'], decrypt_int)
424
425 def decrypt(cypher, key):
426 """Decrypts a cypher with the private key 'key'"""
427
428 return gluechops(cypher, key['d'], key['p']*key['q'], decrypt_int)
429
430 def verify(cypher, key):
431 """Verifies a cypher with the public key 'key'"""
432
433 return gluechops(cypher, key['e'], key['n'], encrypt_int)
434
435 # Do doctest if we're not imported
436 if __name__ == "__main__":
437 import doctest
438 doctest.testmod()
439
440 __all__ = ["gen_pubpriv_keys", "encrypt", "decrypt", "sign", "verify"]
441
OLDNEW
« no previous file with comments | « third_party/google-endpoints/rsa/_compat.py ('k') | third_party/google-endpoints/rsa/_version200.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698