# How Symmetric and Asymmetric Encryption Algorithms Work in TheAlgorithms/Python

> Explore how TheAlgorithms/Python implements symmetric and asymmetric encryption. Learn about single shared key and public private key systems for secure data.

- Repository: [The Algorithms/Python](https://github.com/TheAlgorithms/Python)
- Tags: deep-dive
- Published: 2026-02-24

---

**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`](https://github.com/TheAlgorithms/Python/blob/main/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)

```python
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`](https://github.com/TheAlgorithms/Python/blob/main/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

```python
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`](https://github.com/TheAlgorithms/Python/blob/main/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`, and `ciphertext XOR key = plaintext`
- **Implementation**: Single `encrypt()` function handles both directions

```python
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`](https://github.com/TheAlgorithms/Python/blob/main/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

```python
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`](https://github.com/TheAlgorithms/Python/blob/main/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

```python
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`](https://github.com/TheAlgorithms/Python/blob/main/rsa_key_generator.py) for key creation and [`rsa_cipher.py`](https://github.com/TheAlgorithms/Python/blob/main/rsa_cipher.py) for encryption operations.

### Key Generation (rsa_key_generator.py)

The `generate_key()` function in [`ciphers/rsa_key_generator.py`](https://github.com/TheAlgorithms/Python/blob/main/ciphers/rsa_key_generator.py) creates mathematically linked public and private key pairs using large prime numbers.

**Key generation process:**

1. **Prime generation**: Uses the Miller-Rabin probabilistic test (`rabin_miller.generate_large_prime`) to generate two distinct large primes *p* and *q*
2. **Modulus calculation**: Computes `n = p * q` (the RSA modulus)
3. **Totient calculation**: Calculates φ(n) = (p-1) × (q-1)
4. **Public exponent selection**: Chooses random `e` such that `gcd(e, φ(n)) == 1`
5. **Private exponent calculation**: Computes modular inverse `d = find_mod_inverse(e, φ(n))`
6. **File storage**: Writes keys to `<name>_pubkey.txt` and `<name>_privkey.txt` in CSV format (`key_size,n,eor_d`)

```python
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`](https://github.com/TheAlgorithms/Python/blob/main/ciphers/rsa_cipher.py) module handles the actual cryptographic operations using modular exponentiation.

**Block handling mechanism:**

- Text is broken into blocks of `block_size` bytes (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 blocks
- `decrypt_message(blocks: List[int], message_length: int, key: Tuple[int, int]) → str`: Decrypts blocks back to original string
- `encrypt_and_write_to_file(...)`: Convenience function for file-based encryption
- `read_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:

```python
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/Python` use 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.py`](https://github.com/TheAlgorithms/Python/blob/main/rsa_key_generator.py) and [`rsa_cipher.py`](https://github.com/TheAlgorithms/Python/blob/main/rsa_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`](https://github.com/TheAlgorithms/Python/blob/main/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`](https://github.com/TheAlgorithms/Python/blob/main/ciphers/caesar_cipher.py), [`ciphers/vigenere_cipher.py`](https://github.com/TheAlgorithms/Python/blob/main/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`](https://github.com/TheAlgorithms/Python/blob/main/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`](https://github.com/TheAlgorithms/Python/blob/main/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.