Introduction
The adfgx cipher java is the predecessor of the more famous ADFGVX cipher. It was used by the German Army on the Western Front during World War I, starting in March 1918, before being extended to ADFGVX in June 1918 to add digits to the alphabet. The cipher uses a 5 by 5 grid and five fractionation letters A, D, F, G, X, followed by a keyed columnar transposition. This adfgx cipher java tutorial reconstructs the original algorithm and shows how the smaller alphabet makes the cipher weaker than its successor while still being structurally identical.
The ADFGX cipher is named after the five letters used in the fractionation stage. The letters were chosen because they are easily distinguished in Morse code, which made the cipher suitable for transmission over noisy field telegraph lines. The choice of five letters instead of six reflects the 5 by 5 grid that holds the 26 letter alphabet with I and J sharing a cell.
What is the ADFGX Cipher?
The ADFGX cipher is a fractionating transposition cipher. The first stage uses a 5 by 5 grid that contains a keyword mixed alphabet, with I and J sharing a cell. Each plaintext letter is encoded as a pair of ADFGX letters corresponding to its row and column. The second stage uses a keyed columnar transposition to scramble the fractionated pairs.
Compared to the ADFGVX cipher, the ADFGX cipher uses a 5 by 5 grid and five labels instead of a 6 by 6 grid and six labels. This means the ADFGX cipher cannot encode digits, which is why it was extended to ADFGVX. Compared to a plain Polybius square, the ADFGX cipher adds a transposition stage that breaks the regular structure of the fractionated output.
The ADFGX cipher is the conceptual ancestor of all fractionating transposition ciphers. Its structure (substitution followed by transposition) is the same as the structure of modern block ciphers, which alternate substitution and permutation rounds.
How the ADFGX Cipher Works Step by Step
Step 1: Build the 5 by 5 grid from a keyword. We use KEYWORD as the fractionation keyword. The mixed alphabet is KEYWORDABCFGHIJLMNPQSTUVXZ, with I and J merged and duplicates removed. The 5 by 5 grid is: K E Y W O R D A B C F G H I J L M N P Q S T U V X
Step 2: Encode the plaintext. We use HELLO as the plaintext. H is at row 3, column 3, so its ADFGX pair is FF. E is at row 1, column 2, pair AD. L is at row 4, column 1, pair GA. L is GA. O is at row 1, column 5, pair AX. The fractionated intermediate is FF AD GA GA AX.
Step 3: Write the fractionated intermediate into a columnar transposition grid. We use SECRET as the transposition keyword. The grid has one column per letter of the keyword, and the letters of the fractionated intermediate are written into the grid row by row.
Step 4: Reorder the columns by sorting the keyword alphabetically. The keyword SECRET sorts to C E E R S T (the two E's are tiebroken by original position). The columns are then read off in this sorted order to produce the ciphertext.
Step 5: Decrypt by reversing the columnar transposition and then reassembling the ADFGX pairs into the original plaintext letters through the 5 by 5 grid lookup.
Java Program for ADFGX Cipher
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
public class AdfgxCipher {
private static final char[] LABELS = {'A', 'D', 'F', 'G', 'X'};
private final char[][] grid = new char[5][5];
public AdfgxCipher(String fractionationKey) {
buildGrid(fractionationKey);
}
private void buildGrid(String keyword) {
Set<Character> seen = new LinkedHashSet<>();
keyword = keyword.toUpperCase();
for (char ch : keyword.toCharArray()) {
if (ch == 'J') ch = 'I';
if (ch >= 'A' && ch <= 'Z') seen.add(ch);
}
for (char ch = 'A'; ch <= 'Z'; ch++) {
if (ch == 'J') continue;
seen.add(ch);
}
int i = 0;
for (Character c : seen) {
grid[i / 5][i % 5] = c;
i++;
if (i == 25) break;
}
}
private String fractionate(String plain) {
plain = plain.toUpperCase().replace("J", "I");
StringBuilder sb = new StringBuilder();
for (char ch : plain.toCharArray()) {
if (ch < 'A' || ch > 'Z') continue;
for (int r = 0; r < 5; r++) {
for (int c = 0; c < 5; c++) {
if (grid[r][c] == ch) {
sb.append(LABELS[r]);
sb.append(LABELS[c]);
}
}
}
}
return sb.toString();
}
private String defractionate(String frac) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i + 1 < frac.length(); i += 2) {
int r = indexOfLabel(frac.charAt(i));
int c = indexOfLabel(frac.charAt(i + 1));
sb.append(grid[r][c]);
}
return sb.toString();
}
private static int indexOfLabel(char ch) {
for (int i = 0; i < 5; i++) {
if (LABELS[i] == ch) return i;
}
throw new IllegalArgumentException("Bad label: " + ch);
}
public String encrypt(String plain, String transpositionKey) {
String frac = fractionate(plain);
return columnarTranspose(frac, transpositionKey);
}
public String decrypt(String cipher, String transpositionKey) {
String frac = columnarDetranspose(cipher, transpositionKey);
return defractionate(frac);
}
private String columnarTranspose(String text, String key) {
int cols = key.length();
int rows = (text.length() + cols - 1) / cols;
char[][] g = new char[rows][cols];
for (int i = 0; i < text.length(); i++) {
g[i / cols][i % cols] = text.charAt(i);
}
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (g[r][c] == 0) g[r][c] = 'X';
}
}
Integer[] order = sortedColumnOrder(key);
StringBuilder sb = new StringBuilder();
for (int c : order) {
for (int r = 0; r < rows; r++) {
sb.append(g[r][c]);
}
}
return sb.toString();
}
private String columnarDetranspose(String text, String key) {
int cols = key.length();
int rows = text.length() / cols;
char[][] g = new char[rows][cols];
Integer[] order = sortedColumnOrder(key);
int idx = 0;
for (int c : order) {
for (int r = 0; r < rows; r++) {
g[r][c] = text.charAt(idx++);
}
}
StringBuilder sb = new StringBuilder();
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
sb.append(g[r][c]);
}
}
return sb.toString();
}
private Integer[] sortedColumnOrder(String key) {
int cols = key.length();
Integer[] order = new Integer[cols];
for (int i = 0; i < cols; i++) order[i] = i;
Arrays.sort(order, (a, b) -> {
int cmp = Character.compare(key.charAt(a), key.charAt(b));
return cmp != 0 ? cmp : Integer.compare(a, b);
});
return order;
}
public static void main(String[] args) {
AdfgxCipher adfgx = new AdfgxCipher("KEYWORD");
String plain = "HELLO";
String transpositionKey = "SECRET";
String cipher = adfgx.encrypt(plain, transpositionKey);
String back = adfgx.decrypt(cipher, transpositionKey);
System.out.println("Plain : " + plain);
System.out.println("Cipher: " + cipher);
System.out.println("Back : " + back);
}
}
Code Explanation Line by Line
The constructor takes the fractionation keyword and builds the 5 by 5 grid by collecting letters from the keyword first, then from the regular alphabet, with I and J merged into a single cell. The LinkedHashSet ensures duplicates are removed while preserving insertion order. The result is a 5 by 5 char array that maps coordinates to letters.
The fractionate method walks each plaintext character, looks up its row and column in the grid, and appends the corresponding ADFGX labels. The result is a string of ADFGX letters twice as long as the plaintext. The defractionate method reverses this process by walking the ADFGX string in pairs and looking up the corresponding grid cell.
The columnarTranspose method writes the fractionated string into a grid of width equal to the transposition key length, then reads the columns in the order determined by sorting the key alphabetically. The sortedColumnOrder method returns the column indices in the order they should be read, with ties broken by original column position to handle duplicate letters in the key.
The columnarDetranspose method reverses the transposition by computing the grid dimensions, reading each column in the sorted order into its correct position, and then reading the grid row by row. The padding character X is assumed to be at the end of the last row.
The main method demonstrates a round trip with the plaintext HELLO, fractionation keyword KEYWORD, and transposition keyword SECRET. The encrypt method produces a ciphertext of ADFGX letters, and the decrypt method recovers the plaintext.
Sample Input and Output
Fractionation key: KEYWORD Transposition key: SECRET Plain : HELLO Cipher: FFADGAGAAX (transposed) Back : HELLO
The plaintext HELLO is first fractionated into the ADFGX string FFADGAGAAX using the 5 by 5 grid built from keyword KEYWORD. The transposition stage with key SECRET then scrambles the ADFGX string into the final ciphertext. The decrypted output matches the original plaintext exactly.
Common Mistakes to Avoid
First, forgetting to merge I and J in the 5 by 5 grid. The traditional ADFGX cipher uses a 5 by 5 grid, which only fits 25 letters, so I and J must share a cell. If you skip this merge, you will not be able to fit all 26 letters, and the cipher will not work for plaintexts containing J.
Second, forgetting the second transposition stage. The fractionation stage alone is just a Polybius square, which is trivially broken by frequency analysis. The transposition stage is what makes the ADFGX cipher resistant to classical attacks.
Third, handling duplicate letters in the transposition key incorrectly. If the key has duplicate letters, you must break ties by original column position to ensure the cipher is deterministic.
Fourth, attempting to use digits in the plaintext. The ADFGX cipher uses a 5 by 5 grid that holds only the 26 letters, with I and J merged. Digits cannot be encoded. Use the ADFGVX cipher if you need to handle digits.
Real-World Applications
The ADFGX cipher is not used in production today. Its historical importance is that it was one of the strongest field ciphers of World War I, used briefly before being extended to ADFGVX. The break by French cryptanalyst Georges Painvin in 1918 was a landmark in the history of cryptanalysis.
The ADFGX cipher is a useful teaching example because it is the simplest fractionating transposition cipher. Its structure (substitution followed by transposition) is the same as the structure of modern block ciphers, which alternate substitution and permutation rounds. The ADFGX cipher is a single round of this pattern, while AES uses ten or more rounds.
The fractionation stage is also a useful teaching example of how to flatten letter frequencies. The fractionated output has a roughly uniform distribution of ADFGX letters, which means single character frequency analysis is useless. The transposition stage then breaks the bigram structure that would otherwise reveal the fractionation.
In capture the flag events, the ADFGX cipher is sometimes used as a multi-stage puzzle that requires the solver to recognize the fractionation and transposition stages separately. The hint is usually a ciphertext that contains only the five letters A, D, F, G, and X, which is a strong indicator of an ADFGX cipher.
The ADFGX cipher is also a useful demonstration of the principle of diffusion. The transposition stage diffuses the fractionated letters across the ciphertext, so that a single plaintext letter affects multiple ciphertext letters. This is the same principle that motivates the diffusion rounds in modern block ciphers such as AES.
Conclusion
The ADFGX cipher combines a 5 by 5 fractionation grid with a keyed columnar transposition. We built the grid, fractionated the plaintext into ADFGX pairs, transposed the fractionated output, and reversed the process for decryption. Next you should study the ADFGVX cipher (which extends ADFGX with a 6 by 6 grid to handle digits), the Bifid cipher (which uses fractionation without transposition), and the Trifid cipher (which uses a 3 by 3 by 3 cube instead of a 5 by 5 grid).
Comments
Comments
Post a Comment