维吉尼亚密码破解(重合指数法)(完整代码,C++实现)

接上篇,针对我上篇的编码方式可以完美破解,有时间再补思路哈。

#include<iostream>
#include<stdio.h>
#include<cstring>
using namespace std;
float wf[] = {0.082, 0.015, 0.028, 0.043, 0.127, 0.022, 0.02, 0.061, 0.07, 0.002, 0.008, 0.04, 0.024, 0.067, 0.075, 0.019, 0.001, 0.06, 0.063, 0.091, 0.028, 0.01, 0.023, 0.001, 0.02, 0.001};

//解密 
void decrypt(string c,string k)
{
  string p="";
  int lk=k.size(),cl=c.size(),s=0;
  for(int i=0;i<cl;i++)
  {
	//其它字符 
  	if(c[i]>='a'&&c[i]<='z')
  	{
		int j=(i-s)%lk;
		p+=(c[i]-'a'+26-(k[j]-'a'))%26+'a';
	} 
	else if(c[i]>='A'&&c[i]<='Z')
	{
		int j=(i-s)%lk;
		p+=(c[i]-'A'+26-(k[j]-'a'))%26+'a';
	}
	else
	{
  		p+=c[i];
	    s++;
	}
  }
  cout<<"明文为:"<<p;
}

//求解密钥 
void getk(string c,string c1) 
{
  //求出密钥长度 
  int klen=1;   //密钥长度
  int clen=c.size();   //密文的长度 	     	
  while(1)
  {

    float IC[klen]; //重合指数
	float avgIC=0;  //平均重合指数
	for(int i=0;i<klen;i++)    //求每组重合指数 
	{		
	    int out[26]={ 0 };   //盛放字母个数的数组
		for(int j=0;i+j*klen<clen;j++)
	    { 
	       if(c[i+j*klen]>='a'&&c[i+j*klen]<='z')//小写 
	          out[(int)(c[i+j*klen]-'a')]++;
	       else if(c[i+j*klen]>='A'&&c[i+j*klen]<='Z')//大写 
	          out[(int)(c[i+j*klen]-'A')]++;
		} 
        float e=0;
        int L=0;
        for(int k=0;k<26;k++)    
            L+=out[k];
        L*=(L-1);
	    for(int k=0;k<26;k++)       
	       if(out[k]!=0)
	           e+=((float)out[k]*(float)(out[k]-1))/(float)L;
		IC[i]=e;
    }
    
	for(int i=0;i<klen;i++)  //求IC的平均值
	   avgIC+=IC[i];
	avgIC/=klen;  
	          
    if (avgIC >= 0.06)  break;    //判断退出条件,重合指数的平均值是否大于0.06 
    else  klen++;
  }
  
   cout<<"密钥长度为:"<<klen<<endl; 
   
  //求出密钥具体值 
    string k="";
	int key[klen]={ 0 };    //存放密钥 
	for(int i=0;i<klen;i++)    //逐个推测密钥字 
	{	
	    int g=0;   //密文移动g个位置 
	    for(int t=0;t<26;t++)
	    {
	 	   float x=0.000f;    //拟重合指数 	
	       int   out[26]={ 0 };   //盛放字母个数的数组
		   for(int j=0;i+j*klen<clen;j++)
	       { 
	         if(c[i+j*klen]>='a'&&c[i+j*klen]<='z')//小写 
	           out[(int)(c[i+j*klen]-'a')]++;
	         else if(c[i+j*klen]>='A'&&c[i+j*klen]<='Z')//大写 
	           out[(int)(c[i+j*klen]-'A')]++;
		   }  
           int L=0;
           for(int k=0;k<26;k++)
		   {
		   	    L+=out[k];     //子串密文长度  
                x+=wf[k]*out[(k+g)%26];  //逐个尝试字母表,求出拟重合指数无偏估计量
			}      

            if(x/L>0.055)
            {
        	    key[i]=g;
        	    break;
		    }
            else g++;
	   }
    } 
    for(int i=0;i<klen;i++)    //输出密钥字 
		k+=char ('a'+key[i]);
   cout<<"密钥为:"<<k<<endl;
   decrypt(c1,k);
}

int main()
{
	string c1;
	cout<<"请输入密文:";
	getline(cin,c1); 
	int clen=c1.size();
	
	string c="";
	for(int i=0;i<clen;i++)
    {
  	if(c1[i]>='a'&&c1[i]<='z')
  	{
		c+=c1[i];
	} 
	else if(c1[i]>='A'&&c1[i]<='Z')
	{
	   c+=c1[i];
	}
	else
	{
        continue;
	}
    } 
    
	getk(c,c1);
	return 0;
} 
//Asolm dlpy dlsaws aewv oisfe Flh Ncczw Zcuhrtkoamzy, hoij dvhop evlmc sshhd lbk hzyh avfdh altd cyklywgeetcu. Tpzdsi cpojx qzf px zcwnmylhlh qcct emzia jzff filcg hkz, lh alle hpqp, l upvw dvvapo cmj spf syifff my evl tfmzpg xprpe, dss aswo dlsaws alle vlv qlhoic hoz e xpaiic zt alp Csk Gczgz Scroumklhpsy. Xcyi lyr tscp dlsaws rrph vlv, essf xszinle evlc hpfl gspoaio mm alp zfneytnhxtzb, alp xcuij evlc ozbhxpo khw yzh bwpo wu xsp fpkse khc. Ess prntrlre soz e rcshx ypuhxtgs prqwilrnp cu xsp Flh Ncczw Zcuhrtkoamzy, dlsaws kse efbwe th hrj xcyi, essf ecp bvx htzsmyr hv hzyoai esspv xzblc. Ld tvv xp, W dmww bvx ozbhxp xcuij ec alp zfneytnhxtzb, P gszczi ez upzp xcuij ec alp asywzy kos td wu rppr vj spzw, wz evl qzysf azyh ii elylr mj calpcg, tevp gbvp evl tpcgvr rph alp cshp xzblc.

最后的注解为提供的可破解的文本

  • 9
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值