CS1302 Introduction to Computer Programming
This notebook will introduce the idea of public-key (asymmetric key) cryptography called the RSA algorithm.
Motivation¶
What is public key encryption?
Suppose there is one receiver trying to receive private messsages from multiple senders.
Solution to Exercise 1
- Easy to share keys: Encryption key can be shared to all senders publicly.
- Easy to store keys: Only the receiver needs to know the private key.
Is public key encryption possible?
Unfortunately, public key encryption is an invertible function given a public key:
YOUR ANSWER HERE
How to make public key encryption secure?
We can make it computationally infeasible to invert unless with the private key is available. Such a function is called the trapdoor function. An example of a trapdoor function is:
As the size of and increases, the time required to factor increases dramatically as illustrated here.
RSA Algorithm¶
How to encrypt/decrypt?
The encryption and decryption use modulo exponentiation instead of addition:
and , , and are positive integers.
Computing exponentiation can be fast using repeated squaring. The built-in function pow already has an efficient implementation:
%%timeit
x, e, n = 3, 2 ** 1000000, 4
pow(x, e, n)%%timeit
def modulo_power(x, e, n):
# YOUR CODE HERE
raise NotImplementedError()
x, e, n = 3, 2 ** 1000000, 4
pow(x, e, n)How to ensure decryptability?
For , we need and
Solution to Exercise 4
RSA makes use of the following result to choose :
There are elegant and elementary combinatorial proofs.
No because the private key can then be easily computed from the public key: .
Can we have and ?
No because is the modular multiplicative inverse of , which is easy to compute, e.g., using pow with an exponent of -1. In particular, for prime modulus here, the inverse is :
e, n = 3, 7
d = pow(e, -1, n)
d, e * d % n == 1 and d == e ** (n - 2) % nHow to make it difficult to compute ?
RSA makes use of the hardness of factoring a product of large primes to create the desired trapdoor function.
This implies is divisible by both and , and so
Raising both sides to the power of any positive integer give:
Although is still the modulo multiplicative inverse of , it is with respect to , which is not easy to compute without knowing the factors of , namely and . It can be shown that computing is as hard as computing or factoring .
How to generate the public key and private key?
By (12), we can compute as the modulo multiplicative inverse of . How to choose then?
We can choose any such that does not divide .
YOUR ANSWER HERE
The following function randomly generate the e, d, n for some given prime numbers p and q:
from math import gcd
from random import randint
def get_rsa_keys(p, q):
n = p * q
lcm = (p - 1) * (q - 1) // gcd(p - 1, q - 1)
while True:
e = randint(1, lcm - 1)
if gcd(e, lcm) == 1:
break
d = pow(e, -1, lcm)
return e, d, n, lcmNote that
As an example, if we choose two prime numbers and :
e, d, n, lcm = get_rsa_keys(17094589121, 1062873761)
e, d, n, e * d % lcm == 1The integer can be encrypted as follows:
x = 1302
c = pow(x, e, n)
print(f'The plain text "{x}" has been encrypted into "{c}".')With the private key , the ciphertext can be decrypted easily as
output = pow(c, d, n)
print(f'The cipher "{c}" has been decrypted into "{output}".')