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