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

Side by Side Diff: third_party/google-endpoints/rsa/_version200.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:: 3.0
20
21 This submodule is deprecated and will be completely removed as of version 4. 0.
22
23 """
24
25 __author__ = "Sybren Stuvel, Marloes de Boer, Ivo Tamboer, and Barry Mead"
26 __date__ = "2010-02-08"
27 __version__ = '2.0'
28
29 import math
30 import os
31 import random
32 import sys
33 import types
34 from rsa._compat import byte
35
36 # Display a warning that this insecure version is imported.
37 import warnings
38 warnings.warn('Insecure version of the RSA module is imported as %s' % __name__)
39 warnings.warn('This submodule is deprecated and will be completely removed as of version 4.0.',
40 DeprecationWarning)
41
42
43 def bit_size(number):
44 """Returns the number of bits required to hold a specific long number"""
45
46 return int(math.ceil(math.log(number,2)))
47
48 def gcd(p, q):
49 """Returns the greatest common divisor of p and q
50 >>> gcd(48, 180)
51 12
52 """
53 # Iterateive Version is faster and uses much less stack space
54 while q != 0:
55 if p < q: (p,q) = (q,p)
56 (p,q) = (q, p % q)
57 return p
58
59
60 def bytes2int(bytes):
61 r"""Converts a list of bytes or a string to an integer
62 """
63
64 if not (type(bytes) is types.ListType or type(bytes) is types.StringType):
65 raise TypeError("You must pass a string or a list")
66
67 # Convert byte stream to integer
68 integer = 0
69 for byte in bytes:
70 integer *= 256
71 if type(byte) is types.StringType: byte = ord(byte)
72 integer += byte
73
74 return integer
75
76 def int2bytes(number):
77 """
78 Converts a number to a string of bytes
79 """
80
81 if not (type(number) is types.LongType or type(number) is types.IntType):
82 raise TypeError("You must pass a long or an int")
83
84 string = ""
85
86 while number > 0:
87 string = "%s%s" % (byte(number & 0xFF), string)
88 number /= 256
89
90 return string
91
92 def to64(number):
93 """Converts a number in the range of 0 to 63 into base 64 digit
94 character in the range of '0'-'9', 'A'-'Z', 'a'-'z','-','_'.
95 """
96
97 if not (type(number) is types.LongType or type(number) is types.IntType):
98 raise TypeError("You must pass a long or an int")
99
100 if 0 <= number <= 9: #00-09 translates to '0' - '9'
101 return byte(number + 48)
102
103 if 10 <= number <= 35:
104 return byte(number + 55) #10-35 translates to 'A' - 'Z'
105
106 if 36 <= number <= 61:
107 return byte(number + 61) #36-61 translates to 'a' - 'z'
108
109 if number == 62: # 62 translates to '-' (minus)
110 return byte(45)
111
112 if number == 63: # 63 translates to '_' (underscore)
113 return byte(95)
114
115 raise ValueError('Invalid Base64 value: %i' % number)
116
117
118 def from64(number):
119 """Converts an ordinal character value in the range of
120 0-9,A-Z,a-z,-,_ to a number in the range of 0-63.
121 """
122
123 if not (type(number) is types.LongType or type(number) is types.IntType):
124 raise TypeError("You must pass a long or an int")
125
126 if 48 <= number <= 57: #ord('0') - ord('9') translates to 0-9
127 return(number - 48)
128
129 if 65 <= number <= 90: #ord('A') - ord('Z') translates to 10-35
130 return(number - 55)
131
132 if 97 <= number <= 122: #ord('a') - ord('z') translates to 36-61
133 return(number - 61)
134
135 if number == 45: #ord('-') translates to 62
136 return(62)
137
138 if number == 95: #ord('_') translates to 63
139 return(63)
140
141 raise ValueError('Invalid Base64 value: %i' % number)
142
143
144 def int2str64(number):
145 """Converts a number to a string of base64 encoded characters in
146 the range of '0'-'9','A'-'Z,'a'-'z','-','_'.
147 """
148
149 if not (type(number) is types.LongType or type(number) is types.IntType):
150 raise TypeError("You must pass a long or an int")
151
152 string = ""
153
154 while number > 0:
155 string = "%s%s" % (to64(number & 0x3F), string)
156 number /= 64
157
158 return string
159
160
161 def str642int(string):
162 """Converts a base64 encoded string into an integer.
163 The chars of this string in in the range '0'-'9','A'-'Z','a'-'z','-','_'
164 """
165
166 if not (type(string) is types.ListType or type(string) is types.StringType):
167 raise TypeError("You must pass a string or a list")
168
169 integer = 0
170 for byte in string:
171 integer *= 64
172 if type(byte) is types.StringType: byte = ord(byte)
173 integer += from64(byte)
174
175 return integer
176
177 def read_random_int(nbits):
178 """Reads a random integer of approximately nbits bits rounded up
179 to whole bytes"""
180
181 nbytes = int(math.ceil(nbits/8.))
182 randomdata = os.urandom(nbytes)
183 return bytes2int(randomdata)
184
185 def randint(minvalue, maxvalue):
186 """Returns a random integer x with minvalue <= x <= maxvalue"""
187
188 # Safety - get a lot of random data even if the range is fairly
189 # small
190 min_nbits = 32
191
192 # The range of the random numbers we need to generate
193 range = (maxvalue - minvalue) + 1
194
195 # Which is this number of bytes
196 rangebytes = ((bit_size(range) + 7) / 8)
197
198 # Convert to bits, but make sure it's always at least min_nbits*2
199 rangebits = max(rangebytes * 8, min_nbits * 2)
200
201 # Take a random number of bits between min_nbits and rangebits
202 nbits = random.randint(min_nbits, rangebits)
203
204 return (read_random_int(nbits) % range) + minvalue
205
206 def jacobi(a, b):
207 """Calculates the value of the Jacobi symbol (a/b)
208 where both a and b are positive integers, and b is odd
209 """
210
211 if a == 0: return 0
212 result = 1
213 while a > 1:
214 if a & 1:
215 if ((a-1)*(b-1) >> 2) & 1:
216 result = -result
217 a, b = b % a, a
218 else:
219 if (((b * b) - 1) >> 3) & 1:
220 result = -result
221 a >>= 1
222 if a == 0: return 0
223 return result
224
225 def jacobi_witness(x, n):
226 """Returns False if n is an Euler pseudo-prime with base x, and
227 True otherwise.
228 """
229
230 j = jacobi(x, n) % n
231 f = pow(x, (n-1)/2, n)
232
233 if j == f: return False
234 return True
235
236 def randomized_primality_testing(n, k):
237 """Calculates whether n is composite (which is always correct) or
238 prime (which is incorrect with error probability 2**-k)
239
240 Returns False if the number is composite, and True if it's
241 probably prime.
242 """
243
244 # 50% of Jacobi-witnesses can report compositness of non-prime numbers
245
246 for i in range(k):
247 x = randint(1, n-1)
248 if jacobi_witness(x, n): return False
249
250 return True
251
252 def is_prime(number):
253 """Returns True if the number is prime, and False otherwise.
254 """
255
256 if randomized_primality_testing(number, 6):
257 # Prime, according to Jacobi
258 return True
259
260 # Not prime
261 return False
262
263
264 def getprime(nbits):
265 """Returns a prime number of max. 'math.ceil(nbits/8)*8' bits. In
266 other words: nbits is rounded up to whole bytes.
267 """
268
269 while True:
270 integer = read_random_int(nbits)
271
272 # Make sure it's odd
273 integer |= 1
274
275 # Test for primeness
276 if is_prime(integer): break
277
278 # Retry if not prime
279
280 return integer
281
282 def are_relatively_prime(a, b):
283 """Returns True if a and b are relatively prime, and False if they
284 are not.
285
286 >>> are_relatively_prime(2, 3)
287 1
288 >>> are_relatively_prime(2, 4)
289 0
290 """
291
292 d = gcd(a, b)
293 return (d == 1)
294
295 def find_p_q(nbits):
296 """Returns a tuple of two different primes of nbits bits"""
297 pbits = nbits + (nbits/16) #Make sure that p and q aren't too close
298 qbits = nbits - (nbits/16) #or the factoring programs can factor n
299 p = getprime(pbits)
300 while True:
301 q = getprime(qbits)
302 #Make sure p and q are different.
303 if not q == p: break
304 return (p, q)
305
306 def extended_gcd(a, b):
307 """Returns a tuple (r, i, j) such that r = gcd(a, b) = ia + jb
308 """
309 # r = gcd(a,b) i = multiplicitive inverse of a mod b
310 # or j = multiplicitive inverse of b mod a
311 # Neg return values for i or j are made positive mod b or a respectively
312 # Iterateive Version is faster and uses much less stack space
313 x = 0
314 y = 1
315 lx = 1
316 ly = 0
317 oa = a #Remember original a/b to remove
318 ob = b #negative values from return results
319 while b != 0:
320 q = long(a/b)
321 (a, b) = (b, a % b)
322 (x, lx) = ((lx - (q * x)),x)
323 (y, ly) = ((ly - (q * y)),y)
324 if (lx < 0): lx += ob #If neg wrap modulo orignal b
325 if (ly < 0): ly += oa #If neg wrap modulo orignal a
326 return (a, lx, ly) #Return only positive values
327
328 # Main function: calculate encryption and decryption keys
329 def calculate_keys(p, q, nbits):
330 """Calculates an encryption and a decryption key for p and q, and
331 returns them as a tuple (e, d)"""
332
333 n = p * q
334 phi_n = (p-1) * (q-1)
335
336 while True:
337 # Make sure e has enough bits so we ensure "wrapping" through
338 # modulo n
339 e = max(65537,getprime(nbits/4))
340 if are_relatively_prime(e, n) and are_relatively_prime(e, phi_n): break
341
342 (d, i, j) = extended_gcd(e, phi_n)
343
344 if not d == 1:
345 raise Exception("e (%d) and phi_n (%d) are not relatively prime" % (e, p hi_n))
346 if (i < 0):
347 raise Exception("New extended_gcd shouldn't return negative values")
348 if not (e * i) % phi_n == 1:
349 raise Exception("e (%d) and i (%d) are not mult. inv. modulo phi_n (%d)" % (e, i, phi_n))
350
351 return (e, i)
352
353
354 def gen_keys(nbits):
355 """Generate RSA keys of nbits bits. Returns (p, q, e, d).
356
357 Note: this can take a long time, depending on the key size.
358 """
359
360 (p, q) = find_p_q(nbits)
361 (e, d) = calculate_keys(p, q, nbits)
362
363 return (p, q, e, d)
364
365 def newkeys(nbits):
366 """Generates public and private keys, and returns them as (pub,
367 priv).
368
369 The public key consists of a dict {e: ..., , n: ....). The private
370 key consists of a dict {d: ...., p: ...., q: ....).
371 """
372 nbits = max(9,nbits) # Don't let nbits go below 9 bits
373 (p, q, e, d) = gen_keys(nbits)
374
375 return ( {'e': e, 'n': p*q}, {'d': d, 'p': p, 'q': q} )
376
377 def encrypt_int(message, ekey, n):
378 """Encrypts a message using encryption key 'ekey', working modulo n"""
379
380 if type(message) is types.IntType:
381 message = long(message)
382
383 if not type(message) is types.LongType:
384 raise TypeError("You must pass a long or int")
385
386 if message < 0 or message > n:
387 raise OverflowError("The message is too long")
388
389 #Note: Bit exponents start at zero (bit counts start at 1) this is correct
390 safebit = bit_size(n) - 2 #compute safe bit (MSB - 1)
391 message += (1 << safebit) #add safebit to ensure folding
392
393 return pow(message, ekey, n)
394
395 def decrypt_int(cyphertext, dkey, n):
396 """Decrypts a cypher text using the decryption key 'dkey', working
397 modulo n"""
398
399 message = pow(cyphertext, dkey, n)
400
401 safebit = bit_size(n) - 2 #compute safe bit (MSB - 1)
402 message -= (1 << safebit) #remove safebit before decode
403
404 return message
405
406 def encode64chops(chops):
407 """base64encodes chops and combines them into a ',' delimited string"""
408
409 chips = [] #chips are character chops
410
411 for value in chops:
412 chips.append(int2str64(value))
413
414 #delimit chops with comma
415 encoded = ','.join(chips)
416
417 return encoded
418
419 def decode64chops(string):
420 """base64decodes and makes a ',' delimited string into chops"""
421
422 chips = string.split(',') #split chops at commas
423
424 chops = []
425
426 for string in chips: #make char chops (chips) into chops
427 chops.append(str642int(string))
428
429 return chops
430
431 def chopstring(message, key, n, funcref):
432 """Chops the 'message' into integers that fit into n,
433 leaving room for a safebit to be added to ensure that all
434 messages fold during exponentiation. The MSB of the number n
435 is not independant modulo n (setting it could cause overflow), so
436 use the next lower bit for the safebit. Therefore reserve 2-bits
437 in the number n for non-data bits. Calls specified encryption
438 function for each chop.
439
440 Used by 'encrypt' and 'sign'.
441 """
442
443 msglen = len(message)
444 mbits = msglen * 8
445 #Set aside 2-bits so setting of safebit won't overflow modulo n.
446 nbits = bit_size(n) - 2 # leave room for safebit
447 nbytes = nbits / 8
448 blocks = msglen / nbytes
449
450 if msglen % nbytes > 0:
451 blocks += 1
452
453 cypher = []
454
455 for bindex in range(blocks):
456 offset = bindex * nbytes
457 block = message[offset:offset+nbytes]
458 value = bytes2int(block)
459 cypher.append(funcref(value, key, n))
460
461 return encode64chops(cypher) #Encode encrypted ints to base64 strings
462
463 def gluechops(string, key, n, funcref):
464 """Glues chops back together into a string. calls
465 funcref(integer, key, n) for each chop.
466
467 Used by 'decrypt' and 'verify'.
468 """
469 message = ""
470
471 chops = decode64chops(string) #Decode base64 strings into integer chops
472
473 for cpart in chops:
474 mpart = funcref(cpart, key, n) #Decrypt each chop
475 message += int2bytes(mpart) #Combine decrypted strings into a msg
476
477 return message
478
479 def encrypt(message, key):
480 """Encrypts a string 'message' with the public key 'key'"""
481 if 'n' not in key:
482 raise Exception("You must use the public key with encrypt")
483
484 return chopstring(message, key['e'], key['n'], encrypt_int)
485
486 def sign(message, key):
487 """Signs a string 'message' with the private key 'key'"""
488 if 'p' not in key:
489 raise Exception("You must use the private key with sign")
490
491 return chopstring(message, key['d'], key['p']*key['q'], encrypt_int)
492
493 def decrypt(cypher, key):
494 """Decrypts a string 'cypher' with the private key 'key'"""
495 if 'p' not in key:
496 raise Exception("You must use the private key with decrypt")
497
498 return gluechops(cypher, key['d'], key['p']*key['q'], decrypt_int)
499
500 def verify(cypher, key):
501 """Verifies a string 'cypher' with the public key 'key'"""
502 if 'n' not in key:
503 raise Exception("You must use the public key with verify")
504
505 return gluechops(cypher, key['e'], key['n'], decrypt_int)
506
507 # Do doctest if we're not imported
508 if __name__ == "__main__":
509 import doctest
510 doctest.testmod()
511
512 __all__ = ["newkeys", "encrypt", "decrypt", "sign", "verify"]
513
OLDNEW
« no previous file with comments | « third_party/google-endpoints/rsa/_version133.py ('k') | third_party/google-endpoints/rsa/asn1.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698