维吉尼亚密码破解实验报告

维吉尼亚密码破解实验报告

思路

主要就是计算重合指数来进行破解
遍历尝试秘钥长度
在确定秘钥长度的基础上,对于每一个分组尝试计算偏移量——相当于破解单个的凯撒密码,用到的也是重合指数的计算

代码分析

在代码所在的文件夹中”密文.txt”,”明文.txt”分别存放要破解的密文和破解得到的明文,通过文件输入输出函数进行处理。用到向量将密文的字母全部读入。

int main()
{
    char * name[3]={NULL,NULL,NULL};
    name[0]="密文.txt";
    name[1]="明文.txt";
    if( !name[0] )
    {
        cout<<"cracker: too few parameters"<<endl;
        //printUsage();
        return 0;
    }
    vector<char> m;
    //读入文章内容 
    readFile(name[0],m);
    //破解秘钥
    crack(name[0],"cracked.txt",1);
    //破解密文
    decrypt(name[0],name[1],key);
    return 0;
}

然后先尝试不同的秘钥长度下,重合指数和统计学的重合指数的方差,遍历1~256不同的长度的可能秘钥长度,认为方差最小的秘钥长度就为实际的秘钥长度。

//mode==1的时候是计算重合指数,mode==0的时候是检验一定偏移的时候重合指数是否符合要求 
double calcKasiski(vector<char> seq, int mode = 1)//mode 0:check mode
{
    int freq[26]={
  0};
    double result=0;
    int n = seq.size();
    for(int i=0;i<n;i++)
    {
        if( (seq[i]-'a'<0) || (seq[i]-'a'>=26) )
        {
            cout<<"calcKasisiki():seq-\'a\' overflow"<<endl;
            return 0;
        }
        freq[seq[i]-'a']++;
    }
    double Pi=0;
    for(int j=0;j<26;j++)
    {
        if(mode==1)
        {
            Pi = freq[j]*1.0/n;
        }
        else
        {
            Pi = freq_table[j]/100;
        }
        result = result + Pi * (freq[j]-1)*1.0/(n-1);
    }
    return result;
}
// 秘钥长度分析 
double klenAssess(const vector<char> raw_text,int klen)
{
    vector<char> m[klen];
    char c;
    int n=raw_text.size();

    for(int i=0;i<n;i++)
    {
        c=raw_text[i];
        if(c==EOF)
         break;
        m[i%klen].push_back(c);
    };

    double sqdiff=0;
    for (int j=0;j<klen;j++)
    {
        double ksk = calcKasiski(m[j],1);
        sqdiff = sqdiff + (ksk-KASISKI)*(ksk-KASISKI);
    }
    sqdiff=sqdiff*1.0/klen;
    cout<<"square diff of ksk for klen="<<klen<<": "<<sqdiff<<endl;
    return sqdiff;
}

在确定秘钥长度的基础上,将密文以秘钥长度为步长分组,对于每一个分组,遍历26个可能的偏移量,此时也是用到重合指数计算,选择重合指数最小的偏移量作为该组的偏移量,并得到对应的秘钥的字母。

//计算每一组的偏移,选择检验模式的,计算重合指数最符合的偏移 
char kCrackShift(const vector<char> list)//only a-z in list
{
    double result[26]={
  0};
    for(int j=0;j<26;j+&
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值