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