资源简介
在只知道密文的情况下,对密文分析。猜测密钥长度,然后进行验证,确定密钥长度后,破译出密钥,最后反解出原文。c语言代码,密文放在txt文件当中,破译的明文,也保存在txt文件当中,扩展性强
代码片段和文件信息
#include
#include
#include
#include
#define top 100//设置输入上限
int judge(char str[]);
void guess_keyt(char *secret);
void analysis(char *secretint lengthint m_len);
void translate(char *secretint lenint lengthint m_lenchar *alphabet);
void write_file(char yuan_wen[]);
int main()
{
FILE *fp;
char secret[1000];//保存初始密文
if((fp = fopen(“密文.txt““r“)) == NULL)//从文件当中读取初始,并保存在数组中
{
printf(“文件打开失败!“);
return -1;
}
fscanf(fp“%s“&secret);
fclose(fp);
guess_keyt(secret);
return 0;
}
//用来猜测密钥长度
void guess_keyt(char *secret)
{
int ijktotal = 0;
double max;
int m_len;//初步确认的密钥长度
int length;//初始密文长度
int num;//保存输入的密钥长度
char s_top[10];//输入的猜测的密钥长度,字符串格式,然后判断输入是否合法
char *secret1 = secret;
length = strlen(secret1);
printf(“请输入你认为的密钥最大长度(不超过%d):\n“top);
scanf(“%s“s_top);
num = judge(s_top);
int coincidence[top];//移动num位后,每次移动的重合次数
double average;//总共移动num次后,重合次数的平均数
double fangc[num];//总共移动num次后,每次移动的方差
//用凯撒猜测发,初步确认密钥长度
//计算从移动1次,到移动你认为的最大次数的,重合次数
for(i = 1;i <= num;i++)
{
coincidence[i-1] = 0;
for(j = 0k = i;j < length;j++k++)
{
if(k == length)
{
k = 0;
}
if(secret[k] == secret1[j])
{
coincidence[i-1]++;
}
}
}
printf(“移动%d的重合次数分别为:\n“num);
for(i = 0;i < num;i++)
{
total = total + coincidence[i];
printf(“%d “coincidence[i]);
}
//计算每一次的样本方差,用来找出最佳值
average = total*1.0/num;
printf(“%d“total);
printf(“\n\n这%d次的平均数为:\n%.2f\n\n“numaverage);
printf(“样本方差分别为:\n“);
for(i = 0;i < num;i++)
{
fangc[i] = (coincidence[i] - average)*(coincidence[i] - average);
printf(“%.2f “fangc[i]);
}
//方差最大值时对应的次数,最有可能就是密钥的长度,计算可能的密钥长度
for(i = 0;i < num;i++)
{
if(max < fangc[i])
{
max = fangc[i];
m_len = i + 1;
}
}
printf(“\n\n我们可以明显的看出来,第%d个样本方差为%.2f远远大于其他数据\n即密钥长度可能为:%d\n\n接下来通过重合指数进行验证\n\n\n“m_lenmaxm_len);
analysis(secretlengthm_len);
// printf(“%d“num);
}
void analysis(char *secretint lengthint m_len)
{
int i = 0j = 0k = 0num = 0;
int len;//分组后每组的长度
float average = 0ave1 = 0ave2 = 0;
char group[m_len][len];//分组后的密文
char alphabet[] = {“ABCDEFGHIJKLMNOPQRSTUVWXYZ“};
int frequency[m_len][26];//分组后每组每个字母的频数
double ratio[m_len];//每组中任取两个字母相同的概率
len = length / m_len;//按密钥长度对密文进行分组,计算每组的长度
if(length % m_len != 0)
{
len++;
}
for(i = 0;i < len;i++)//对密文分组
{
for(j = 0;j < m_len;j++)
{
group[j][i] = secret[k];
k++;
}
}
for(i = 0;i < m_len;i++)//对分组后的密文,计算每组当中每个字母出现的频数
{
for(j = 0;j < 26;j++)
{
frequency[i][j] = 0;
for(k = 0;k < len;k++)
{
if(group[i][k] == alphabet[j])
{
frequency[i][j]++;
}
}
}
}
for(i = 0;i < m_len;i++)//对每一组分别计算重合指数,即任取两个字母相同的概率
{
ratio[i] = 0;
num = 0;
for(j = 0;j < 26;j++)
{
if(frequency[i][j] >= 2)//出现次数小于2的字母,不存在取到两个相同的情况
{
num += frequency[i][j]*(frequency[i][j
属性 大小 日期 时间 名称
----------- --------- ---------- ----- ----
文件 312 2017-02-25 15:49 密文.txt
文件 7690 2017-03-10 22:21 维吉尼亚密码解析.cpp
- 上一篇:服装销售管理系统
- 下一篇:蛮力法、分治法和动态规划法设计最大子段和问题的算法
评论
共有 条评论