C 密码学

问题描述 投票:0回答:1

您拦截了一个进化不良的恐怖分子组织,该组织使用凯撒方法作为密码。消息始终是英文的。他们所做的就是通过移动字母表的 K 个位置来将每个字母替换为另一个字母。因此,例如,如果我们将字母表向前移动两个位置,我们将得到以下对应关系:

**A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

CDEFGHIJKLMNOPQRSTUVWXYZAB **

当然这个方法有一个非常简单的攻击方式:

尝试所有可能的替代方案;

使用公式:(Ei-Oi)^2 / Ei 计算每个可能的替换每个字母 Ei

的预期相对频率与获得的 **Oi ** 之间的下一个度量

您的程序应读取一行最多 10^4 个字符的文本。

您的程序应该打印所需的偏移量和解密的文本。您的程序应该只处理字母(大写或小写)。

编写一个程序来读取一行文本并解密它。使用下表计算每个字母的值 Ei(第三列):

E 11.1607% 56.88 M 3.0129% 15.36

A 8.4966% 43.31 H 3.0034% 15.31

R 7.5809% 38.64 G 2.4705% 12.59

I 7.5448% 38.45 B 2.0720% 10.56

O 7.1635% 36.51 F 1.8121% 9.24

T 6.9509% 35.43 Y 1.7779% 9.06

N 6.6544% 33.92 W 1.2899% 6.57

S 5.7351% 29.23 K 1.1016% 5.61

L 5.4893% 27.98 V 1.0074% 5.13

C 4.5388% 23.13 X 0.2902% 1.48

U 3.6308% 18.51 Z 0.2722% 1.39

D 3.3844% 17.25 J 0.1965% 1.00

P 3.1671% 16.14 Q 0.1962% 1.00

示例: ** 输入1**

GXOXKFHKX

输出1

7 不再有

输入2

Oj wz、jm ijo oj wz、ocvo dn ocz lpznodji:Rczoczm 'odn ijwgzm di ocz hdiy oj npaazm。

输出2

5 存在还是不存在,这就是问题:受苦的心灵是否更高尚。

#include <stdio.h>
#include <string.h>



double tab[26] = {43.31, 10.56, 23.13, 17.25, 56.88, 9.24,

                    12.59, 15.31, 38.45, 1.00, 5.61, 27.98,

                    15.36, 33.92, 36.51, 16.14, 1.00, 38.64,

                    29.23, 35.43, 18.51, 5.13, 6.57, 1.48,

                    9.06, 1.39};


void calcularfrequencias(const char texto[], double frequencias[]) 
{
    int letras = 0;

    for (int i = 0; texto[i] != '\0'; i++) 
    {
        char c = texto[i];
        if (c >= 'A' && c <= 'Z')
         {
            frequencias[c - 'A']++;
            letras++;
        }
         else if (c >= 'a' && c <= 'z') 
        {
            frequencias[c - 'a']++;
            letras++;
        }
    }


    for (int i = 0; i < 26; i++) 
    {
        frequencias[i] /= letras;
    }
}


int encontrardeslocamento(double frequencias[])
 {
    int deslocamento = 0;
    double menor = 1e9;

    for (int i = 0; i < 26; i++)
     {
        double diferenca = 0.0;
        for (int j = 0; j < 26; j++)
         {
            int x = (j + i) % 26;
            diferenca += (frequencias[j] - tab[x]) * (frequencias[j] - tab[x]);
        }
        if (diferenca < menor) 
        {
            menor = diferenca;
            deslocamento = i;
        }
    }

    return deslocamento;
}

void decifrar(char texto[], int deslocamento)
 {
    for (int i = 0; texto[i] != '\0'; i++) 
    {
        char c = texto[i];
        if (c >= 'A' && c <= 'Z') 
        {
            printf("%c", ((c - 'A' + deslocamento) % 26) + 'A');
        }
        else if (c >= 'a' && c <= 'z') 
        {
            printf("%c", ((c - 'a' + deslocamento) % 26) + 'a');
        } 
        else 
        {
            printf("%c", c);
        }
    }
}

int main() 
{
    char texto_cifrado[10000];
     if (fgets(texto_cifrado, sizeof(texto_cifrado), stdin) != NULL) 
     {

    double frequencias[26];
    calcularfrequencias(texto_cifrado, frequencias);

    int deslocamento = encontrardeslocamento(frequencias);

    printf("%d ", deslocamento);
    decifrar(texto_cifrado, deslocamento);
     }
    return 0;
}


我尝试过这个,但是当我尝试它时,它在一个输入中不起作用: Gx‘Fwnwj—fwnwjegjw’。”

输出应该是:8 of ‘Never—nevermore’。”

但在这段代码中,输出是 21 Bs ‘Arire—arirezber’。” 我无法弄清楚。

谢谢您的帮助。

c cryptography
1个回答
0
投票
#include <stdio.h>

#include <string.h>


double tab[26] = {43.31, 10.56, 23.13, 17.25, 56.88, 9.24,
                    12.59, 15.31, 38.45, 1.00, 5.61, 27.98,
                    15.36, 33.92, 36.51, 16.14, 1.00, 38.64,
                    29.23, 35.43, 18.51, 5.13, 6.57, 1.48,
                    9.06, 1.39};


void calcularfrequencias(const char texto[], double frequencias[]) 
{    for (int i = 0; i < 26; i++) 
{
frequencias [i] = 0;

}
    int letras = 0;
    for (int i = 0; texto[i] != '\0'; i++) 
    {
        char c = texto[i];
        if (c >= 'A' && c <= 'Z')
         {
            frequencias[c - 'A']++;
            letras++;
        }
         else if (c >= 'a' && c <= 'z') 
        {
            frequencias[c - 'a']++;
            letras++;
        }
    }
    for (int i = 0; i < 26; i++) 
    {
        frequencias[i] /= letras;
    }
}
int encontrardeslocamento(double frequencias[])
 {
    int deslocamento = 0;
    double menor = 1e9;
    for (int i = 0; i < 26; i++)
     {
        double diferenca = 0.0;
        for (int j = 0; j < 26; j++)
         {
            int x = (j + i) % 26;
            diferenca += (frequencias[j] - tab[x]) * (frequencias[j] - tab[x]) / tab [x];
        }
        if (diferenca < menor) 
        {
            menor = diferenca;
            deslocamento = i;
        }
    }
    return deslocamento;
}
void decifrar(char texto[], int deslocamento)
 {
    for (int i = 0; texto[i] != '\0'; i++) 
    {
        char c = texto[i];
        if (c >= 'A' && c <= 'Z') 
        {
            printf("%c", ((c - 'A' + deslocamento) % 26) + 'A');
        }
        else if (c >= 'a' && c <= 'z') 
        {
            printf("%c", ((c - 'a' + deslocamento) % 26) + 'a');
        } 
        else 
        {
            printf("%c", c);
        }
    }
}
int main() 
{
    char texto_cifrado[10000];
     if (fgets(texto_cifrado, sizeof(texto_cifrado), stdin) != NULL) 
     {

    double frequencias[26];
    calcularfrequencias(texto_cifrado, frequencias);

    int deslocamento = encontrardeslocamento(frequencias);

    printf("%d ", deslocamento);
    decifrar(texto_cifrado, deslocamento);
     }
    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.