Asymmetric Encryption & Decryption in Python
Derick Zr • December 01, 2021
6 min read
Today, we live in a data-driven world, and in most use cases, businesses collect and store sensitive personal and non-personal information, which can be exploited by cyber criminals.
In simple word, Cryptography is associated with the process of converting ordinary plain text into unintelligible text and vice-versa. It is a method of storing and transmitting data in a particular form so that only those for whom it is intended can read and process it.
Cryptography ensures the integrity of data using hashing algorithms and message digests. By providing codes and digital keys to ensure that what is received is genuine and from the intended sender, the receiver is assured that the data received has been safe during transmission.
Usualy entreprises uses cryptography on a daily basis to protect enterprise information and communication from cyber threats through the use of codes. Cryptography achieves several information security-related objectives including confidentiality, integrity, and authentication, and non-repudiation. In this article, we explore what these reveal about cryptography.
How is cryptography used in cybersecurity?
Cryptography involves the use of mathematical concepts and a set of rule-based calculations, called algorithms, to transform messages in ways that are hard to decipher. These algorithms are then used for cryptographic key generation, digital signing, verification to protect data privacy, web browsing on the internet, and confidential communication like credit card transactions and emails.
Three types of cryptography
1. Secret Key Cryptography (SKC)
This type of cryptography is sometimes referred to as symmetric encryption, as it uses the same digital key for encryption and decryption. SKC is leveraged in use cases where privacy and confidentiality are priorities.
2. Public Key Cryptography (PKC)
Also called asymmetric encryption, PKC uses two different keys for encryption and decryption, which makes it suitable for authentication, non-repudiation, and key exchange.
3. Hash Functions
Hashing utilises mathematical algorithms to permanently encrypt information. Only systems that use the same algorithm can decrypt these messages. Hash functions are primarily used to ensure message integrity in high-risk environments.
How important is cryptography to security
When executed via the right strategies, cryptography helps you safeguard this sensitive information, preventing it from falling to cyber threats and threat actors.
Cryptography protects the confidentiality of information
Confidentiality is a key priority when it comes to cryptography. It means that only people with the right permission can access the information transmitted and that this information is protected from unauthorised access at all stages of its lifecycle. Confidentiality is necessary for maintaining the privacy of those whose personal information is stored in enterprise systems. Encryption, therefore, is the only way to ensure that your information remains secure while it’s stored and being transmitted. Now as we know what’s Cryptography, let’s see a practical example on how encryption and decryption work behind the scences. we will look into methods of generating keys, storing keys and using the asymmetric encryption method RSA to encrypt and decrypt messages and files.
DEMO
Installing cryptography
Since Python does not come with anything that can encrypt files, we will need to use a third-party module.
PyCrypto is quite popular but since it does not offer built wheels, if you don’t have Microsoft Visual C++ Build Tools installed, you will be told to install it. Instead of installing extra tools just to build this, I will be using the cryptography module. To install this, execute:
python -m pip install cryptography
To make sure it installed correctly, in your terminal execute:
python -m pip install cryptography
Getting a Key
To generate the two keys, we can call rsa.generate_private_key with some general parameters. The public key will be found in the object that holds the creation of the private key.
in your IDEA create a file [name].py
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
public_key = private_key.public_key()
Storing Keys
To store the keys in a file, the keys need to be serialized and then written to a file. To store the private key, we need to use the following.
...
pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
)
with open('private_key.pem', 'wb') as f:
f.write(pem)
You can protect the contents of this file using a top key serialization password find an example here
Reading Keys
To get the keys out of the files, we need to read each file and then load them. To read the private key, use the following.
...
with open("private_key.pem", "rb") as f:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
backend=default_backend()
)
If you store the key with a password, set password to what you used.
The variable private_key
will now have the private key
. To read the public key, we need to use a slightly modified version.
The variable public_key
will now have the public key
.
...
with open("public_key.pem", "rb") as f:
public_key = serialization.load_pem_public_key(
key_file.read(),
backend=default_backend()
)
EXAMPLE
to show this in action, here is a properly constructed example
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
# Generating a key
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
public_key = private_key.public_key()
# Storing the keys
pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
)
with open('Bank/private_key.pem', 'wb') as f:
f.write(pem)
with open('Grace/private_key.pem', 'wb') as f:
f.write(pem)
pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
with open('public_key.pem', 'wb') as f:
f.write(pem)
f = open('Bank/info.txt', 'rb')
message = f.read()
f.close()
encrypted = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
f = open('Grace/info.encrypted', 'wb')
f.write(encrypted)
f.close()
# Grace RECEIVED THE ENCRYPTED MESSAGE
# AND AUTOMATICALLY THE SYSTEM WILL DECRYPTED IT USING THE PRIVATE KEY of GRACE
original_message = private_key.decrypt(
encrypted,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
with open('Grace/Bank_info.txt','wb') as f:
f.write(original_message)
encrypting and Decrypting files
To encrypt and decrypt files, you will need to use read and write binary when opening files. You can simply substitute the values I previously used for message with the contents of a file. For example:
...
f = open('test.txt', 'rb')
message = f.read()
f.close()
Using the variable message
you can then encrypt it.
To store, you can use the general Python method when encryption returns bytes.
encrypted = 'data from encryption'
f = open('test.encrypted', 'wb')
f.write(encrypted)
f.close()
Now to decrypt you can easily read the data from test.encrypted like the first bit of code in this section, decrypt it and then write it back out to test.txt using the second bit of code in this section.
I really hope you had a good time reading this article and hopefully understood the concepts