Experimenting with
Asymmetric Encryption and Decryption using RSA keys
The public key and the private key in the keypair are inverse keys. That is, data encrypted by the public key can only be successfully decrypted by using the private key; data encrypted by the private key can only be decrypted by the public key.
As shown in Figure 5.1 of the textbook (copied below), to send a confidential message to Bob using asymmetric cryptography, Alice uses Bob’s public key to encrypt the plaintext. The generated ciphertext from the encryption will then be made available to Bob. When Bob has accessed the ciphertext, he will use his own private key to decrypt the ciphertext in order to retrieve the original plaintext message.
Step A: Run the
following script to generate an RSA keypair and save the keys into files (the
public key in public_key.pem and the private key in private_key.pem.
Assumption: The generated private key and public key belongs to Bob, and the public key is made available to Alice.
NOTE: Normally, keys are generated using external tools such as openssl, keytool, etc.
# script: asymTest.py from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import rsa # key generations private_key = rsa.generate_private_key( public_exponent=65537, key_size=3072, backend=default_backend(), ) public_key = private_key.public_key() #serialization of the keys private_bytes = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption(),
) # Save the private key into the file private_key.pem. # If the file exists, overwirte it. with open('private_key.pem', 'wb') as private_file: private_file.write(private_bytes) public_bytes = public_key.public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo,
) # Save the public key into the file public_key.pem. # If the file exists, overwirte it. with open('public_key.pem', 'wb') as public_file: public_file.write(public_bytes) |
Figure 1: The script
of generating an RSA keypair and saving the private key into private_key.pem
and the public key into public_key.pem
The screen output of running the above script is shown in Figure 2.
Figure 2: Generating
an RSA keypair and save the private key into private_key.pem and public key
into public_key.pem
Step B: To generate a confidential file that only Bob can access, Alice will use Bob’s public key to encrypt a plaintext message and then saves the generated ciphertext in the file ciphertext.dat.
Assumption: The ciphertext.dat file will made available to Bob.
The script to generate the ciphertext file is shown in Figure 3.
# script: AliceEncrypt.py from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization # Deserialization of Bob's public key with open('public_key.pem', 'rb') as public_file: loaded_public_key =
serialization.load_pem_public_key( public_file.read(), backend=default_backend() ) padding_config = padding.OAEP( mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None, ) plaintext = b'message from Alice to Bob' ciphertext = loaded_public_key.encrypt( plaintext=plaintext, padding=padding_config, ) print("ciphertext (encrypted by Alice using Bob's public key):
", ciphertext) # Save the ciphertext to a file with open('ciphertext.dat', 'wb') as encrypted_file: encrypted_file.write(ciphertext) |
Figure 3: The script of generating the ciphertext.dat file from a
plaintext message
The screen output of running the above script is shown in Figure 4.
Figure 4: The screen
output of generating the ciphertext.dat file from a plaintext message
Step C: Assuming the ciphertext.dat file is made available to Bob (via file transfer or messaging), Bob will use his private key to decrypt the ciphertext in that file.
The script of loading the private key and the ciphertext is shown in Figure 5. Once loaded, the private key is used to decrypt the ciphertext.
# script:BobDecrypt.py from cryptography.hazmat.primitives
import hashes from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization # Deserialization of Bob's private key with open('private_key.pem', 'rb') as private_file: loaded_private_key =
serialization.load_pem_private_key( private_file.read(), password=None, backend=default_backend() ) padding_config = padding.OAEP( mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None, ) # Read the ciphertext file with open('ciphertext.dat', 'rb') as ciphertext_file: ciphertext =
ciphertext_file.read() decrypted_by_private_key = loaded_private_key.decrypt( ciphertext=ciphertext, padding=padding_config) #assert decrypted_by_private_key == plaintext print("The decrypted ciphertext: ",
decrypted_by_private_key) |
Figure 5: The screen
output of generating the ciphertext.dat file from a plaintext message
The screen output of running the above script is shown in Figure 6.
Figure 6: The screen output of
generating the ciphertext.dat file from a plaintext message