RSA: encryption and decryption
Encryption
# pip install pycryptodome
from Crypto.Util.number import bytes_to_long, getPrime
# Plaintext as bytes
pt = b"Some plaintext message to be encrypted"
# Converted to an integer (m)
m = bytes_to_long(pt)
# Get 1024-bit primes (p and q)
p = getPrime(1024)
q = getPrime(1024)
# Multiplying p and q gives us a 2048-bit public modulus (n)
n = p * q
# Public exponent (e)
# This is the 4th of Fermat's primes: https://en.wikipedia.org/wiki/Fermat_number
e = 65537
# Ciphertext (c) - `m` to the power of `e` modulo `n`
c = pow(m, e, n)
# The message (m) and the primes (p and q) are kept secret
# The public exponent (e), ciphertext (c) and public modulus (n) may be sharedDecryption
# Euler's totient (phi) - usually denoted as `φ(N)`
euler_phi = (p-1) * (q-1)
# Private key (d) - the modular inverse of `e`
# Requires that `e` and `euler_phi` are coprime
# If they are not coprime, `e` may not be invertible mod `d`
# `d` inverts `e` modulo `n`: `e * d ≡ 1 mod n` or simpler `(e * d) % n == 1`
assert gcd(e, euler_phi) == 1
d = pow(e, -1, euler_phi)
# The original message (m) can be recovered
m = pow(c, d, n)In reality the message (m) should be padded. The padding alone can mitigate most of the weaknesses described below.