 Open in App
Not now

# Program to perform a letter frequency attack on a monoalphabetic substitution cipher

• Difficulty Level : Medium
• Last Updated : 30 Jan, 2023

Given a string S of size N representing a monoalphabetic cipher, the task is to print the top five possible plain texts that can be decrypted from the given monoalphabetic cipher using a letter frequency attack.

Examples:

Input: S = “ETAOINSHRDLCUMWFGYPBVKJXQZ”
Output: A SIMPLE MESSAGE
B TJNQMF NFTTBHF
A SIMPLE MESSAGE
C UKORNG OGUUCIG
C UKORNG OGUUCIG

Input: S = “ABCDEFGH”
Output: W OEILHA IAOOWCA
J BRVYUN VNBBJPN
C UKORNG OGUUCIG
R JZDGCV DVJJRXV
Y QGKNJC KCQQYEC

Approach: The problem can be solved based on the following observations:

1. Frequency analysis is one of the known ciphertext attacks. It is based on the study of the frequency of letters or groups of letters in a ciphertext. In all languages, different letters are used with different frequencies.
2. The frequency array attack is based on the observation that in an English text, not all letters occur with the same frequency.
3. In the given problem, the string, T = “ETAOINSHRDLCUMWFGYPBVKJXQZ” is used for deciphering.
4. Therefore, the idea is to find the difference between ith maximum occurring letter in the given string and the string T and then shift all the letters of the given string with that difference. The string obtained will be one of the possible decrypted strings.

Follow the steps below to solve the problem:

• Initialize a string say T as “ETAOINSHRDLCUMWFGYPBVKJXQZ”.
• Find the frequency of each character of the string S, and store it in a variable, say freq[].
• Iterate over the range [0, 5] using the variable i and perform the following steps:
• Find the ith most occurring element in the string S and store it in a variable, say ch.
• Find the difference between the ch and ith character of the string T and store it in a variable, say x.
• Iterate over the characters of string S, and shift all characters by x and then push the obtained string into an array plaintext[].
• Finally, after the above steps, print the strings obtained in the array plaintext[].

Below is the implementation of the above approach:

## C++

 `// C++ program for the above approach``#include ``using` `namespace` `std;` `// Function to decrypt a monoalphabetic``// substitution cipher using the letter``// frequency attack``void` `printString(string S, ``int` `N)``{` `    ``// Stores final 5 possible deciphered``    ``// plaintext``    ``string plaintext;` `    ``// Store the frequency of each letter in``    ``// cipher text``    ``int` `freq = { 0 };` `    ``// Stores the frequency of each letter``    ``// in cipher text in descending order``    ``int` `freqSorted;` `    ``// Store which alphabet is used already``    ``int` `Used = { 0 };` `    ``// Traverse the string S``    ``for` `(``int` `i = 0; i < N; i++) {``        ``if` `(S[i] != ``' '``) {``            ``freq[S[i] - ``'A'``]++;``        ``}``    ``}` `    ``// Copy the frequency array``    ``for` `(``int` `i = 0; i < 26; i++) {``        ``freqSorted[i] = freq[i];``    ``}` `    ``// Stores the string formed from concatenating``    ``// the english letters in the decreasing frequency``    ``// in the english language``    ``string T = ``"ETAOINSHRDLCUMWFGYPBVKJXQZ"``;` `    ``// Sort the array in descending order``    ``sort(freqSorted, freqSorted + 26, greater<``int``>());` `    ``// Iterate over the range [0, 5]``    ``for` `(``int` `i = 0; i < 5; i++) {` `        ``int` `ch = -1;` `        ``// Iterate over the range [0, 26]``        ``for` `(``int` `j = 0; j < 26; j++) {` `            ``if` `(freqSorted[i] == freq[j] && Used[j] == 0) {``                ``Used[j] = 1;``                ``ch = j;``                ``break``;``            ``}``        ``}``        ``if` `(ch == -1)``            ``break``;` `        ``// Store the numerical equivalent of letter at``        ``// ith index of array letter_frequency``        ``int` `x = T[i] - ``'A'``;` `        ``// Calculate the probable shift used``        ``// in monoalphabetic cipher``        ``x = x - ch;` `        ``// Temporary string to generate one``        ``// plaintext at a time``        ``string curr = ``""``;` `        ``// Generate the probable ith plaintext``        ``// string using the shift calculated above``        ``for` `(``int` `k = 0; k < N; k++) {` `            ``// Insert whitespaces as it is``            ``if` `(S[k] == ``' '``) {``                ``curr += ``' '``;``                ``continue``;``            ``}` `            ``// Shift the kth letter of the``            ``// cipher by x``            ``int` `y = S[k] - ``'A'``;``            ``y += x;` `            ``if` `(y < 0)``                ``y += 26;``            ``if` `(y > 25)``                ``y -= 26;` `            ``// Add the kth calculated/shifted``            ``// letter to temporary string``            ``curr += ``'A'` `+ y;``        ``}` `        ``plaintext[i] = curr;``    ``}` `    ``// Print the generated 5 possible plaintexts``    ``for` `(``int` `i = 0; i < 5; i++) {``        ``cout << plaintext[i] << endl;``    ``}``}` `// Driver Code``int` `main()``{``    ``// Given string``    ``string S = ``"B TJNQMF NFTTBHF"``;``    ``int` `N = S.length();` `    ``// Function Call``    ``printString(S, N);` `    ``return` `0;``}`

