維吉尼亞密碼暴力破解c++實現
阿新 • • 發佈:2019-02-07
維吉尼亞密碼是一種多表替換密碼,暴力破解相對來說比單表置換密碼難一些。在網上找基於重合互指數法的破解程式碼,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;
求出金鑰之後解密就很容易啦,查表即可。