记得TP在上学期的程序设计周里做过一个实验,就是维吉尼亚密码加密的算法,当然,这是相当简单的。(不过TP不给力啊,我帮他完成了大部分)。
只需要将原文字text每个字符加上固定的密钥值就行,不过为了标准化,我们的原文小写无空格,密文大写,密钥大写。原文字可以文件读入。
//代码:大河时代。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
void toL(char* m)
{
int i;
for(i=0;i<strlen(m);i++)
if(m[i]>='a'&&m[i]<='z') m[i]-=32;
}
void tol(char* m)
{
int i;
for(i=0;i<strlen(m);i++)
if(m[i]>='A'&&m[i]<='Z') m[i]+=32;
}
void sol(char *m,char *keyw)
{
int i,lm,lk;
char ch,yon;
char c[500];
FILE *vv;
lm=strlen(m);
lk=strlen(keyw);
printf("the message is the following:(the key is %s)\n\n",keyw);
for(i=0;i<lm;i++)
{
ch=m[i]+(keyw[i%lk]-65)-97;
if(ch>25) ch-=26;
ch+=97;
ch-=32;
printf("%c",ch);
c[i]=ch;
}
c[lm]='\0';
printf("\n\n\nexport the message?(y/n)");
scanf("%c",&yon);
if(yon=='y'||yon=='Y')
{
getchar();
vv=fopen("message.txt","w+");
fprintf(vv,"%s\n",c);
printf("export success!the file name is message.txt\n");
fclose(vv);
}
}
void main()
{
char m[500];
char keyw[50];
int choose;
FILE *v;
printf("1.input the text by keyboard\n2.load text by file\nplease choose:");
scanf("%d",&choose);
while(choose!=1&&choose!=2)
{
printf("enter ERROR!\n");
scanf("%d",&choose);
}
getchar();
if(choose==1) gets(m);
if(choose==2)
{
printf("the file name must be text.txt,please ensure it!\n");
getch();
v=fopen("text.txt","r+");
if(v==0) {printf("load ERROR!\n");getch();exit(0);}
fscanf(v,"%s",m);
fclose(v);
}
tol(m);
system("cls");
printf("the message is :\n%s\n\nplease enter the key:",m);
scanf("%s",keyw);
getchar();
toL(keyw);
system("cls");
sol(m,keyw);
getch();
}
但是,这远远是不够的,对于一个信息安全的学生来讲,研究密码破译有着相当重要的意义。在未知密钥的情况下对于维吉尼亚加密的破解,已经有了很明确的方案。这里运用Kasiski测试法和重合指数法(ic)寻找密钥长度,再用重合指数法拟合每一位的密钥字符,最后解密。
当然,维吉尼亚的密码破译是有前提的。第一:原文必须有意义,不能是随便输入的字符。第二,原文必须有一定的长度,一般200字母即可。密文可以文件录入,如果Kasiski测试法不能找到较为准确的密钥长度,会提示破译失败。具体使用可以看程序本身。
//代码:大河时代。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
int sort(int* a,int* b,int* c,int x)
{
int count=0,i,j,flag=1;
int min,temp;
for(i=0;i<x;i++)
{
for(j=0;j<count;j++)
if(b[j]==a[i]) {flag=0;break;}
if(flag) b[count++]=a[i];
else flag=1;
}
for(i=0;i<count;i++)
{ c[i]=0;
for(j=0;j<x;j++)
if(a[j]==b[i]) c[i]++;
}
for(i=0;i<count-1;i++)
{
min=i+1;
for(j=i+1;j<count;j++)
if(c[j]<c[min]) min=j;
if(c[i]>c[min])
{
temp=b[i];b[i]=b[min];b[min]=temp;
temp=c[i];c[i]=c[min];c[min]=temp;
}
}
return count;
}
double ic(char *p)
{
int i,j,l;
double a[27]={0.0};
double s=0.0;
l=strlen(p);
for(j=1;j<=26;j++)
for(i=0;i<l;i++)
if(p[i]==65+j-1) a[j]++;
for(i=1;i<=26;i++)
{
a[i]=(a[i]*(a[i]-1))/(l*(l-1));
if(a[i]>1e-8) s+=a[i];
}
return s;
}
int doulet(char m[],char a[][2],int b[],int c[][10],int d[][10],int e[][80], int f[380])
{ //文本 //连续字母 //出现个数 //位置 //相对位置 //位置的因子 //因子个数
char p,q,x;
int i,j,k,l=strlen(m),count=0,t,max,min,temp,s;
for(i=0;i<l-1;i++)
{
p=m[i];q=m[i+1];
x=0;
for(j=0;j<l-1;j++)
if(m[j]==p&&m[j+1]==q) x++;
if(x>1) {a[count][0]=p;a[count][1]=q;b[count]=x;count++;}
}
for(i=0;i<count-1;i++)
for(j=i+1;j<count;j++)
if(a[i][0]==a[j][0]&&a[i][1]==a[j][1])
{
for(k=j;k<count-1;k++)
{ a[k][0]=a[k+1][0];
a[k][1]=a[k+1][1];
b[k]=b[k+1];
}
count--;
}
for(i=0;i<count-1;i++)
{
max=i+1;
for(j=i+1;j<count;j++)
if(b[j]>b[max]) max=j;
if(b[i]<b[max])
{
temp=b[i];b[i]=b[max];b[max]=temp;
temp=a[i][0];a[i][0]=a[max][0];a[max][0]=temp;
temp=a[i][1];a[i][1]=a[max][1];a[max][1]=temp;
}
}
for(i=0;i<count;i++)
{
t=0;
for(j=0;j<l;j++)
if(m[j]==a[i][0]&&m[j+1]==a[i][1])
{c[i][t++]=j;}
}
for(i=0;i<count;i++)
for(j=0;j<b[i]-1;j++)
d[i][j]=c[i][j+1]-c[i][j];
for(i=0;i<count;i++)
{
t=0;
for(j=0;j<b[i]-1;j++)
{
for(k=1;k<=(d[i][j]<50?d[i][j]:50);k++)
if(d[i][j]%k==0) e[i][t++]=k;
}
f[i]=t;
}
for(s=0;s<count;s++)
{
for(i=0;i<f[s]-1;i++)
for(j=i+1;j<f[s];j++)
if(e[s][i]==e[s][j])
{
for(k=j;k<f[s]-1;k++)
e[s][k]=e[s][k+1];
f[s]--;
}
for(i=0;i<f[s]-1;i++)
{
min=i+1;
for(j=i+1;j<f[s];j++)
if(e[s][j]<e[s][min]) min=j;
if(e[s][i]>e[s][min])
{
temp=e[s][i];e[s][i]=e[s][min];e[s][min]=temp;
}
}
}
if(count>20) count=20;
return count;
}
void qksort(int* zh,int zhn)
{
int i,min,j,temp;
for(i=0;i<zhn-1;i++)
{
min=i+1;
for(j=i+1;j<zhn;j++)
if(zh[j]<zh[min]) min=j;
if(zh[i]>zh[min])
{
temp=zh[i];zh[i]=zh[min];zh[min]=temp;
}
}
}
int zhengl(int* a,int *b,int *c,int n)
{
int x=1,i,j,max,temp;
for(i=0;i<n;i++)
a[i]=c[i];
for(i=1;i<n;)
{
if(a[i]==a[i-1])
{
for(j=i;j<n-1;j++)
a[j]=a[j+1];
n--;
x++;
}
else {b[i-1]=x;i++;x=1;}
}
b[n-1]=x;
for(i=0;i<n-1;i++)
{
max=i+1;
for(j=i+1;j<n;j++)
if(b[j]>b[max]) max=j;
if(b[i]<b[max])
{
temp=b[i];b[i]=b[max];b[max]=temp;
temp=a[i];a[i]=a[max];a[max]=temp;
}
}
n=n>18?18:n;
return n;
}
double cic(char* m,int n)
{
int i,j,k;
int p[50]={0};
char ch[50][500];
double xic[50],s=0.0;
for(i=0;i<strlen(m);i++)
{
ch[i%n][p[i%n]]=m[i];
p[i%n]++;
}
for(i=0;i<n;i++)
{
ch[i][p[i]]='\0';
p[i]++;
}
for(i=0;i<n;i++)
xic[i]=ic(ch[i]);
for(i=0;i<n;i++)
s+=xic[i];
return s/n;
}
void cal(char* m,int key,char *keyw)
{
double plet[27]={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 i,j,k,l,letmax[50];
double pml[27]={0.0},ic[27]={0.0},icmax[50];
int p[50]={0};
char ch[50][500];
char change[500];
for(i=0;i<strlen(m);i++)
{
ch[i%key][p[i%key]]=m[i];
p[i%key]++;
}
for(i=0;i<key;i++)
{
ch[i][p[i]]='\0';
}
printf("\n");
for(i=0;i<key;i++) //行
{
for(j=0;j<26;j++) //加j
{
for(k=0;k<26;k++) pml[k]=0;
ic[j]=0.0;
for(k=0;k<p[i];k++) //列
{
change[k]=ch[i][k]-j;
if(change[k]<65) change[k]+=26;
}
for(k=0;k<p[i];k++)
pml[change[k]-65]++;
for(k=0;k<26;k++)
ic[j]+=(pml[k]/p[i])*plet[k];
}
letmax[i]=0;icmax[i]=ic[0];
for(j=0;j<26;j++)
if(fabs(icmax[i]-0.065)>fabs(ic[j]-0.065))
{
icmax[i]=ic[j];
letmax[i]=j;
}
printf("%d\t%c\t%f %.2f%%\n",letmax[i],letmax[i]+'A',icmax[i],fabs(icmax[i]-0.065)*100);
}
for(i=0;i<key;i++)
keyw[i]=letmax[i]+65;
keyw[key]=0;
}
void sol(char *m,char *keyw)
{
int i,lm,lk;
char ch,yon;
char c[500];
FILE *vv;
lm=strlen(m);
lk=strlen(keyw);
printf("the text is the following:(the key is %s)\n\n",keyw);
for(i=0;i<lm;i++)
{
ch=m[i]-(keyw[i%lk]-65);
if(ch<65) ch+=26;
ch+=32;
printf("%c",ch);
c[i]=ch;
}
c[lm]='\0';
printf("\n\n\nexport the text?(y/n)");
scanf("%c",&yon);
if(yon=='y'||yon=='Y')
{
getchar();
vv=fopen("text.txt","w+");
fprintf(vv,"%s\n",c);
printf("export success!the file name is text.txt\n");
fclose(vv);
}
}
void toL(char* m)
{
int i;
for(i=0;i<strlen(m);i++)
if(m[i]>='a'&&m[i]<='z') m[i]-=32;
}
void main()
{
char m[500];
int i,n,j,num[380];
char dl[380][2];
int c[380][10],d[380][10],e[380][80],f[380];
int zh[1000],zhn=0;
int yz[1000],yzs[1000],gs;
double xic[20],xdic[20];
int key=0;
char keyw[50],yon;
int choose;
FILE *v;
printf("1.input the message by keyboard\n2.load message by file\nplease choose:");
scanf("%d",&choose);
while(choose!=1&&choose!=2)
{
printf("enter ERROR!\n");
scanf("%d",&choose);
}
getchar();
if(choose==1) gets(m);
if(choose==2)
{
printf("the file name must be message.txt,please ensure it!\n");
getch();
v=fopen("message.txt","r+");
if(v==0) {printf("load ERROR!\n");getch();exit(0);}
fscanf(v,"%s",m);
fclose(v);
}
toL(m);
system("cls");
printf("the message is :\n%s\n\nthe first step is to search the num of key,continue?(y/n)",m);
scanf("%c",&yon);
if(yon=='y'||yon=='Y') {getchar();system("cls");} else exit(0);
n=doulet(m,dl,num,c,d,e,f);
for(i=0;i<n;i++){
printf("%c%c %d ",dl[i][0],dl[i][1],num[i]);
for(j=0;j<num[i]-1;j++) printf("%d,",d[i][j]);
if(num[i]>3) printf("\t"); else if(num[i]>1) printf("\t\t"); else printf("\t\t\t");
for(j=0;j<f[i];j++) printf("%d,",e[i][j]);
printf("\n");}
for(i=0;i<n;i++)
for(j=0;j<f[i];j++)
zh[zhn++]=e[i][j];
qksort(zh,zhn);
printf("\nproper nums of key:\n");
gs=zhengl(yz,yzs,zh,zhn);
for(i=0;i<gs;i++)
printf("%-3d ",yz[i]);
printf("\n");
printf("\n");
for(i=0;i<gs;i++)
{
xic[i]=cic(m,yz[i]);
xdic[i]=fabs(xic[i]-0.065)*100;
}
for(j=0;j<gs;j++)
if(xdic[j]<1.0) {key=yz[j];break;}
if(key==0) printf("no key nums are available!please check the message!\n");
else{
for(i=0;i<gs;i++)
{
if(xdic[i]<1.0)
{
printf("%-5d%-5d %lf\t%.2lf%%\n",yz[i],yzs[i],xic[i],xdic[i]);
if(yz[i]<key) key=yz[i];
}
}
printf("key num %d is recomended,continue the second step?(y/n)",key);
scanf("%c",&yon);
if(yon=='y'||yon=='Y')
{getchar();system("cls");}
else
{printf("enter the num of key:");scanf("%d",&key);getchar();system("cls");}
cal(m,key,keyw);
printf("%s\n",keyw);
printf("key %s is recomended,continue?",keyw);
scanf("%c",&yon);
if(yon=='y'||yon=='Y')
{getchar();system("cls");}
else
{printf("enter the key:");scanf("%s",&keyw);getchar();system("cls");}
toL(keyw);
sol(m,keyw);
}
getch();
}
下面可以给出一个密文,大家用程序测试一下就知道可以破译的了。将密文保存至程序目录,命名message.txt即可。
BZGTNPMMCGZFPUWJCUIGRWXPFNLHZCKOAPGLKYJNRAQFIUYRAVGNPANUMDQOAHMWTGJDXGOMPJPTKAAVZIUIWKVTUCWBWNFWDFUMPJWPMQGPTNWXTSDPLPMWJAXUHHXWPFXXGVAPFNTXVFKOYIRBOQJHCBVWVFYCGQFGUSUBDWVIYATJGTBNDKGHCTMTWIUEFJITVUGJHHIMUVJICUWYQWYGGUWPUUCWIFGWUANILKPHDKOSPJTTWJQOJHXLBJAPZHVQWPDYPGLLGDBCHTGIZCCMEGVIIJLIFFBHSMEGUJHRXBOQUBDNASPEUCWNGWSNWXTSDPLPMWJAIUHUMWPSYCTUWFBMIAMKVBNTDMQNBVDKILQSSDYVWVXIGDQFIBHSLEAVDBXGOLGDBCHTGIZVNFQFKTNGRWXUDCTGKWCOXIXKZPPFDZG