The transposition cipher rearranges the letters of a message using a columnar transposition matrix. Unlike substitution ciphers, it doesn’t change the letters themselves—it only changes their positions.
How it works
The transposition cipher uses a matrix-based approach :
Remove spaces from the message
Arrange the message into a matrix with a fixed number of columns (the key)
Add padding characters (*) if needed to fill the last row
Read the matrix column-by-column to create the ciphertext
This cipher preserves all letter frequencies, making it resistant to frequency analysis but vulnerable to anagramming attacks.
Algorithm explanation
Visual example
For message “HOLA MUNDO” with key = 5:
Original: HOLAMUNDO
Step 1: Arrange in matrix (5 columns)
┌─┬─┬─┬─┬─┐
│H│O│L│A│M│
├─┼─┼─┼─┼─┤
│U│N│D│O│*│ ← Padding added
└─┴─┴─┴─┴─┘
Step 2: Read column by column
Column 1: H, U → HU
Column 2: O, N → ON
Column 3: L, D → LD
Column 4: A, O → AO
Column 5: M, * → M*
Ciphertext: HUONLDAOM*
Decryption process
Ciphertext: HUONLDAOM*
Key: 5 columns, 2 rows
Read sequentially into matrix by columns:
┌─┬─┬─┬─┬─┐
│H│O│L│A│M│
├─┼─┼─┼─┼─┤
│U│N│D│O│*│
└─┴─┴─┴─┴─┘
Read row by row: HOLAMUNDO* → Remove padding → HOLAMUNDO
Implementation details
The implementation is in transposicion.py with two main functions:
def cifrar ( mensaje , clave ):
mensaje = mensaje.replace( " " , "" )
filas = len (mensaje) // clave
if len (mensaje) % clave != 0 :
filas += 1
mensaje += "*" * (clave - ( len (mensaje) % clave)) # Add padding
cifrado = ""
for j in range (clave):
for i in range (filas):
cifrado += mensaje[i * clave + j]
return cifrado
Usage example
Basic encryption and decryption
from transposicion import cifrar, descifrar
# Original message
mensaje = "HOLA MUNDO"
# Key (number of columns)
clave = 5
# Encryption
mensaje_cifrado = cifrar(mensaje, clave)
print ( f "Original: { mensaje } " )
print ( f "Encrypted: { mensaje_cifrado } " ) # "HUONLDAOM*"
# Decryption
mensaje_descifrado = descifrar(mensaje_cifrado, clave)
print ( f "Decrypted: { mensaje_descifrado } " ) # "HOLAMUNDO"
Step-by-step example
Remove spaces
mensaje = "HOLA MUNDO"
mensaje = mensaje.replace( " " , "" ) # "HOLAMUNDO"
Calculate matrix dimensions
clave = 5 # columns
filas = len (mensaje) // clave # 9 // 5 = 1
if len (mensaje) % clave != 0 : # 9 % 5 = 4 (remainder)
filas += 1 # filas = 2
Add padding if needed
padding_needed = clave - ( len (mensaje) % clave) # 5 - 4 = 1
mensaje += "*" * padding_needed # "HOLAMUNDO*"
Read column by column
# Column 0: positions 0, 5 → "HU"
# Column 1: positions 1, 6 → "ON"
# Column 2: positions 2, 7 → "LD"
# Column 3: positions 3, 8 → "AO"
# Column 4: positions 4, 9 → "M*"
cifrado = "HUONLDAOM*"
Parameters
The plaintext message to encrypt. Spaces are automatically removed. All characters are preserved.
The number of columns in the transposition matrix. Must be a positive integer. Larger values create wider, shorter matrices.
Key characteristics
Letter frequency Preserved - Same letters appear in ciphertext
Message length May increase due to padding with *
Character support Supports any characters (not limited to alphabet)
Encryption speed O(n) linear time complexity
Padding behavior
The cipher adds asterisk (*) characters as padding when the message length is not divisible by the key. These are automatically removed during decryption.
Padding calculation
message_length = 9
key = 5
padding_needed = key - (message_length % key) # 5 - (9 % 5) = 5 - 4 = 1
Example with different keys
mensaje = "HOLA" # Length: 4
clave = 3
# Matrix (3 columns, 2 rows)
# H O L
# A * * ← 2 padding characters
cifrado = cifrar(mensaje, 3 ) # "HAOL**"
mensaje = "HOLA" # Length: 4
clave = 4
# Matrix (4 columns, 1 row)
# H O L A ← No padding needed
cifrado = cifrar(mensaje, 4 ) # "HOLA"
mensaje = "HOLA" # Length: 4
clave = 5
# Matrix (5 columns, 1 row)
# H O L A * ← 1 padding character
cifrado = cifrar(mensaje, 5 ) # "HOLA*"
Security notes
The transposition cipher provides minimal security and should only be used for educational purposes.
Vulnerabilities
Frequency preservation : Letter frequencies remain unchanged, revealing language patterns
Anagramming attacks : The ciphertext is just an anagram of the plaintext
Pattern analysis : Common words and patterns can be identified
Small keyspace : Limited number of practical key values
Known-plaintext attack : If part of the message is known, the key can be deduced
Educational value
The transposition cipher teaches important concepts:
Difference between substitution and transposition
Matrix operations in cryptography
Why encryption needs both confusion and diffusion
Limitations of single-technique ciphers
Advanced example
# Longer message with special characters
mensaje = "ESTO ES UN MENSAJE SECRETO!"
clave = 7
print ( f "Original: { mensaje } " )
print ( f "Length: { len (mensaje) } characters" )
cifrado = cifrar(mensaje, clave)
print ( f "Encrypted: { cifrado } " )
print ( f "Length: { len (cifrado) } characters (with padding)" )
descifrado = descifrar(cifrado, clave)
print ( f "Decrypted: { descifrado } " )
# Output:
# Original: ESTO ES UN MENSAJE SECRETO!
# Length: 28 characters
# Encrypted: EEMTESOSSEUTNJREETCO*!S***
# Length: 28 characters (with padding)
# Decrypted: ESTOESUNENJAJESECRETO!
Notice that spaces are removed during encryption, so the decrypted message won’t have the original spacing.
Matrix visualization
For better understanding, here’s how different key values affect the matrix:
mensaje = "ABCDEFGHIJ" # 10 characters
# Key = 2 (2 columns, 5 rows)
# A B
# C D
# E F
# G H
# I J
# Ciphertext: ACEGIBDFHJ
# Key = 5 (5 columns, 2 rows)
# A B C D E
# F G H I J
# Ciphertext: AFBGCHDIEJ
# Key = 10 (10 columns, 1 row)
# A B C D E F G H I J
# Ciphertext: ABCDEFGHIJ (no change!)
Using a key equal to the message length produces no encryption at all!
Common use cases
Teaching transposition vs substitution
Demonstrating matrix operations
Understanding cipher weaknesses
Cryptanalysis practice
Used in ancient military communications
Rail fence cipher variant
Route cipher techniques
Classical cryptography study
Can be combined with substitution for stronger encryption
Double transposition increases security
Historical use in World War communications
Teaching defense-in-depth principles
import time
# Short message
mensaje_corto = "HOLA" * 10
start = time.time()
cifrado = cifrar(mensaje_corto, 5 )
end = time.time()
print ( f "Short message: { (end - start) * 1000 :.3f} ms" )
# Long message
mensaje_largo = "HOLA" * 10000
start = time.time()
cifrado = cifrar(mensaje_largo, 5 )
end = time.time()
print ( f "Long message: { (end - start) * 1000 :.3f} ms" )
The cipher has O(n) time complexity, making it efficient even for longer messages.
See also