Skip to content

Code Examples

Mattias Aabmets edited this page Jan 27, 2024 · 6 revisions

Table of Contents

  1. Key Encapsulation Mechanisms
  2. Digital Signature Schemes
  3. The Krypton Cipher
    1. Krypton for Basic Encryption
    2. KryptonFile for Symmetric File Encryption
    3. KryptonKEM for Asymmetric File Encryption
  4. Key Derivation Functions
    1. Argon2Hash for Comparing Password Hashes
    2. Argon2Key for High-Cost Key Derivation
    3. KKDF for Fast Key Derivation

Key Encapsulation Mechanisms

Link to KEM Source Code

from quantcrypt.kem import Kyber

# First, we create an instance of a KEM algorithm.
kem = Kyber()

# Next, we generate a PK and SK pair.
public_key, secret_key = kem.keygen()

# Then, we use the PK to encapsulate the internally 
# generated shared_secret bytes into cipher_text bytes.
cipher_text, shared_secret = kem.encaps(public_key)

# Finally, the secret_key is used to decapsulate the
# original shared_secret from the cipher_text bytes.
shared_secret_copy = kem.decaps(secret_key, cipher_text)

# Check that the shared secrets match
assert shared_secret_copy == shared_secret

Back to Top

Digital Signature Schemes

Link to DSS Source Code

from quantcrypt.dss import Dilithium, Falcon, FastSphincs, SmallSphincs

# First, we create an instance of a DSS algorithm
# and also define a message to be signed.
dss = Dilithium()
message = b'Hello World'

# Next, we generate a PK and SK pair.
public_key, secret_key = kem.keygen()

# Then, we use the secret_key to sign the message.
signature = dss.sign(secret_key, message)

# Finally, we use the public_key to verify the validity of the signature.
dss.verify(public_key, message, signature)

Back to Top

The Krypton Cipher

Krypton for Basic Encryption

Link to Krypton Source Code

import secrets
from quantcrypt.cipher import Krypton

# Krypton requires the symmetric secret key to be 64 bytes long.
secret_key = secrets.token_bytes(64)
plaintext = b"Hello World"

krypton = Krypton(secret_key)

# Encrypt the plaintext and generate the verification data packet.
krypton.begin_encryption()
ciphertext = krypton.encrypt(plaintext)
verif_dp = krypton.finish_encryption()

# Decrypt the plaintext and verify its validity in finish_decryption call.
krypton.begin_decryption(verif_dp)
plaintext_copy = krypton.decrypt(ciphertext)
krypton.finish_decryption()

assert plaintext_copy == plaintext

Back to Top

KryptonFile for Symmetric File Encryption

Link to KryptonFile Source Code

import secrets
from pathlib import Path
from quantcrypt.cipher import KryptonFile

# Krypton requires the symmetric secret key to be 64 bytes long.
secret_key = secrets.token_bytes(64)

# The plaintext file, which must exist, can be of any type and any size. 
plaintext_file = Path("/absolute/path/to/plaintext_file.any")

# If the ciphertext_file exists, it will be overwritten.
ciphertext_file = Path("/absolute/path/to/ciphertext_file.any")

# Create a Krypton instance with the secret key and encrypt the
# plaintext file contents into the designated ciphertext file.
krypton = KryptonFile(secret_key)
krypton.encrypt(plaintext_file, ciphertext_file)

# The ciphertext file can be decrypted into another file or into memory.
# Note: Do not decrypt huge files into memory, use your best judgement.
plaintext_file_copy = Path("/absolute/path/to/plaintext_file_copy.any")
krypton.decrypt_to_file(ciphertext_file, plaintext_file_copy)
plaintext_data = krypton.decrypt_to_memory(ciphertext_file)

Back to Top

KryptonKEM for Asymmetric File Encryption

Link to KryptonKEM Source Code

from pathlib import Path
from quantcrypt.kem import Kyber
from quantcrypt.cipher import KryptonKEM

# First we instantiate the KEM algorithm to generate a keypair.
kem = Kyber()
public_key, secret_key = kem.keygen()

# We need to provide KryptonKEM with the class of the 
# KEM algorithm which was used to generate the keypair.
krypton = KryptonKEM(Kyber)

# The plaintext file, which must exist, can be of any type and any size. 
plaintext_file = Path("/absolute/path/to/plaintext_file.any")

# If the ciphertext_file exists, it will be overwritten.
ciphertext_file = Path("/absolute/path/to/ciphertext_file.any")

# Use the public_key to encrypt the plaintext file 
# contents into the designated ciphertext file.
krypton.encrypt(public_key, plaintext_file, ciphertext_file)

# Use the secret_key to decrypt the ciphertext file into another file or into memory.
# Note: Do not decrypt huge files into memory, use your best judgement.
plaintext_file_copy = Path("/absolute/path/to/plaintext_file_copy.any")
krypton.decrypt_to_file(secret_key, ciphertext_file, plaintext_file_copy)
plaintext_data = krypton.decrypt_to_memory(secret_key, ciphertext_file)

Back to Top

Key Derivation Functions

Argon2Hash for Comparing Password Hashes

Link to Argon2Hash Source Code

from quantcrypt.kdf import Argon2

strong_password = "A8c7hBBTnVC90kP5AIe2"

# Generate the hash of the users password to be stored into a database
a1 = Argon2.Hash(strong_password)

# Verify the login password with the password hash from the database
a2 = Argon2.Hash(strong_password, a1.public_hash)
assert a2.verified is True

# Argon2 asserts user password strength with the zxcvbn library.
# The following line raises quantcrypt.errors.KDFWeakPasswordError:
Argon2.Hash("my_weak_password")

# You can disable the password minimum strength requirement:
Argon2.Hash("my_weak_password", min_years=0)
Argon2.Hash(b"my_weak_password")  # bytes

Back to Top

Argon2Key for High-Cost Key Derivation

Link to Argon2Key Source Code

import secrets
from quantcrypt.kdf import Argon2
from quantcrypt.cipher import Krypton

secret_key = secrets.token_bytes(32)

# Expand a 32 byte secret key into a 64 byte secret key:
argon = Argon2.Key(secret_key)

# Use the 64 byte secret key to key the Krypton cipher:
krypton = Krypton(argon.secret_key)

Back to Top

KKDF for Fast Key Derivation

Link to KKDF Source Code

import secrets
from quantcrypt.kdf import KKDF

# Obtain a master secret key
secret_key = secrets.token_bytes(64)

# Derive the keys
keys = KKDF(
    master=secret_key, 
    key_len=64, 
    num_keys=1
)

# Sanity check
assert isinstance(keys, tuple)
assert isinstance(keys[0], bytes)
assert len(keys[0]) == 64

Back to Top

Clone this wiki locally