← Back to Blog

ADFGVX Project — Round 2/5

We left Round 1 with a sorted character sequence built on a validated key. Here's where we are:

import string

all_chars = string.ascii_uppercase + string.digits

final_key = ""
while len(final_key) < 6:
    key = input("Please enter key: ")
    clean_key = ""
    for letter in key.upper():
        if letter in all_chars:
            clean_key += letter
    final_key = ""
    for letter in clean_key:
        if letter not in final_key:
            final_key += letter
    if len(final_key) < 6:
        print("Invalid key. Please try again.")

sorted_chars = ""
reference = final_key + all_chars

for letter in reference:
    if letter not in sorted_chars:
        sorted_chars += letter

With key WASHINGTON, sorted_chars is:

WASHINGTOBCDEFJKLMPQRUVWXYZ0123456789

Placed in the 6×6 grid:

   A  D  F  G  V  X
A  W  A  S  H  I  N
D  G  T  O  B  C  D
F  E  F  J  K  L  M
G  P  Q  R  U  V  X
V  Y  Z  0  1  2  3
X  4  5  6  7  8  9

Now we build the substitution dictionary — every character mapped to its ADFGVX pair.

There's a mathematical approach. Each character in sorted_chars has an index from 0 to 35. Dividing by 6 gives the row index. The remainder gives the column index. Both are used to look up the corresponding letter in "ADFGVX".

matrix_letters = "ADFGVX"
matrix_dict = {}

for i in range(0, len(sorted_chars)):
    matrix_dict[sorted_chars[i]] = matrix_letters[i // len(matrix_letters)] + matrix_letters[i % len(matrix_letters)]

It works. But it requires comfort with integer division and modulo — concepts from outside programming. So we use a simpler approach: a pre-generated list of all 36 pairs, in order from AA to XX.

matrix_letters = [
    "AA", "AD", "AF", "AG", "AV", "AX",
    "DA", "DD", "DF", "DG", "DV", "DX",
    "FA", "FD", "FF", "FG", "FV", "FX",
    "GA", "GD", "GF", "GG", "GV", "GX",
    "VA", "VD", "VF", "VG", "VV", "VX",
    "XA", "XD", "XF", "XG", "XV", "XX"
]

matrix_dict = {}
for i in range(0, len(sorted_chars)):
    matrix_dict[sorted_chars[i]] = matrix_letters[i]

Same result. More explicit. Index 0 in sorted_chars maps to matrix_letters[0] — which is "AA". Index 1 maps to "AD". And so on.

A few entries from the resulting matrix_dict with key WASHINGTON:

{
    'W': 'AA',   # index 0  → AA
    'A': 'AD',   # index 1  → AD
    'S': 'AF',   # index 2  → AF
    'H': 'AG',   # index 3  → AG
    'T': 'DA',   # index 6  → DA
    'O': 'DF',   # index 8  → DF
    'E': 'FA',   # index 12 → FA
    '0': 'VA',   # index 24 → VA
    '9': 'XX'    # index 35 → XX
}

Now the message. Minimal validation — not empty, characters cleaned and uppercased. A message can be very short. "Yes" is a valid message. We don't over-validate.

message = ""
while not message:
    message = input("Enter your message: ")

clean_message = ""
for letter in message.strip().upper():
    if letter in all_chars:
        clean_message += letter

Spaces, punctuation, special characters — all stripped. Only what exists in all_chars survives. What remains is ready for substitution.

substituted_message = ""
for letter in clean_message:
    substituted_message += matrix_dict[letter]

One line of logic. Every character in the clean message is replaced by its two-letter ADFGVX pair from the dictionary.

A simulation. Key: WASHINGTON. Message: ATTACK.

clean_message:       ATTACK
A → AD
T → DA
T → DA
A → AD
C → DV
K → FG

substituted_message: ADDADADADVFG

Six characters in. Twelve characters out. Every character doubled — that's always the case with ADFGVX substitution. The message length after substitution is always exactly twice the original.

The substitution is done. Next — transposition. The second layer of the cipher. Round 3.

[ login to bookmark ] // copied! 30 views · 2 min
← prev ADFGVX Project — Round 1/5 next → ADFGVX Project — Round 3/5
// 0 comments
// No comments yet. Be the first.
// leave a comment

// Your comment will appear after approval.