View difference between Paste ID: 6NBK7jZz and PanJAtzk
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