## Java

 `// Java program for the above approach``import` `java.util.*;` `class` `GFG{` `// Function to decrypt a monoalphabetic``// substitution cipher using the letter``// frequency attack``static` `void` `printString(String S, ``int` `N)``{` `    ``// Stores final 5 possible deciphered``    ``// plaintext``    ``String []plaintext = ``new` `String[``5``];` `    ``// Store the frequency of each letter in``    ``// cipher text``    ``int` `freq[] = ``new` `int``[``26``];` `    ``// Stores the frequency of each letter``    ``// in cipher text in descending order``    ``int` `freqSorted[] = ``new` `int``[``26``];` `    ``// Store which alphabet is used already``    ``int` `Used[] = ``new` `int``[``26``];` `    ``// Traverse the String S``    ``for` `(``int` `i = ``0``; i < N; i++) {``        ``if` `(S.charAt(i) != ``' '``) {``            ``freq[S.charAt(i) - ``'A'``]++;``        ``}``    ``}` `    ``// Copy the frequency array``    ``for` `(``int` `i = ``0``; i < ``26``; i++) {``        ``freqSorted[i] = freq[i];``    ``}` `    ``// Stores the String formed from concatenating``    ``// the english letters in the decreasing frequency``    ``// in the english language``    ``String T = ``"ETAOINSHRDLCUMWFGYPBVKJXQZ"``;` `    ``// Sort the array in descending order``    ``Arrays.sort(freqSorted);``    ``freqSorted= reverse(freqSorted);``    ``// Iterate over the range [0, 5]``    ``for` `(``int` `i = ``0``; i < ``5``; i++) {` `        ``int` `ch = -``1``;` `        ``// Iterate over the range [0, 26]``        ``for` `(``int` `j = ``0``; j < ``26``; j++) {` `            ``if` `(freqSorted[i] == freq[j] && Used[j] == ``0``) {``                ``Used[j] = ``1``;``                ``ch = j;``                ``break``;``            ``}``        ``}``        ``if` `(ch == -``1``)``            ``break``;` `        ``// Store the numerical equivalent of letter at``        ``// ith index of array letter_frequency``        ``int` `x = T.charAt(i) - ``'A'``;``        ` `        ``// Calculate the probable shift used``        ``// in monoalphabetic cipher``        ``x = x - ch;` `        ``// Temporary String to generate one``        ``// plaintext at a time``        ``String curr = ``""``;` `        ``// Generate the probable ith plaintext``        ``// String using the shift calculated above``        ``for` `(``int` `k = ``0``; k < N; k++) {` `            ``// Insert whitespaces as it is``            ``if` `(S.charAt(k) == ``' '``) {``                ``curr += (``char``)``' '``;``                ``continue``;``            ``}` `            ``// Shift the kth letter of the``            ``// cipher by x``            ``int` `y = S.charAt(k) - ``'A'``;``            ``y += x;` `            ``if` `(y < ``0``)``                ``y += ``26``;``            ``if` `(y > ``25``)``                ``y -= ``26``;` `            ``// Add the kth calculated/shifted``            ``// letter to temporary String``            ``curr += (``char``)(``'A'` `+ y);``        ``}` `        ``plaintext[i] = curr;``    ``}` `    ``// Print the generated 5 possible plaintexts``    ``for` `(``int` `i = ``0``; i < ``5``; i++) {``        ``System.out.print(plaintext[i] +``"\n"``);``    ``}``}``static` `int``[] reverse(``int` `a[]) {``    ``int` `i, n = a.length, t;``    ``for` `(i = ``0``; i < n / ``2``; i++) {``        ``t = a[i];``        ``a[i] = a[n - i - ``1``];``        ``a[n - i - ``1``] = t;``    ``}``    ``return` `a;``}``// Driver Code``public` `static` `void` `main(String[] args)``{``    ``// Given String``    ``String S = ``"B TJNQMF NFTTBHF"``;``    ``int` `N = S.length();` `    ``// Function Call``    ``printString(S, N);` `}``}` `// This code contributed by Princi Singh`

