Programa para realizar un ataque de frecuencia de letras en un cifrado de sustitución monoalfabético

Dada una string S de tamaño N que representa un cifrado monoalfabético , la tarea es imprimir los cinco textos sin formato posibles que se pueden descifrar del cifrado monoalfabético dado mediante un ataque de frecuencia de letras .

Ejemplos:

Entrada: S = “ETAOINSHRDLCUMWFGYPBVKJXQZ”
Salida: A MENSAJE SIMPLE
              B TJNQMF NFTTBHF
             A MENSAJE SIMPLE
             C UKORNG OGUUCIG
             C UKORNG OGUUCIG

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

Enfoque: El problema se puede resolver con base en las siguientes observaciones:

  1. El análisis de frecuencia es uno de los ataques de texto cifrado conocidos. Se basa en el estudio de la frecuencia de letras o grupos de letras en un texto cifrado. En todos los idiomas, se usan diferentes letras con diferentes frecuencias.
  2. El ataque de array de frecuencia se basa en la observación de que en un texto en inglés, no todas las letras ocurren con la misma frecuencia .
  3. En el problema dado, la string, T = «ETAOINSHRDLCUMWFGYPBVKJXQZ» se usa para descifrar.
  4. Por lo tanto, la idea es encontrar la diferencia entre la i -ésima letra máxima que aparece en la string dada y la string T y luego cambiar todas las letras de la string dada con esa diferencia. La string obtenida será una de las posibles strings descifradas.
     

Siga los pasos a continuación para resolver el problema:

  • Inicialice una string, diga T como «ETAOINSHRDLCUMWFGYPBVKJXQZ».
  • Encuentre la frecuencia de cada carácter de la string S y guárdela en una variable, digamos freq[].
  • Iterar sobre el rango [0, 5] usando la variable i y realizar los siguientes pasos:
    • Encuentre el i -ésimo elemento que aparece más en la string S y guárdelo en una variable, digamos ch .
    • Encuentre la diferencia entre el ch y el i -ésimo  carácter de la string T y guárdelo en una variable, digamos x .
    • Itere sobre los caracteres de la string S, y cambie todos los caracteres por x y luego inserte la string obtenida en una array de texto plano [].
  • Finalmente, luego de los pasos anteriores, imprima las strings obtenidas en el arreglo plaintext[].

A continuación se muestra la implementación del enfoque anterior:

C++

// C++ program for the above approach
#include <bits/stdc++.h>
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[5];
 
    // Store the frequency of each letter in
    // cipher text
    int freq[26] = { 0 };
 
    // Stores the frequency of each letter
    // in cipher text in descending order
    int freqSorted[26];
 
    // Store which alphabet is used already
    int Used[26] = { 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[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[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
Producción

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

Complejidad temporal: O(N)
Espacio auxiliar: O(N)

Publicación traducida automáticamente

Artículo escrito por arjunsaini9081 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *