How Symmetric and Asymmetric Encryption Algorithms Work in TheAlgorithms/Python
Symmetric algorithms use a single shared key for encryption and decryption, while asymmetric RSA uses mathematically linked public and private keys for secure communication without shared secrets.
TheAlgorithms/Python repository provides educational implementations of both symmetric and asymmetric encryption algorithms, offering clean, self-contained Python code that demonstrates fundamental cryptographic concepts. The ciphers package contains classic symmetric ciphers like Caesar and Vigenère alongside a complete RSA implementation, making it an ideal reference for understanding how encryption functions at the code level.
Symmetric Encryption Algorithms
Symmetric ciphers in the repository use the same secret key for both encryption and decryption operations. These implementations operate directly on strings and bytes, making them lightweight and easy to understand.
Caesar Cipher
The Caesar cipher implementation in ciphers/caesar_cipher.py performs a simple character shift using modular arithmetic.
- Encryption: Shifts each character's ASCII code by a constant offset
- Decryption: Shifts in the reverse direction by the same offset
- Key: Integer shift value (typically 0-255)
from ciphers.caesar_cipher import encrypt, decrypt
ciphertext = encrypt("Hello World!", shift=3) # → "Khoor Zruog!"
plaintext = decrypt(ciphertext, shift=3) # → "Hello World!"
Vigenère Cipher
Located in ciphers/vigenere_cipher.py, this implementation extends the Caesar concept by using a repeating keyword to drive variable shifts.
- Core mechanism: Each character in the keyword determines the shift amount for the corresponding plaintext character
- Key: Text string (ASCII letters) that repeats to match message length
- Security: Stronger than Caesar but still vulnerable to frequency analysis
from ciphers.vigenere_cipher import encrypt, decrypt
key = "SECRET"
encrypted = encrypt("Attack at dawn", key)
decrypted = decrypt(encrypted, key)
XOR Cipher
The ciphers/xor_cipher.py module implements bitwise XOR encryption, where the same operation serves as both encryption and decryption.
- Mechanism: Each byte is XORed with a corresponding byte from the repeating key
- Key property:
plaintext XOR key = ciphertext, andciphertext XOR key = plaintext - Implementation: Single
encrypt()function handles both directions
from ciphers.xor_cipher import encrypt
message = "Hello"
key = "K"
encrypted = encrypt(message, key) # Encrypt
decrypted = encrypt(encrypted, key) # Decrypt (same function)
One-Time Pad (OTP)
Found in ciphers/onepad_cipher.py, this implementation provides theoretically unbreakable encryption when used correctly.
- Requirement: Key must be truly random, as long as the message, and used only once
- Mechanism: Byte-wise XOR between message and key
- Security: Information-theoretically secure, unlike computationally secure algorithms
from ciphers.onepad_cipher import encrypt
import os
message = "Secret message"
key = os.urandom(len(message)) # Truly random key
ciphertext = encrypt(message, key)
Hill Cipher
The ciphers/hill_cipher.py implementation uses linear algebra for encryption, treating blocks of text as vectors and applying matrix transformations.
- Mechanism: Multiplies plaintext vector by key matrix modulo 26
- Key: Square invertible matrix (size 2×2 or 3×3) with determinant coprime to 26
- Decryption: Uses modular inverse of the key matrix
from ciphers.hill_cipher import encrypt, decrypt
import numpy as np
key_matrix = [[3, 3], [2, 5]] # Must be invertible mod 26
encrypted = encrypt("HELP", key_matrix)
Asymmetric RSA Implementation
The RSA implementation in TheAlgorithms/Python provides a complete public-key cryptosystem split across two modules: rsa_key_generator.py for key creation and rsa_cipher.py for encryption operations.
Key Generation (rsa_key_generator.py)
The generate_key() function in ciphers/rsa_key_generator.py creates mathematically linked public and private key pairs using large prime numbers.
Key generation process:
- Prime generation: Uses the Miller-Rabin probabilistic test (
rabin_miller.generate_large_prime) to generate two distinct large primes p and q - Modulus calculation: Computes
n = p * q(the RSA modulus) - Totient calculation: Calculates φ(n) = (p-1) × (q-1)
- Public exponent selection: Chooses random
esuch thatgcd(e, φ(n)) == 1 - Private exponent calculation: Computes modular inverse
d = find_mod_inverse(e, φ(n)) - File storage: Writes keys to
<name>_pubkey.txtand<name>_privkey.txtin CSV format (key_size,n,eor_d)
from ciphers.rsa_key_generator import make_key_files
# Generate 1024-bit RSA keys and save to disk
make_key_files("myrsa", 1024) # Creates myrsa_pubkey.txt & myrsa_privkey.txt
Encryption and Decryption (rsa_cipher.py)
The ciphers/rsa_cipher.py module handles the actual cryptographic operations using modular exponentiation.
Block handling mechanism:
- Text is broken into blocks of
block_sizebytes (default 128) - Each block is interpreted as a base-256 integer (
BYTE_SIZE = 256) - Encryption:
cipher_block = pow(plain_block, e, n) - Decryption:
plain_block = pow(cipher_block, d, n)
Core functions:
encrypt_message(message: str, key: Tuple[int, int]) → List[int]: Encrypts string to list of integer blocksdecrypt_message(blocks: List[int], message_length: int, key: Tuple[int, int]) → str: Decrypts blocks back to original stringencrypt_and_write_to_file(...): Convenience function for file-based encryptionread_from_file_and_decrypt(...): File-based decryption helper
Practical Usage Example
This complete example demonstrates the full RSA lifecycle from key generation to message recovery:
from ciphers.rsa_key_generator import make_key_files
from ciphers.rsa_cipher import encrypt_and_write_to_file, read_from_file_and_decrypt
# 1️⃣ Generate a fresh 1024-bit RSA key pair (only needs to be done once)
make_key_files("myrsa", 1024) # creates myrsa_pubkey.txt & myrsa_privkey.txt
# 2️⃣ Encrypt a message using the public key
plaintext = "Confidential data inside RSA"
encrypt_and_write_to_file(
message_filename="secret.txt",
key_filename="myrsa_pubkey.txt",
message=plaintext,
block_size=128
)
# 3️⃣ Decrypt using the private key
decrypted = read_from_file_and_decrypt("secret.txt", "myrsa_privkey.txt")
print("Recovered text:", decrypted) # → "Confidential data inside RSA"
Summary
- Symmetric ciphers in
TheAlgorithms/Pythonuse a single shared secret key for both encryption and decryption, implementing classic algorithms like Caesar, Vigenère, XOR, One-Time Pad, and Hill cipher in pure Python. - Asymmetric RSA provides a complete public-key cryptosystem across
rsa_key_generator.pyandrsa_cipher.py, generating mathematically linked key pairs using prime numbers and modular arithmetic for secure communication without shared secrets. - All implementations are self-contained, require no external cryptography libraries, and serve as educational references for understanding encryption fundamentals at the source code level.
Frequently Asked Questions
What is the difference between symmetric and asymmetric encryption in the repository?
Symmetric encryption algorithms like Caesar and Vigenère use the same key for both encryption and decryption, making them fast but requiring secure key distribution. Asymmetric RSA uses mathematically linked public and private keys, allowing anyone to encrypt with the public key while only the private key holder can decrypt, solving the key distribution problem at the cost of computational overhead.
How does the RSA key generation process work in TheAlgorithms/Python?
The generate_key() function in ciphers/rsa_key_generator.py uses the Miller-Rabin primality test to generate two large random primes p and q, computes the modulus n = p × q, calculates Euler's totient φ(n) = (p-1)(q-1), selects a public exponent e coprime to φ(n), and computes the private exponent d as the modular multiplicative inverse of e modulo φ(n).
Can the symmetric ciphers in this repository be used for production security?
No, the symmetric implementations in ciphers/caesar_cipher.py, ciphers/vigenere_cipher.py, and similar files are designed for educational purposes to illustrate classical cryptography concepts. While the One-Time Pad (ciphers/onepad_cipher.py) is theoretically unbreakable when used with truly random keys of equal length to the message, the other classical ciphers are vulnerable to modern cryptanalysis and should not be used for securing sensitive data in production environments.
How does block handling work in the RSA implementation?
The RSA cipher in ciphers/rsa_cipher.py processes text in fixed-size blocks (default 128 bytes) to accommodate the mathematical constraints of modular arithmetic. Each block is converted to a large integer by treating the bytes as a base-256 number, then encrypted using modular exponentiation (pow(block, e, n)). During decryption, the process reverses using the private exponent d, and the resulting integers are converted back to bytes, with the original message length preserved to handle padding correctly.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →