1. 程式人生 > >維吉尼亞密碼暴力破解c++實現

維吉尼亞密碼暴力破解c++實現

  維吉尼亞密碼是一種多表替換密碼,暴力破解相對來說比單表置換密碼難一些。在網上找基於重合互指數法的破解程式碼,java、python都有,本菜鳥只有c++用的相對熟練一點,就用c++寫了暴力破解過程。程式碼耗時提高效率什麼的暫沒考慮。

  維吉尼亞方陣是26*26的方陣,第一行代表明文字母,第一列代表金鑰字母,每一行都是一個凱撒加密。


在只知道密文的情況下想要破解維吉尼亞加密,首先要確定金鑰的長度。

確定金鑰長度有兩種方式:

1.Kasiski測試法

  搜尋長度至少為2的相鄰的一對對相同的密文段,記下它們之間的距離。而金鑰長度d可能就是這些距離的最大公因子。

2.重合指數法

 公式:

  

程式碼:

void Miyaolenth(char c[]) 
{
  int klen=1;   //金鑰長度
  int clen=strlen(c);   //密文的長度 		     	
  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++)
		   out[(int)(c[i+j*klen]-'A')]++;  
        float e=0.000f;
        int L=0;
        for(int k=0;k<26;k++)    //子串密文長度 
            L+=out[k];
        L*=(L-1);
	    for(int k=0;k<26;k++)        //分組計算重合指數IC 
	       if(out[k]!=0)
	           e=e+((float)out[k]*(float)(out[k]-1))/(float)L;
		IC[i]=e;
    }
	for(int i=0;i<klen;i++)
	   avgIC+=IC[i];
	avgIC/=klen;          //求IC的平均值  
    if (avgIC >= 0.06)  break;    //判斷退出條件,重合指數的平均值是否大於0.06 
    else  klen++;
  }
  cout<<"金鑰長度為:"<<klen<<endl; 
}

確定好金鑰長度之後開始求金鑰。

重合互指數法求金鑰:

  根據金鑰的長度對密文進行分組,每一組都是一個凱撒加密。計算擬重合指數,通過擬重合指數可以確定每組的移位金鑰,從而求出整個的金鑰。

公式:


程式碼:

float p[] = {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};
	
	int key[100]={ 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++)
		   out[(int)(c[i+j*klen]-'A')]++;  
        int L=0;
        for(int k=0;k<26;k++)      //子串密文長度 
            L+=out[k];
        for(int k=0;k<26;k++)
            x=x+p[k]*out[(k+g)%26];
        if(x/L>0.055)
        {
        	key[i]=g;
        	break;
		}
        else g++;
	   }
    }
   cout<<"加密金鑰為:"; 
   for(int i=0;i<klen;i++)    //輸出金鑰字 
		cout<<char ('a'+key[i]);
   cout<<endl;



求出金鑰之後解密就很容易啦,查表即可。