Skip to content

Commit 0115ee7

Browse files
Merge pull request #53 from prateekiiest/master
Upadated RSA Algorithm under Cryptography Section
2 parents 02ea8d0 + ab9e034 commit 0115ee7

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

Diff for: Cryptography/RSA.py

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import random
2+
3+
4+
'''
5+
Euclid's algorithm for determining the greatest common divisor
6+
Use iteration to make it faster for larger integers
7+
'''
8+
def gcd(a, b):
9+
while b != 0:
10+
a, b = b, a % b
11+
return a
12+
13+
'''
14+
Euclid's extended algorithm for finding the multiplicative inverse of two numbers
15+
'''
16+
def multiplicative_inverse(e, phi):
17+
d = 0
18+
x1 = 0
19+
x2 = 1
20+
y1 = 1
21+
temp_phi = phi
22+
23+
while e > 0:
24+
temp1 = temp_phi/e
25+
temp2 = temp_phi - temp1 * e
26+
temp_phi = e
27+
e = temp2
28+
29+
x = x2- temp1* x1
30+
y = d - temp1 * y1
31+
32+
x2 = x1
33+
x1 = x
34+
d = y1
35+
y1 = y
36+
37+
if temp_phi == 1:
38+
return d + phi
39+
40+
'''
41+
Tests to see if a number is prime.
42+
'''
43+
def is_prime(num):
44+
if num == 2:
45+
return True
46+
if num < 2 or num % 2 == 0:
47+
return False
48+
for n in xrange(3, int(num**0.5)+2, 2):
49+
if num % n == 0:
50+
return False
51+
return True
52+
53+
def generate_keypair(p, q):
54+
if not (is_prime(p) and is_prime(q)):
55+
raise ValueError('Both numbers must be prime.')
56+
elif p == q:
57+
raise ValueError('p and q cannot be equal')
58+
#n = pq
59+
n = p * q
60+
61+
#Phi is the totient of n
62+
phi = (p-1) * (q-1)
63+
64+
#Choose an integer e such that e and phi(n) are coprime
65+
e = random.randrange(1, phi)
66+
67+
#Use Euclid's Algorithm to verify that e and phi(n) are comprime
68+
g = gcd(e, phi)
69+
while g != 1:
70+
e = random.randrange(1, phi)
71+
g = gcd(e, phi)
72+
73+
#Use Extended Euclid's Algorithm to generate the private key
74+
d = multiplicative_inverse(e, phi)
75+
76+
#Return public and private keypair
77+
#Public key is (e, n) and private key is (d, n)
78+
return ((e, n), (d, n))
79+
80+
def encrypt(pk, plaintext):
81+
#Unpack the key into it's components
82+
key, n = pk
83+
#Convert each letter in the plaintext to numbers based on the character using a^b mod m
84+
cipher = [(ord(char) ** key) % n for char in plaintext]
85+
#Return the array of bytes
86+
return cipher
87+
88+
def decrypt(pk, ciphertext):
89+
#Unpack the key into its components
90+
key, n = pk
91+
#Generate the plaintext based on the ciphertext and key using a^b mod m
92+
plain = [chr((char ** key) % n) for char in ciphertext]
93+
#Return the array of bytes as a string
94+
return ''.join(plain)
95+
96+
97+
if __name__ == '__main__':
98+
'''
99+
Detect if the script is being run directly by the user
100+
'''
101+
print "RSA Encrypter/ Decrypter"
102+
p = int(raw_input("Enter a prime number (17, 19, 23, etc): "))
103+
q = int(raw_input("Enter another prime number (Not one you entered above): "))
104+
print "Generating your public/private keypairs now . . ."
105+
public, private = generate_keypair(p, q)
106+
print "Your public key is ", public ," and your private key is ", private
107+
message = raw_input("Enter a message to encrypt with your private key: ")
108+
encrypted_msg = encrypt(private, message)
109+
print "Your encrypted message is: "
110+
print ''.join(map(lambda x: str(x), encrypted_msg))
111+
print "Decrypting message with public key ", public ," . . ."
112+
print "Your message is:"
113+
print decrypt(public, encrypted_msg)

0 commit comments

Comments
 (0)