日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

古典密码之维吉尼亚密码无密钥破解

發布時間:2023/12/15 综合教程 29 生活家
生活随笔 收集整理的這篇文章主要介紹了 古典密码之维吉尼亚密码无密钥破解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

維吉尼亞密碼

(又譯維熱納爾密碼)是使用一系列凱撒密碼組成密碼字母表的加密算法,屬于多表密碼的一種簡單形式。

維吉尼亞密文是通過明文加上密鑰,根據維吉尼亞密碼表來生成密文。

維吉尼亞的密碼強度是跟密鑰的長度有關,或者你可以用幾個密鑰進行加密,如果幾個密鑰進行加密,那么我們盡量讓不同密鑰的長度互質,

如果明文不長,當密鑰長度和明文一樣長,理論上是不可破譯。

然而,實際上很那做到密鑰長度和明文長度一樣長,因此這就給維吉尼亞密碼破譯提供了可能。

1、首先,我們從維吉尼亞密碼加密方式可以發現,假如密鑰的長度為 k ,那么明文中第 Xi ,Xi+k ,Xi+2*k,……是不是用同一個密碼加密,那么不就是凱撒密碼嗎? 那么問題來了,我們怎么獲取到密鑰長度是多少呢?

2、Kasiski 實驗

   為了獲取到密鑰長度,我們需要進行Kasiski 實驗,什么是Kasiski 實驗呢?

假如有一段密文: ACEBTSSTRCESQSSTQRCK

那么我們從中挑選出至少三個字符以上相同的字串,并且比較他們相鄰兩個字串相鄰位置之差:比如密文中 "SST",它們相差了8。

因為在加密過程中,出現至少三個字符以上相同的字串,明文不同的概率是很小的,那么我們是不是可以知道,密鑰的長度一定是8的因子。

如果還能找到其他至少三個字符以上相同的字串,那么密鑰長度是它們的最大公約數的概率非常大。

到目前為止我們可能已經有好幾種密鑰長度的可能了,那么怎么來確定密鑰長度呢?或者說怎么求出密鑰,獲取明文呢?

3、重合指數攻擊

設一門語言由n個字母組成,每個字母出現的概率為 Pi 則重合指數是指兩個元素隨機相同的概率之和,記作 CI =∑ Pi2 (1<= i <= n);

經分析,英文中,一段文字是隨機的話,CI =0.0385 ;如果這段文字是有意義的,那么 CI=0.065 (約等)。實際上計算的CI應該用這個公式

L:密文長度; fi :在密文中的出現次數。 (公式來源)

  這個有什么好處呢?

  好處就是用我們猜測的密鑰長度來進行分組,分別計算每組的CI,再求個平均,計算當前密鑰長度下,CI 的值與0.065相差多少。然后按照最接近0.065的密鑰長度進行排序,為了提高解密的成功率,一般會取前5~10個較為接近的密鑰長度作為猜測。

  

4、字母頻率分析

  密鑰長度知道了,然而怎么獲取密鑰到底是多少呢?

還是根據統計學:我們可以知道每個字母在英文中的頻率

  字母表頻率

  正常的文本中,每個字母出現的頻率是遵循上述規則。

  那么破解密鑰就變得很簡單了,我們統計在某個密鑰長度下的密各個組的字母頻率,這樣對單個組來說,就是凱撒密碼,我們循環26次,判斷哪種情況下字母頻率與統計字母頻率的內積最大,即 R=∑Pi*Qi ('a'<= i <='z') 。

  這樣我們對密鑰的某個單個字符破解出來了,同理我們可以破解出密鑰。

最后從你程序輸出的幾組結果進行人工判別一下,哪個是有意義的明文。

(轉載請注明出處Thanks?(?ω?)?)