## Python3

 `# Python3 program for the above approach` `# Function to decrypt a monoalphabetic``# substitution cipher using the letter``# frequency attack``def` `printString(S, N):``    ` `    ``# Stores final 5 possible deciphered``    ``# plaintext``    ``plaintext ``=` `[``None``] ``*` `5``    ` `    ``# Store the frequency of each letter in``    ``# cipher text``    ``freq ``=` `[``0``] ``*` `26``    ` `    ``# Stores the frequency of each letter``    ``# in cipher text in descending order``    ``freqSorted ``=` `[``None``] ``*` `26``    ` `    ``# Store which alphabet is used already``    ``used ``=` `[``0``] ``*` `26``    ` `    ``# Traverse the string S``    ``for` `i ``in` `range``(N):``        ``if` `S[i] !``=` `' '``:``            ``freq[``ord``(S[i]) ``-` `65``] ``+``=` `1``            ` `    ``# Copy the frequency array        ``    ``for` `i ``in` `range``(``26``):``        ``freqSorted[i] ``=` `freq[i]``        ` `    ``# Stores the string formed from``    ``# concatenating the english letters``    ``# in the decreasing frequency in the``    ``# english language    ``    ``T ``=` `"ETAOINSHRDLCUMWFGYPBVKJXQZ"``    ` `    ``# Sort the array in descending order``    ``freqSorted.sort(reverse ``=` `True``)``    ` `    ``# Iterate over the range [0, 5]``    ``for` `i ``in` `range``(``5``):``        ``ch ``=` `-``1``        ` `        ``# Iterate over the range [0, 26]``        ``for` `j ``in` `range``(``26``):``            ``if` `freqSorted[i] ``=``=` `freq[j] ``and` `used[j] ``=``=` `0``:``                ``used[j] ``=` `1``                ``ch ``=` `j``                ``break``            ` `        ``if` `ch ``=``=` `-``1``:``            ``break``        ` `        ``# Store the numerical equivalent of letter``        ``# at ith index of array letter_frequency``        ``x ``=` `ord``(T[i]) ``-` `65``        ` `        ``# Calculate the probable shift used``        ``# in monoalphabetic cipher``        ``x ``=` `x ``-` `ch``        ` `        ``# Temporary string to generate one``        ``# plaintext at a time``        ``curr ``=` `""``        ` `        ``# Generate the probable ith plaintext``        ``# string using the shift calculated above``        ``for` `k ``in` `range``(N):``            ` `            ``# Insert whitespaces as it is``            ``if` `S[k] ``=``=` `' '``:``                ``curr ``+``=` `" "``                ``continue``            ` `            ``# Shift the kth letter of the``            ``# cipher by x``            ``y ``=` `ord``(S[k]) ``-` `65``            ``y ``+``=` `x``            ` `            ``if` `y < ``0``:``                ``y ``+``=` `26``            ``if` `y > ``25``:``                ``y ``-``=` `26``            ` `            ``# Add the kth calculated/shifted``            ``# letter to temporary string    ``            ``curr ``+``=` `chr``(y ``+` `65``)``            ` `        ``plaintext[i] ``=` `curr``    ` `    ``# Print the generated 5 possible plaintexts    ``    ``for` `i ``in` `range``(``5``):``        ``print``(plaintext[i])` `# Driver code` `# Given string``S ``=` `"B TJNQMF NFTTBHF"``N ``=` `len``(S)` `# Function Call``printString(S, N)` `# This code is contributed by Parth Manchanda`

