2.4. Symmetric-key Cryptography#
In symmetric-key cryptography the same key is used to both encrypt the plaintext to ciphertext and decrypt the ciphertext to plaintext.
2.4.1. Simple Example#
We previously saw a simple substitution letter where we substituted letters with other letters using a normal alphabet and a mixed alphabet where we created the mixed alphabet using a key. In this example the key is \(\textcolor{red}{IMAGINATION}\).
Plaintext |
A |
B |
C |
D |
E |
F |
G |
H |
I |
J |
K |
L |
M |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Ciphertext |
\(\textcolor{red}{I}\) |
\(\textcolor{red}{M}\) |
\(\textcolor{red}{A}\) |
\(\textcolor{red}{G}\) |
\(\textcolor{red}{N}\) |
\(\textcolor{red}{T}\) |
\(\textcolor{red}{O}\) |
B |
C |
D |
E |
F |
H |
Plaintext |
N |
O |
P |
Q |
R |
S |
T |
U |
V |
W |
X |
Y |
Z |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Ciphertext |
J |
K |
L |
P |
Q |
R |
S |
U |
V |
W |
X |
Y |
Z |
Plaintext:
UNITED WE STAND DIVIDED WE FALL
Ciphertext:
UJCSNG WN RSIJG GCVCGNG WN TIFF
If you know the key you can ‘unlock’ the encryption because you can determine what the mixed alphabet looks like and therefore you know the mapping between the plaintext and the ciphertext.
2.5. In Practice#
Simple ciphers like a substitution cipher are vulnerable to brute force attacks or frequency analysis and can be broken. Modern encryption algorithms incorporate several clever techniques to create encryption that is resistant to these kinds of attacks.
Symmetric-key encryption algorithms achieve a high level of security in two ways:
Confusion, which is decorrelating the input plain text from the output cipher text
Diffusion, which is hidings the plain text by spreading it over a greater number of characters
2.5.1. Blocks#
Modern encryption algorithms work by breaking the plain text into fixed size chunks called blocks. Each block is processed through the algorithm separately.
The “block size” is the length of the data, in bits, that each block contains. Generally block sizes are fixed for an encryption algorithm, or there are variations of the algorithms for common block sizes e.g. 128 bits or 256 bits.
The image below shows a simplified example with a 16 bit block size.
In contrast, simple substitution ciphers like a Caesar cipher can be thought of as using a block size of 1 character, since each character is processed separately.
Larger block sizes improve security by making it much harder to find repeating patterns or “collisions” that could be exploited to reveal the underlying plaintext. In other words, larger block sizes increase the confusion.
2.5.2. Substitution-Permutation Networks#
Modern encryption algorithms rely on repetitions of two operations: substitution and permutation. Both steps are performed by what is called “boxes” i.e. there are “S-Boxes” and “P-Boxes”, which are just complicated functions.
Substitution (S-Boxes)
The substitution step replaces segments of the data with different values using carefully designed substitution rules (functions). This process adds confusion to the encryption process and the more complex the substitution process is, the greater the confusion.
Permutation (P-Boxes)
The permutation step rearranges the bits (or bytes) within a block according to a fixed rule. This rearrangement spreads the influence of each input bit across many output bits. The combined effect is that a small change in the plaintext or key will result in a dramatic change in the ciphertext. In other words permutation process increases diffusion.
2.5.3. Rounds#
In practice, modern encryption algorithms repeat the substitution and permutation steps a fixed number of times. Each repetition is called a round. Repeating the process compounds the confusion and diffusion properties.
2.5.4. Recommended Video#
2.5.5. Disadvantages#
The main disadvantage of symmetric-key cryptography is the both parties need to know what they key is. For example, if Alice wanted to send a secret message to Stevie using a symmetric cipher, both Alice and Stevie need to know what the key is. But say Alice and Stevie are in two different cities, how do they share the secret key? They can’t encrypt anything yet because they need to share a key to encrypt, so they would have to send the key securely somehow in plaintext, which runs the risk that someone else sees the key. The most secure way to share the key would be to meet in person to share the key, but this could be quite impractical, especially if they wanted to periodically change their secret key. We’ll see later that you can get around this using asymmetric cryptography.
Demo: Crypto Module - Symmetric
Implementing encryption and decryption in code can be quite tricky and error prone.
To simplify the process and save you time, we’ve provided you with a module called crypto that implements Symmetric-key encryption. This page serves to explain how to use this module.
Note
A copy of this module has been provided in the files for this page.
Generating Keys
The static method Symmetric.generate_key returns a new randomly generated key as a str.
Example
from crypto import Symmetric
key = Symmetric.generate_key()
print(key)
Encrypting
The static method Symmetric.encrypt(message, key):
accepts two parameters:
messagewhich is thestrto encryptkeywhich is a keystrpreviously generated bySymmetric.generate_key
returns the ciphertext as a
str.
Example
from crypto import Symmetric
message = "SECRET"
key = "1xzcBiDwPPAsUVScnms_3aw8APdFz9C1e_jrxm0rXhM="
ciphertext = Symmetric.encrypt(message, key)
print(ciphertext)
Decrypting
The static method Symmetric.decrypt(encrypted, key):
accepts two parameters:
encryptedwhich is the cipher textkeywhich is a keystrpreviously generated by Symmetric.generate_key
returns the cipher text as a
str.
Example
from crypto import Symmetric
cipher_text = "gAAAAABnxp7a2nQKoa87xg6So-XyEN7DYHU-0g1OS_PWSra2Fkp54eukT1OMYQKoGhkHuAeLrSO1p_6Ktz21gVIF631oyT8Ldg=="
key = "1xzcBiDwPPAsUVScnms_3aw8APdFz9C1e_jrxm0rXhM="
plaintext = Symmetric.decrypt(ciphertext, key)
print(plaintext)
Code Samples
from crypto import Symmetric
# Generate key
key = Symmetric.generate_key()
print("key:", key)
# Encrypting
message = "SECRET"
ciphertext = Symmetric.encrypt(message, key)
print("\nCiphertext:", ciphertext)
# Decrypting
plaintext = Symmetric.decrypt(ciphertext, key)
print("\nPlaintext:", plaintext)
crypto.py
from typing import List
from cryptography.hazmat.primitives.asymmetric import rsa, padding as asym_padding
from cryptography.hazmat.primitives import hashes, serialization
import base64
from cryptography.fernet import Fernet
class Symmetric:
@staticmethod
def generate_key() -> str:
# Returns a Base64-encoded key as an ASCII string
return Fernet.generate_key().decode('ascii')
@staticmethod
def encrypt(message: str, key: str) -> str:
if not isinstance(message, str):
raise TypeError("message must be a string")
if not isinstance(key, str):
raise TypeError("key must be a string")
if len(message) == 0:
raise ValueError("message must not be empty")
try:
message_bytes = message.encode('ascii')
except Exception as e:
raise ValueError("Failed to encode message in ASCII") from e
try:
key_bytes = key.encode('ascii')
except Exception as e:
raise ValueError("Failed to encode key in ASCII") from e
return Fernet(key_bytes).encrypt(message_bytes).decode('ascii')
@staticmethod
def decrypt(encrypted: str, key: str) -> str:
if not isinstance(encrypted, str):
raise TypeError("encrypted must be a string")
if not isinstance(key, str):
raise TypeError("key must be a string")
try:
encrypted_bytes = encrypted.encode("ascii")
except Exception as e:
raise ValueError("Failed to encode encrypted message in ASCII") from e
try:
key_bytes = key.encode('ascii')
except Exception as e:
raise ValueError("Failed to encode key in ASCII") from e
return Fernet(key_bytes).decrypt(encrypted_bytes).decode('ascii')
Code Challenge: Encrypt a Message
You’ve been given a module called crypto which contains a class called Symmetric. Use the Symmetric class to encrypt a message provided by the user.
Your program must:
generate a new symmetric encryption key
encrypt a message that the user inputs with the generated key
print both the key and the message to the terminal
Write your program in exercise.py.
Example
Enter your message: hello
KEY (KEEP THIS SECRET):
R8MpSi4Qc6SrcbKVtylFJbgCwHP-1VTy28dOrTcdNWw=
ENCRYPTED MESSAGE:
gAAAAABnw7v8j55BJ6PJyWRuFATj1YBH0e-QhBpJanDOI4fosH17FBgmMI71UdRphtGzWfx22cBB0J_waGJKXwDU0z9TJNeifA==
Note
Because the encryption process is random, even if you use the same key you will likely get different encrypted messages!
Solution
Solution is locked
Code Challenge: Decrypt a Message
You’ve been given a module called crypto which contains a class called Symmetric. Use the Symmetric class to decrypt a message provided by the user.
Your program must:
read a key and message from the terminal
decrypt the message
print the decrypted message to the terminal
Write your program in exercise.py.
Example
Enter the key:
R8MpSi4Qc6SrcbKVtylFJbgCwHP-1VTy28dOrTcdNWw=
Enter the encrypted message:
gAAAAABnw7v8j55BJ6PJyWRuFATj1YBH0e-QhBpJanDOI4fosH17FBgmMI71UdRphtGzWfx22cBB0J_waGJKXwDU0z9TJNeifA==
Original Message:
hello
Note
You can test your code using the example key and message above or generate them from the previous exercise!
Solution
Solution is locked