C++源程序:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 struct Node{
  4     float value; //重合指數差,與我們的標準重合指數的差值越小越好
  5     int length;
  6 };
  7 vector< Node > key; //存放key可能的長度和重合指數差
  8 set< int > key_len; //存放key可能的長度
  9 /*
 10 英文字母使用頻率表 g
 11 */
 12 double g[]={0.08167, 0.01492, 0.02782, 0.04253, 0.12702, 0.02228, 0.02015, 0.06094, 0.06966, 0.00153, 0.00772, 0.04025,0.02406, 0.06749, 0.07507, 0.01929, 0.00095, 0.05987, 0.06327, 0.09056, 0.02758, 0.00978, 0.02360, 0.00150,0.01974, 0.00074};
 13 bool Greater_sort(Node a,Node b){
 14     return a.value<b.value;
 15 }
 16 /*
 17 Coincidence_index,計算所選分組的重合指數
 18 start表示分組的起點,length表示步長
 19 重合指數CI的實際估計值是
 20 X(i)=F(i)*(F(i)-1)/sum*(sum-1)
 21 ('a'<=i<='z',F(i)為i字符在當前分組出現的次數)
 22 對上述X(i)求和就是整個分組的重合指數CI
 23 */
 24 float Coincidence_index(string cipher,int start,int length){
 25     float index=0.000;
 26     int sum=0;
 27     int num[26];
 28     memset(num,0,sizeof(num));
 29     while(start<=cipher.length()){
 30         num[cipher[start]-'a']++;
 31         start+=length;
 32         sum++;
 33     }
 34     for(int i=0;i<26;i++){
 35         if(num[i]<=1) continue;
 36         index+=(float)(num[i]*(num[i]-1))/(float)((sum)*(sum-1));
 37     }
 38     return index;
 39 }
 40 /*
 41 Find_same()函數即是根據 kasiski測試法的原理
 42 我們可以獲取key可能的長度
 43 */
 44 void Find_same(string cipher){
 45     for(int i=3;i<5;i++){
 46         for(int j=0;j<cipher.length()-i;j++){
 47             string p=cipher.substr(j,i);
 48             for(int k=j+i;k<cipher.length()-i;k++){
 49                 string tmp=cipher.substr(k,i);
 50                 if(tmp==p){
 51                     Node x;
 52                     x.length=k-j;
 53                     key.push_back(x);
 54                 }
 55             }
 56         }
 57     }
 58 }
 59 int gcd(int a,int b){
 60     if(b==0) return a;
 61     else return gcd(b,a%b);
 62 }
 63 /*
 64 
 65 求出可能的key的值的最大公因子
 66 經過重合指數檢驗,對key的長度進行排序
 67 
 68 */
 69 void Get_key(string cipher){
 70     Find_same(cipher);
 71     for(int i=0;i<key.size();i++){
 72         int x=key[i].length;
 73         for(int j=0;j<key.size();j++){
 74             if(key[i].length>key[j].length)
 75                 key_len.insert(gcd(key[i].length,key[j].length));
 76             else
 77                 key_len.insert(gcd(key[j].length,key[i].length));
 78         }
 79     }
 80     key.clear();
 81     set< int >::iterator it=key_len.begin();
 82     while(it!=key_len.end()){
 83         int length=*it;
 84         if(length==1){
 85             it++;
 86             continue;
 87         }
 88         float sum=0.000;
 89         cout<<length<<" ";
 90         for(int i=0;i<length;i++){
 91             cout<<Coincidence_index(cipher,i,length)<<"  ";
 92             sum+=Coincidence_index(cipher,i,length);
 93         }
 94         cout<<endl;
 95         Node x;
 96         x.length=length;
 97         x.value=(float)fabsf(0.065-(float)(sum/(float)length));
 98         if(x.value<=0.1)
 99             key.push_back(x);
100         it++;
101     }
102     sort(key.begin(),key.end(),Greater_sort);
103 }
104 /*
105 
106 為了提高解密的成功率,我們取前面10個公因子進行求解
107 對每個公因子的每個分子進行字母的擬重合指數分析
108 由Chi測試(卡方檢驗),獲取峰值點
109 該峰值點極有可能是明文
110 
111 */
112 void Get_ans(string cipher){
113     int lss=0;
114     while(lss<key.size()&&lss<10){
115         Node x=key[lss];
116         int ans[cipher.length()];
117         memset(ans,0,sizeof(ans));
118         map< char ,int > mp;
119         for(int i=0;i<x.length;i++){
120             double max_pg=0.000;
121             for(int k=0;k<26;k++){
122                 mp.clear();
123                 double pg=0.000;
124                 int sum=0;
125                 for(int j=i;j<cipher.length();j+=x.length){
126                     char c=(char)((cipher[j]-'a'+k)%26+'a');
127                     mp[c]++;
128                     sum++;
129                 }
130                 for(char j='a';j<='z';j++){
131                     pg+=((double)mp[j]/(double)sum)*g[j-'a'];
132                 }
133                 if(pg>max_pg){
134                     ans[i]=k;
135                     max_pg=pg;
136                 }
137             }
138         }
139         cout<<endl<<"key_length: "<<x.length<<endl<<"key is: ";
140         for(int i=0;i<x.length;i++){
141             cout<<(char)((26-ans[i])%26+'a')<<" ";
142         }
143         cout<<endl<<"Clear text:"<<endl;
144         for(int i=0;i<cipher.length();i++){
145             cout<<(char)((cipher[i]-'a'+ans[i%x.length])%26+'a');
146         }
147         cout<<endl;
148         lss++;
149     }
150 }
151 int main(){
152     string cipher;
153     cin>>cipher;
154     transform(cipher.begin(), cipher.end(), cipher.begin(),::tolower);
155     Get_key(cipher);
156     for(int i=0;i<key.size();i++){
157         cout<<key[i].length<<"  and "<<key[i].value<<endl;
158     }
159     Get_ans(cipher);
160     return 0;
161 }

總結

以上是生活随笔為你收集整理的古典密码之维吉尼亚密码无密钥破解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。