SHOW:
|
|
- or go back to the newest paste.
| 1 | #!/usr/bin/env python2.6 | |
| 2 | """ | |
| 3 | rsa.py | |
| 4 | ||
| 5 | Key generation, encryption, decryption via standard RSA. | |
| 6 | http://programmingpraxis.com/2010/11/16/rsa-cryptography/ | |
| 7 | ||
| 8 | GRE, 11/19/10 | |
| 9 | """ | |
| 10 | ||
| 11 | ########################################## | |
| 12 | # # | |
| 13 | # Preliminaries # | |
| 14 | # # | |
| 15 | ########################################## | |
| 16 | ||
| 17 | import random | |
| 18 | try: | |
| 19 | # If we can use gmpy's fast procedures, we will... | |
| 20 | import gmpy | |
| 21 | ||
| 22 | def prime_gen(k): | |
| 23 | """ | |
| 24 | Prime number p in [2^(k/2-1), 2^(k/2). | |
| 25 | """ | |
| 26 | assert k >= 1, "Sorry, need a bigger input" | |
| 27 | p = 0 | |
| 28 | while not gmpy.is_prime(p): | |
| 29 | p = random.randrange(pow(2, k//2-1) + 1, pow(2, k//2), 2) | |
| 30 | return p | |
| 31 | ||
| 32 | def extended_euclid(a, m): | |
| 33 | return [int(x) for x in gmpy.gcdext(a, m)] | |
| 34 | ||
| 35 | except ImportError: | |
| 36 | # ...if we can't, we build our own. | |
| 37 | def gcd(a, b): | |
| 38 | while b: | |
| 39 | a, b = b, a % b | |
| 40 | return a | |
| 41 | ||
| 42 | def extended_euclid(a, b): | |
| 43 | (x1, x2, x3) = (1, 0, a) | |
| 44 | (y1, y2, y3) = (0, 1, b) | |
| 45 | while (y3 != 0): | |
| 46 | quotient = x3 / y3 | |
| 47 | tmp1 = x1 - quotient * y1 | |
| 48 | tmp2 = x2 - quotient * y2 | |
| 49 | tmp3 = x3 - quotient * y3 | |
| 50 | (x1, x2, x3) = (y1, y2, y3) | |
| 51 | (y1, y2, y3) = (tmp1, tmp2, tmp3) | |
| 52 | return x3, x1, x2 | |
| 53 | ||
| 54 | # Miller-Rabin primality stuff: | |
| 55 | ||
| 56 | def split(n): | |
| 57 | """ | |
| 58 | Splits n into 2^s * r for an odd r; used in Miller-Rabin. | |
| 59 | """ | |
| 60 | s = 0 | |
| 61 | while (n > 0) and (n % 2 == 0): | |
| 62 | s += 1 | |
| 63 | n >>= 1 | |
| 64 | return (s,n) | |
| 65 | ||
| 66 | ||
| 67 | def P(a,r,s,n): | |
| 68 | """ | |
| 69 | Condition for primality in Miller-Rabin test. | |
| 70 | """ | |
| 71 | if pow(a, r, n) == 1: | |
| 72 | return True | |
| 73 | elif (n - 1) in [pow(a, r*(2**j), n) for j in range(s)]: | |
| 74 | return True | |
| 75 | else: | |
| 76 | return False | |
| 77 | ||
| 78 | ||
| 79 | def miller_rabin(n, t): | |
| 80 | """ | |
| 81 | Tests n for primality t times. | |
| 82 | """ | |
| 83 | (s, r) = split(n - 1) | |
| 84 | for i in xrange(t): | |
| 85 | a = random.randint(2, n-1) | |
| 86 | if not P(a, r, s, n): | |
| 87 | return False | |
| 88 | return True | |
| 89 | ||
| 90 | ||
| 91 | def prime_gen(k): | |
| 92 | """ | |
| 93 | Generates an odd that passes the Miller Rabin primality test for t = 50 | |
| 94 | in the interval [2^(k-1), 2^k]. | |
| 95 | """ | |
| 96 | assert k >= 1, "Sorry, need a bigger input" | |
| 97 | p = 0 | |
| 98 | while (p == 0): | |
| 99 | p = random.randrange(pow(2,k//2-1) + 1, pow(2, k//2), 2) | |
| 100 | if not miller_rabin(p, 50): | |
| 101 | p = 0 | |
| 102 | return p | |
| 103 | ||
| 104 | finally: | |
| 105 | # Modular inversion | |
| 106 | def mod_inv(a, m): | |
| 107 | g, s, t = extended_euclid(a, m) | |
| 108 | if g == 1: | |
| 109 | return s % m | |
| 110 | else: | |
| 111 | return None | |
| 112 | ||
| 113 | ########################################## | |
| 114 | # # | |
| 115 | # Main Work # | |
| 116 | # # | |
| 117 | ########################################## | |
| 118 | ||
| 119 | def key_gen(k = 32, e = prime_gen(32)): | |
| 120 | """ | |
| 121 | Build keys for RSA | |
| 122 | """ | |
| 123 | p = prime_gen(k) | |
| 124 | q = prime_gen(k) | |
| 125 | d = mod_inv(e, (p-1)*(q-1)) | |
| 126 | return p*q, d | |
| 127 | ||
| 128 | ||
| 129 | ||
| 130 | def crypt(message, key, mod): | |
| 131 | return pow(message, key, mod) | |
| 132 | ||
| 133 | ||
| 134 | ########################################## | |
| 135 | # # | |
| 136 | # Testing # | |
| 137 | # # | |
| 138 | ########################################## | |
| 139 | if __name__ == '__main__': | |
| 140 | k = 32 | |
| 141 | e = 65537 | |
| 142 | n, d = key_gen(k, e) | |
| 143 | print "n = %s\nd = %s" % (n, d) | |
| 144 | m = 42 | |
| 145 | print "Message m = %s" % m | |
| 146 | c = crypt(m, e, n) | |
| 147 | print "Encrypted c = %s" % c | |
| 148 | m2 = crypt(c, d, n) | |
| 149 | print "Decrypted m2 = %s" % m2 |