Examples¶
The following have been adapted from Pycryptodome’s documentation.
Encrypt data with AES¶
The following code generates a new 32 byte key and encrypts a piece of data. We use the GCM mode because it allows the receiver to detect any unauthorized modification (similarly, we could have used other authenticated encryption modes like EAX, CCM or SIV)
import os
from pyflocker.ciphers import AES
data = b"baba booey; fafa fooey; le fishe; monke"
key, nonce = os.urandom(32), os.urandom(16)
cipher = AES.new(True, key, AES.MODE_GCM, nonce)
ciphertext = cipher.update(data)
cipher.finalize()
tag = cipher.calculate_tag()
print("Plaintext:", data)
print("Ciphertext:", ciphertext)
print("Tag:", tag)
We can also use other symmetric ciphers like Camellia and ChaCha20.
Encrypt files and file-like objects with symmetric cipher¶
The following code creates a symmetric cipher (here Camellia cipher) and reads data from a file and writes the encrypted data into another file.
from pyflocker.ciphers import Camellia
from pyflocker.ciphers.modes import Modes
infile = open("somedata.bin", "rb")
outfile = open("encrypted.bin", "wb")
key, nonce = os.urandom(32), os.urandom(16)
cipher = Camellia.new(True, key, Modes.MODE_CTR, nonce, file=infile)
cipher.update_into(outfile)
print("Tag:", cipher.calculate_tag())
Similarly, we can also use AES and ChaCha20.
Important
Only those modes that are not defined in pyflocker.ciphers.modes.special
support file encryption/decryption.
Quick file encryption and decryption¶
The following code demonstrates the use of pyflocker.locker
for
encrypting and decrypting files
from pyflocker import locker
password = b"my-super-secret-password"
locker.locker("top-secret-file.txt", password)
You can use a different AES mode too.
from pyflocker import locker
from pyflocker.ciphers import AES
password = b"my-super-secret-password"
locker.locker("top-secret-file.txt", password, aes_mode=AES.MODE_CFB8)
Important
Only those modes that are not defined in pyflocker.ciphers.modes.special
support file encryption/decryption.
Creating, Serializing and Loading an asymmetric key¶
Here, we will use RSA as an example.
Creation¶
from pyflocker.ciphers import RSA
private = RSA.generate(2048)
public = RSA.public_key()
Serialization¶
By default, RSA uses PKCS8
format with PEM
encoding, but you can
use different parameters.
passphrase = b"no not this"
# Serialize the private key
with open("private.pem", "wb") as file:
file.write(private.serialize(passphrase=passphrase))
# Serialize the public key
with open("public.pem", "wb") as file:
file.write(public.serialize())
Loading the keys¶
# Load the private key
with open("private.pem", "rb") as file:
private = RSA.load_private_key(file.read(), passphrase)
# Load the public key
with open("public.pem", "rb") as file:
public = RSA.load_public_key(file.read())
Encryption and Decryption with RSA¶
The following code encrypts a piece of data for a receiver we have the RSA
public key of. The RSA public key is stored in a file called receiver.pem
.
Since we want to be able to encrypt an arbitrary amount of data, we use a hybrid encryption scheme. We use RSA with PKCS#1 OAEP for asymmetric encryption of an AES session key. The session key can then be used to encrypt all the actual data.
Here, we will use the CTR mode with HMAC to allow detection of unauthorized modifications. You can use any mode.
First, we will create a file to read data from:
data = b"""\
Hello world this is a text that will be encrypted.
Add some more of your own here.
"""
with open("somedata.txt", "wb") as file:
file.write(data)
Encryption¶
Next, we will read the data from somedata.txt
and encrypt it.
import os
from pyflocker.ciphers import AES, RSA, OAEP
# Load the receiver's public key.
with open("receiver.pem", "rb") as file:
public = RSA.load_public_key(file.read())
# Create an AES cipher with session key:
# This will be used to encrypt an arbitrary amount of data.
session_key, nonce = os.urandom(32), os.urandom(16)
cipher_aes = AES.new(
True,
session_key,
AES.MODE_CTR,
nonce,
use_hmac=True,
)
# Use the public key to encrypt the session key.
cipher_rsa = public.encryptor(OAEP())
enc_session_key = cipher_rsa.encrypt(session_key)
with open("somedata.txt", "rb") as file:
ciphertext = cipher_aes.update(file.read())
# Calculate the cipher tag
cipher_aes.finalize()
tag = cipher_aes.calculate_tag()
with open("encrypted.bin", "wb") as file:
file.write(
b"".join(
(
enc_session_key,
nonce,
tag,
ciphertext,
)
)
)
Decryption¶
Decryption process is the inverse of encryption. The receiver will decrypt the
encrypted session key and use it to decrypt the encrypted file (here
encrypted.bin
)
from pyflocker.ciphers import AES, RSA, OAEP
# The receiver loads their private key.
with open("private.pem", "rb") as file:
private = RSA.load_private_key(file.read())
# Read the encrypted file and separate the parts.
with open("encrypted.bin", "rb") as file:
(
enc_session_key,
nonce,
tag,
ciphertext,
) = [file.read(n) for n in (private.n.bit_length() // 8, 16, 16, -1)]
# Decrypt the session key and create a cipher.
dec = private.decryptor(OAEP())
session_key = dec.decrypt(enc_session_key)
cipher_aes = AES.new(
False,
session_key,
AES.MODE_CTR,
nonce,
use_hmac=True,
)
# Decrypt the ciphertext and verify the decryption.
plaintext = cipher_aes.update(ciphertext)
cipher_aes.finalize(tag)
print(plaintext)