## C#

 `// C# program for the above approach``using` `System;` `public` `class` `GFG{` `// Function to decrypt a monoalphabetic``// substitution cipher using the letter``// frequency attack``static` `void` `printString(String S, ``int` `N)``{` `    ``// Stores readonly 5 possible deciphered``    ``// plaintext``    ``String []plaintext = ``new` `String;` `    ``// Store the frequency of each letter in``    ``// cipher text``    ``int` `[]freq = ``new` `int``;` `    ``// Stores the frequency of each letter``    ``// in cipher text in descending order``    ``int` `[]freqSorted = ``new` `int``;` `    ``// Store which alphabet is used already``    ``int` `[]Used = ``new` `int``;` `    ``// Traverse the String S``    ``for` `(``int` `i = 0; i < N; i++) {``        ``if` `(S[i] != ``' '``) {``            ``freq[S[i] - ``'A'``]++;``        ``}``    ``}` `    ``// Copy the frequency array``    ``for` `(``int` `i = 0; i < 26; i++) {``        ``freqSorted[i] = freq[i];``    ``}` `    ``// Stores the String formed from concatenating``    ``// the english letters in the decreasing frequency``    ``// in the english language``    ``String T = ``"ETAOINSHRDLCUMWFGYPBVKJXQZ"``;` `    ``// Sort the array in descending order``    ``Array.Sort(freqSorted);``    ``freqSorted= reverse(freqSorted);``    ``// Iterate over the range [0, 5]``    ``for` `(``int` `i = 0; i < 5; i++) {` `        ``int` `ch = -1;` `        ``// Iterate over the range [0, 26]``        ``for` `(``int` `j = 0; j < 26; j++) {` `            ``if` `(freqSorted[i] == freq[j] && Used[j] == 0) {``                ``Used[j] = 1;``                ``ch = j;``                ``break``;``            ``}``        ``}``        ``if` `(ch == -1)``            ``break``;` `        ``// Store the numerical equivalent of letter at``        ``// ith index of array letter_frequency``        ``int` `x = T[i] - ``'A'``;``        ` `        ``// Calculate the probable shift used``        ``// in monoalphabetic cipher``        ``x = x - ch;` `        ``// Temporary String to generate one``        ``// plaintext at a time``        ``String curr = ``""``;` `        ``// Generate the probable ith plaintext``        ``// String using the shift calculated above``        ``for` `(``int` `k = 0; k < N; k++) {` `            ``// Insert whitespaces as it is``            ``if` `(S[k] == ``' '``) {``                ``curr += (``char``)``' '``;``                ``continue``;``            ``}` `            ``// Shift the kth letter of the``            ``// cipher by x``            ``int` `y = S[k] - ``'A'``;``            ``y += x;` `            ``if` `(y < 0)``                ``y += 26;``            ``if` `(y > 25)``                ``y -= 26;` `            ``// Add the kth calculated/shifted``            ``// letter to temporary String``            ``curr += (``char``)(``'A'` `+ y);``        ``}` `        ``plaintext[i] = curr;``    ``}` `    ``// Print the generated 5 possible plaintexts``    ``for` `(``int` `i = 0; i < 5; i++) {``        ``Console.Write(plaintext[i] +``"\n"``);``    ``}``}``static` `int``[] reverse(``int` `[]a) {``    ``int` `i, n = a.Length, t;``    ``for` `(i = 0; i < n / 2; i++) {``        ``t = a[i];``        ``a[i] = a[n - i - 1];``        ``a[n - i - 1] = t;``    ``}``    ``return` `a;``}``  ` `// Driver Code``public` `static` `void` `Main(String[] args)``{``    ``// Given String``    ``String S = ``"B TJNQMF NFTTBHF"``;``    ``int` `N = S.Length;` `    ``// Function Call``    ``printString(S, N);` `}``}` `// This code is contributed by shikhasingrajput`

