In this tutorial, we will learn how to use the RSA algorithm in Python. The RSA (Rivest-Shamir-Adleman) algorithm is a widely used public key cryptography algorithm that allows for secure data transmission. We will be using the cryptography library in Python to perform encryption and decryption using RSA keys.
To get started, first, make sure you have the cryptography library installed. If not, you can install it using pip:
1 |
pip install cryptography |
Step 1: Generate RSA key pair
The first step is to generate a key pair (public and private keys) that will be used for encryption and decryption. The recommended key size is 2048 bits or higher for better security.
1 2 3 4 5 6 7 8 9 10 11 12 |
from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives import serialization from cryptography.hazmat.backends import default_backend def generate_rsa_key_pair(key_size): private_key = rsa.generate_private_key(public_exponent=65537, key_size=key_size, backend=default_backend()) public_key = private_key.public_key() return private_key, public_key |
Now we can generate a 2048-bit RSA key pair:
1 |
private_key, public_key = generate_rsa_key_pair(2048) |
Step 2: Serialize RSA keys
Now that we have generated our key pair, we need to serialize them so they can be saved or transmitted securely. We will use the PEM format and encrypt the private key with a passphrase.
1 2 3 4 5 6 7 8 |
def serialize_private_key(private_key, passphrase): return private_key.private_bytes(encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.BestAvailableEncryption(passphrase.encode("utf-8"))) def serialize_public_key(public_key): return public_key.public_bytes(encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo) |
Serialize keys and save them:
1 2 3 4 5 |
with open("private_key.pem", "wb") as f: f.write(serialize_private_key(private_key, "your_passphrase")) with open("public_key.pem", "wb") as f: f.write(serialize_public_key(public_key)) |
Step 3: Load RSA keys
Now, let’s load the serialized RSA keys back from the files.
1 2 3 4 5 6 7 |
def load_private_key(file_path, passphrase): with open(file_path, "rb") as f: return serialization.load_pem_private_key(f.read(), password=passphrase.encode("utf-8"), backend=default_backend()) def load_public_key(file_path): with open(file_path, "rb") as f: return serialization.load_pem_public_key(f.read(), backend=default_backend()) |
Load keys:
1 2 |
private_key = load_private_key("private_key.pem", "your_passphrase") public_key = load_public_key("public_key.pem") |
Step 4: Encrypt and decrypt with RSA
Now that we have our keys, we can start encrypting and decrypting data. The cryptography library provides encrypt
and decrypt
methods for the public_key
and private_key
objects respectively.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
from cryptography.hazmat.primitives import padding, hashes from cryptography.hazmat.primitives.asymmetric import padding as asymmetric_padding def rsa_encrypt(plaintext, public_key): plaintext = plaintext.encode("utf-8") ciphertext = public_key.encrypt( plaintext, asymmetric_padding.OAEP( mgf=asymmetric_padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)) return ciphertext def rsa_decrypt(ciphertext, private_key): plaintext = private_key.decrypt( ciphertext, asymmetric_padding.OAEP( mgf=asymmetric_padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)) return plaintext.decode("utf-8") |
Now, let’s encrypt and decrypt a message:
1 2 3 4 5 6 7 |
message = "Hello, world!" encrypted_message = rsa_encrypt(message, public_key) print("Encrypted message:", encrypted_message) decrypted_message = rsa_decrypt(encrypted_message, private_key) print("Decrypted message:", decrypted_message) |
Encrypted message: b'\x1d\xf0...\xad\xb6' Decrypted message: Hello, world!
Full code example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives import serialization, padding, hashes from cryptography.hazmat.primitives.asymmetric import padding as asymmetric_padding from cryptography.hazmat.backends import default_backend def generate_rsa_key_pair(key_size): private_key = rsa.generate_private_key(public_exponent=65537, key_size=key_size, backend=default_backend()) public_key = private_key.public_key() return private_key, public_key def serialize_private_key(private_key, passphrase): return private_key.private_bytes(encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.BestAvailableEncryption(passphrase.encode("utf-8"))) def serialize_public_key(public_key): return public_key.public_bytes(encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo) def load_private_key(file_path, passphrase): with open(file_path, "rb") as f: return serialization.load_pem_private_key(f.read(), password=passphrase.encode("utf-8"), backend=default_backend()) def load_public_key(file_path): with open(file_path, "rb") as f: return serialization.load_pem_public_key(f.read(), backend=default_backend()) def rsa_encrypt(plaintext, public_key): plaintext = plaintext.encode("utf-8") ciphertext = public_key.encrypt( plaintext, asymmetric_padding.OAEP( mgf=asymmetric_padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)) return ciphertext def rsa_decrypt(ciphertext, private_key): plaintext = private_key.decrypt( ciphertext, asymmetric_padding.OAEP( mgf=asymmetric_padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)) return plaintext.decode("utf-8") private_key, public_key = generate_rsa_key_pair(2048) with open("private_key.pem", "wb") as f: f.write(serialize_private_key(private_key, "your_passphrase")) with open("public_key.pem", "wb") as f: f.write(serialize_public_key(public_key)) private_key = load_private_key("private_key.pem", "your_passphrase") public_key = load_public_key("public_key.pem") message = "Hello, world!" encrypted_message = rsa_encrypt(message, public_key) print("Encrypted message:", encrypted_message) decrypted_message = rsa_decrypt(encrypted_message, private_key) print("Decrypted message:", decrypted_message) |
Output
Encrypted message: b's\xe3\x95\xc7g\xa8pc4\x87\xf7\xbe4AN\x14\x9b\xb2\xde\xdb\xe9\xbb\xbew\xce\xf9\xde\x14Z\x8b\x89\xee\x80&RI\xe9&\xa6\xd9\x80O\x88)\xb65s\xd7k\xec\xbd\xfa\xd8\xb0^\xad"\n\xcc\x94r\xbcJ\xc5\x8d\xc5\xd6\xf9\xa4\xf2n+\xf3\xa2\xe2\x96\xd9\x18H\xe06}\x00b\xbaP\xc4\x8f\xef\x03\x19<\x87\n\x0f\xdf\x16(\xdb\x90\xe5\x80\x1b\xaa\xc6\xb7\xe6\x9ej\x82D-\xc4\xbe\xe2\x07\x0eX\xe4aHJ\x90x\x06\xbf\x83\x8f\xf89\x80.\xb3\xf3zZ\xb2VX
\x87\xdb\xcc\xad\xc3\x05,=\xfb_1\x9e\xd9\x87\xabw\nK\xe9\xed\xd0\xd2\xfb\xf0;\xd0\xb7\x05.\x06\xd94T_\x98\x08\xef\x8dI\xd2\x15\xae+\xd7\xbf\xd4\x0e\x9aC\xcc9L\xa8\xc4\xda\xb9\x1ap%\xc5\xfb\x7f\xe42q\xb0\x12\xd9\xf5\xd6\r\x8e\xf6\x12R\xf4_3|}\xb2\xb0\x02\xc7\xd2\xe0P\x924\xeb;\x1b\xee\xf8\x18\x97|\xc9\x89+\x99\xa1\xc1H\xfa\xaaE\x8f\xa2f\x8c8\xf1C\xb4'
Decrypted message: Hello, world!
Conclusion
In this tutorial, we learned how to use the RSA algorithm in Python with the help of the cryptography library. We generated an RSA key pair, serialized the keys, loaded them back, and encrypted and decrypted messages using the keys. This can be very useful for creating secure communications between applications and systems.