1 #include<stdio.h>
  2 
  3 int main(){
  4     char msg[700];
  5     int i,j,t;             
  6     int d=0;
  7     char c;
  8     printf("请在输入的字符串后加上'$'\n"); 
  9     while(1){//统计输入了多少个字符,以$结尾
 10         c=getchar();
 11         if(c=='$')break;
 12         msg[d]=c;
 13         d++;
 14     }
 15         int times=0;//计数
 16         int times2[10]={0};     
 17     int chonghe(int d){
 18         float down=0.059;//阈值 
 19         int i,j=0;
 20         for(j=2;j<10;j++){//不断尝试密钥长度 
 21             int a=0;
 22             int t=0;
 23 
 24             int no=0;
 25             int k;
 26             float sum=0.0;
 27             int num[10][30]={0};
 28             char e[700];
 29             char group[10][400];    
 30             for(i=0;i<d;i+=j){//分组 
 31             group[0][a]=msg[i];
 32             group[1][a]=msg[i+1];
 33             if(j>2&&i+2<d)group[2][a]=msg[i+2];
 34             if(j>3&&i+3<d)group[3][a]=msg[i+3];
 35             if(j>4&&i+4<d)group[4][a]=msg[i+4];
 36             if(j>5&&i+5<d)group[5][a]=msg[i+5];
 37             if(j>6&&i+6<d)group[6][a]=msg[i+6];
 38             if(j>7&&i+7<d)group[7][a]=msg[i+7];
 39             if(j>8&&i+8<d)group[8][a]=msg[i+8];//密钥最长支持为10位 
 40             if(j>9&&i+9<d)group[9][a]=msg[i+9];
 41             a++;
 42             }        
 43         
 44 
 45         
 46         for(i=0;i<a;i++){//分组后统计一个分组里各个字母出现的次数 
 47             no=(int)group[0][i]-97;
 48             num[0][no]++;
 49             no=(int)group[1][i]-97;
 50             num[1][no]++;
 51             if(j>2){
 52                 no=(int)group[2][i]-97;
 53                 num[2][no]++;
 54             }
 55             if(j>3){
 56                 no=(int)group[3][i]-97;
 57                 num[3][no]++;
 58             }
 59             if(j>4){
 60                 no=(int)group[4][i]-97;
 61                 num[4][no]++;
 62             }
 63             if(j>5){
 64                 no=(int)group[5][i]-97;
 65                 num[5][no]++;
 66             }
 67             if(j>6){
 68                 no=(int)group[6][i]-97;
 69                 num[6][no]++;    
 70             }
 71             if(j>7){
 72                 no=(int)group[7][i]-97;
 73                 num[7][no]++;
 74             }
 75             if(j>8){
 76                 no=(int)group[8][i]-97;
 77                 num[8][no]++;
 78             }    
 79             if(j>9){
 80                 no=(int)group[9][i]-97;
 81                 num[9][no]++;
 82             }
 83         }
 84         times=0;
 85         
 86         for(t=0;t<j;t++){//计算重合指数 
 87             sum=0.0;
 88             for(i=0;i<26;i++){
 89                 sum=sum+(num[t][i]/(float)a)*(num[t][i]/(float)a);
 90             }
 91             if(sum<down) times+=1;
 92         }
 93         if(times==0)times2[j]=1;//值都满足阈值的分组记为1 
 94         else times2[j]=0;
 95         
 96     int temp=0;
 97     int times3=0;
 98     for(i=0;i<j;i++){//判断有几组大于阈值 
 99         if(times2[i]==1){
100             times3++;
101             temp=i;
102         }
103     }
104     if(times3==1&&j==9)return temp;//只有一组就反馈出来 
105     else if(times3>1) {
106         down=down+0.001;//超过一组就增加阈值
107         j=0;//从头再来 
108         continue;
109     }
110     else if(times3==0&&j==9){//阈值过高,从头再来 
111         down=down-0.001; 
112         j=0;
113         continue;
114     }
115         
116     }
117     }    
118     
119     int temp=chonghe(d);
120     printf("密钥长度为:%d\n",temp);
121     
122     void fmi(int d,int temp){//计算重合互指数,前面步骤与计算重合指数一致 
123         int a=0;
124         int t=0;
125         int i=0;
126         int j=0;
127         int q=0;
128         int no=0;
129         float sum=0.0;
130         int num[10][30]={0};
131         char group[10][400];
132         int number[10]={0};//记录各位的偏移量 
133         
134         for(i=0;i<d;i=i+temp){//分组 
135             group[0][a]=msg[i];
136             group[1][a]=msg[i+1];
137             if(temp>2&&i+2<d)group[2][a]=msg[i+2];
138             if(temp>3&&i+3<d)group[3][a]=msg[i+3];
139             if(temp>4&&i+4<d)group[4][a]=msg[i+4];
140             if(temp>5&&i+5<d)group[5][a]=msg[i+5];
141             if(temp>6&&i+6<d)group[6][a]=msg[i+6];
142             if(temp>7&&i+7<d)group[7][a]=msg[i+7];
143             if(temp>8&&i+8<d)group[8][a]=msg[i+8];//密钥最长支持为10位 
144             if(temp>9&&i+9<d)group[9][a]=msg[i+9];
145             a++;
146         }
147         
148         for(i=0;i<a;i++){//统计一个分组里各个字母出现的次数 
149             no=(int)group[0][i]-97;
150             num[0][no]++;
151             no=(int)group[1][i]-97;
152             num[1][no]++;
153             if(d>2){
154                 no=(int)group[2][i]-97;
155                 num[2][no]++;
156             }
157             if(d>3){
158                 no=(int)group[3][i]-97;
159                 num[3][no]++;
160             }
161             if(d>4){
162                 no=(int)group[4][i]-97;
163                 num[4][no]++;
164             }
165             if(d>5){
166                 no=(int)group[5][i]-97;
167                 num[5][no]++;
168             }
169             if(d>6){
170                 no=(int)group[6][i]-97;
171                 num[6][no]++;    
172             }
173             if(d>7){
174                 no=(int)group[7][i]-97;
175                 num[7][no]++;
176             }
177             if(d>8){
178                 no=(int)group[8][i]-97;
179                 num[8][no]++;
180             }    
181             if(d>9){
182                 no=(int)group[9][i]-97;
183                 num[9][no]++;
184             }
185         }
186         int k=0;//偏移量 
187         int mark[10]={0};
188         for(i=0;i<temp-1;i++){
189             for(t=i+1;t<temp;t++){
190                 //printf("\n第%d组与第%d组:\n",i+1,t+1); 
191                 for(q=0;q<26;q++){
192                     sum=0.0;
193                     for(j=0;j<26;j++){
194                         if(j-q<0)k=j-q+26;
195                         else k=j-q;
196                         sum=sum+(num[i][j]/(float)a)*(num[t][k]/(float)a);
197                     }
198                     //printf("%d:%f\t",q,sum);
199                     if(sum>0.060){
200                         if(i==0) {
201                             number[t]=26-q;
202                             
203                             mark[t]=1; //标为1则表示该位有一值大于阈值 
204                             //break;
205                         }
206                         else if(i==1){
207                             if(mark[t]==0)number[t]=abs(26-q-number[1]);
208                             //break;
209                         }
210                     }
211                 }
212                 
213                 
214             }
215         }
216         for(i=1;i<temp;i++){printf(" %d",number[i]);}
217         
218         int key[10];
219         int pos_key[26][10];
220         for(i=0;i<26;i++){
221             printf("\n第%d个密钥:",i+1);
222             for(t=1;t<temp;t++){
223                 key[t]=i+number[t];
224                 if(key[t]>=26)key[t]=key[t]-26;
225                 pos_key[i][t]=key[t];
226             }
227             pos_key[i][0]=i;
228             for(t=0;t<temp;t++){
229                 printf("%c",pos_key[i][t]+97);
230             }
231             
232         }
233         int dec;
234         for(j=0;j<26;j++){
235             printf("\n第%d次:\n",j+1);
236             for(i=0;i<d;i+=temp){
237                 for(t=0;t<temp;t++){
238                     dec=(int)msg[i+t]-pos_key[j][t]-97;
239                     if(dec<0)dec=dec+26;
240                     printf("%c",(char)(dec+97));
241                 }
242             
243             }
244     
245         }
246     }
247     
248     fmi(d,temp);
249         
250     return 0;
251     
252 }            
代码写得有些臃肿,但是能用就行。

 

posted on 2021-09-23 11:39  allons10  阅读(216)  评论(0)    收藏  举报