## Javascript

 `function` `printString(S) {``    ``// Stores final 5 possible deciphered plaintext``    ``var` `plaintext = ``new` `Array(5);` `    ``// Store the frequency of each letter in cipher text``    ``var` `freq = ``new` `Array(26).fill(0);` `    ``// Stores the frequency of each letter in cipher text in descending order``    ``var` `freqSorted = ``new` `Array(26);` `    ``// Store which alphabet is used already``    ``var` `used = ``new` `Array(26).fill(0);` `    ``// Traverse the string S``    ``for` `(``var` `i = 0; i < S.length; i++) {``        ``if` `(S[i] !== ``' '``) {``            ``freq[S.charCodeAt(i) - 65] += 1;``        ``}``    ``}` `    ``// Copy the frequency array``    ``for` `(``var` `i = 0; i < 26; i++) {``        ``freqSorted[i] = freq[i];``    ``}` `    ``// Stores the string formed from concatenating the english letters in the decreasing frequency in the english language``    ``var` `T = ``"ETAOINSHRDLCUMWFGYPBVKJXQZ"``;` `    ``// Sort the array in descending order``    ``freqSorted.sort(``function``(a, b) { ``return` `b - a });` `    ``// Iterate over the range [0, 5]``    ``for` `(``var` `i = 0; i < 5; i++) {``        ``var` `ch = -1;` `        ``// Iterate over the range [0, 26]``        ``for` `(``var` `j = 0; j < 26; j++) {``            ``if` `(freqSorted[i] === freq[j] && used[j] === 0) {``                ``used[j] = 1;``                ``ch = j;``                ``break``;``            ``}``        ``}` `        ``if` `(ch === -1) {``            ``break``;``        ``}` `        ``// Store the numerical equivalent of letter``        ``// at ith index of array letter_frequency``        ``var` `x = T.charCodeAt(i) - 65;` `        ``// Calculate the probable shift used in monoalphabetic cipher``        ``x = x - ch;` `        ``// Temporary string to generate one plaintext at a time``        ``var` `curr = ``""``;` `        ``// Generate the probable ith plaintext string using the shift calculated above``        ``for` `(``var` `k = 0; k < S.length; k++) {` `            ``// Insert whitespaces as it is``            ``if` `(S[k] === ``' '``) {``                ``curr += ``" "``;``                ``continue``;``            ``}` `            ``// Shift the kth letter of the cipher by x``            ``var` `y = S.charCodeAt(k) - 65;``            ``y += x;` `            ``if` `(y < 0) {``                ``y += 26;``            ``}``            ``if` `(y > 25) {``                ``y -= 26;``            ``}` `            ``// Add the kth calculated/shifted letter to temporary string``            ``curr += String.fromCharCode(y + 65);``        ``}``        ``plaintext[i] = curr;``    ``}` `    ``console.log(plaintext);``}` `// This Code is Contributed By Shivam Tiwari`

Output

```A SIMPLE MESSAGE
B TJNQMF NFTTBHF
A SIMPLE MESSAGE
C UKORNG OGUUCIG
C UKORNG OGUUCIG```

Time Complexity: O(N)
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up