古典密码附截图和C++代码
发布时间:2024-10-23
发布时间:2024-10-23
古典密码 密码学
实验一 实现一个多表古典加密和解密程序
计算机学院 信安08-3班 柴婷婷 08083708
一、实验目的:
掌握多表古典加密方法。
二、实验要求:
能用高级语言实现古典加密方法。
三、实验内容:
多表古典加密方法主要有Playfair体制、Vigenere体制、Beaufor体制、Vernam体制和Hill体制,用高级语言实现其中一种体制的加密和解密算法。
四、实验过程:
1、Vigenere加密解密:
维吉尼亚密码引入了“密钥”的概念,即根据密钥来决定用哪一行的密表来进行替换,以此来对抗字频统计。
#include <iostream>
#include <string>
using namespace std;
const int N=26;
char
v[N][N]={{'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}}; int number(char x)//把行号字母对应到数字
{
char y='a';
for(int i=0;i<N;i++)
{
if(x==(y+i)) return i;
}
}
void encryption(string m,string k)//加密
{
cout<<"明文:";
cin>>m;
cout<<"密钥:";
cin>>k;
int mlen,klen;
mlen=m.length();
klen=k.length();
char *p,*q,*t;//明文,初始密钥,密钥串。把string换成char
古典密码 密码学
p=new char[m.length()+1];
strcpy(p,m.c_str());
q=new char[k.length()+1];
strcpy(q,k.c_str());
t=new char[m.length()+1];
int j=0;
for(int i=0;i<mlen;i++)
{
t[i]=q[j];
j++;
j=j%klen;
}//生成密钥
cout<<"密文:";
for(i=0;i<mlen;i++)
cout<<v[number(t[i])][number(p[i])];
cout<<endl;
}
void disencryption(string c,string k)//解密
{
cout<<"密文:";
cin>>c;
cout<<"密钥:";
cin>>k;
int clen,klen;
clen=c.length();
klen=k.length();
char *p,*q,*t;//密文,初始密钥,密钥串。把string换成char
p=new char[c.length()+1];
strcpy(p,c.c_str());
q=new char[k.length()+1];
strcpy(q,k.c_str());
t=new char[c.length()+1];
int j=0;
for(int i=0;i<clen;i++)
{
t[i]=q[j];
j++;
j=j%klen;
}//生成密钥
cout<<"明文:";
for(i=0;i<clen;i++)
for(int j=0;j<N;j++)
if(v[number(t[i])][j]==p[i]) {cout<<char(j+97);break;}
cout<<endl;
古典密码 密码学
}
int main()
{
for(int i=1;i<N;i++)
{
for(int j=0;j<N;j++)
{
v[i][j]=v[i-1][(j+1)%N];
}//方阵初始化
}
cout<<"欢迎使用Vigenere加密!"<<endl<<endl;
cout<<"请选择要进行的操作"<<endl;
int flag;
do{
cout<<"1.加密2.解密3.结束:"<<endl;
cin>>flag;
string m,k;
if(flag==1)encryption(m,k);
else if(flag==2) disencryption(m,k);
else if(flag!=1&&flag!=2&&flag!=3) cout<<"输入错误,请重新输入!";
}while(flag!=3);
return 0;
}
运行结果:
2、Playfair 加解密
古典密码 密码学
算法描述:Playfair密码出现于1854年,它依据一个5*5的正方形组成的密码表来编写,密码表里排列有25个字母。如果一种语言字母超过25个,可以去掉使用频率最少的一个。英语中z使用最少,可以去掉它。法语一般去掉w或k,德语则是把i和j合起来当成一个字母看待。英语中z使用最少,可以去掉它。
加密描述:第一步是编制密码表。在这个5*5的密码表中,共有5行5列字母。第一列(或第一行)是密钥,其余按照字母顺序。密钥是一个单词或词组,若有重复字母,可将后面重复的字母去掉。当然也要把使用频率最少的字母去掉。
第二步整理明文。将明文每两个字母组成一对。如果成对后有两个相同字母紧挨或最后一个字母是单个的,就插入一个字母X。
对明文加密规则如下:
1 若p1 p2在同一行,对应密文c1 c2分别是紧靠p1 p2 右端的字母。其中第一列被看做是最后一列的右方。如,按照前表,ct对应oc
2 若p1 p2在同一列,对应密文c1 c2分别是紧靠p1 p2 下方的字母。其中第一行被看做是最后一行的下方。
3 若p1 p2不在同一行,不在同一列,则c1 c2是由p1 p2确定的矩形的其他两角的字母(至于横向替换还是纵向替换要事先约好,或自行尝试)。如,按照前表,wh对应tk或kt。
对密文解密规则如下:
1 若c1 c2在同一行,对应明文p1 p2分别是紧靠c1 c2 左端的字母。其中最后一列被看做是第一列的左方。
2 若c1 c2在同一列,对应明文p1 p2分别是紧靠c1 c2 上方的字母。其中最后一行被看做是第一行的上方。
3 若c1 c2不在同一行,不在同一列,则p1 p2是由c1 c2确定的矩形的其他两角的字母。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM 1000
古典密码 密码学
int main()
{
int i,j,k=0,m,n,temp=0,length;
char key[NUM],voa[26];
char table[5][5];
char word[NUM];
printf("欢迎使用playfair加密!");
printf("密钥: ");
scanf("%s",key);
length=strlen(key);
for(i=0;i<length;i++)
{
if(key[i]=='j')
key[i]='i';
}
for(i=0;i<length;i++)
{
for(j=i+1;j<length;j++)
if(key[i]==key[j])
{
for(int t=j;t<length;t++)
{
key[t]=key[t+1];
}
j--;
length--;
}
if(j==1)
{
key[j]=0;
break;
}
}
for(i=0;i<26;i++)
{
voa[i]=65+i;
}
for(i=0;i<length;i++)
{
key[i]=key[i]-32;
}
古典密码 密码学
char p;
int count=0;
for(i=0;i<26;i++)
{
p=voa[i];
for(j=0;j<length;j++)
{
if(p==key[j])
{
key[i+length]=p;
count+=1;
break;
}
}
if(j==length)
{
key[i+length-count]=p;
}
}
int u=0;
for(i=0;i<26;i++)
{
if(key[i]=='J')
{
for(u=i;u<26;u++)
{
key[u]=key[u+1];
}
}
if(key[i]=='I')
key[i]='*';
}
temp=0;
for(i=0;i<5;i++)
{
for(j=0;j<5;j++)
{
古典密码 密码学
table[i][j]=key[j+temp];
printf("%c ",table[i][j]);
if(j==4)
{
temp+=5;
printf("\n");
}
}
}
printf("明文: ");
scanf("%s",word);
length=strlen(word);
int counter=0;
for(i=0;i<length;)
{
if(word[i]==word[i+1])
{
i+=1;
counter+=1;
}
else
i+=2;
}
for(i=0;i<length+counter;i+=2)
{
if(word[i]==word[i+1])
{
for(j=length+counter-1;j>i+1;j--)
{
word[j]=word[j-1];
}
word[i+1]='x';
}
}
length=length+counter;
古典密码 密码学
if(length%2!=0)
{
word[length]='x';
length+=1;
}
for(k=0;k<length;k++)
{
word[k]=word[k]-32;
}
for(i=0;i<length;i++)
{
if(word[i]=='I'||word[i]=='J')
{
word[i]='*';
}
}
count=0,k=0;
loop: for(i=0;i<5,k<length;i++)
{
for(j=0;j<5;j++)
{
for(m=0;m<5;m++)
{
for(n=0;n<5;n++)
{
if((table[i][j]==word[k])&&(table[m][n]==word[k+1])&&(i==m)) {
count=1;
word[k]=table[i][j+1];
word[k+1]=table[m][n+1];
if(j==4)
{
word[k]=table[i][0];
}
if(n==4)
{
古典密码 密码学
word[k+1]=table[m][0];
}
k+=2;
if(count==1)
{
goto loop;
}
}
else if((table[i][j]==word[k])&&(table[m][n]==word[k+1])&&(j==n)) {
count=1;
word[k]=table[i+1][j];
word[k+1]=table[m+1][n];
if(i==4)
{
word[k]=table[0][j];
}
if(m==4)
{
word[k+1]=table[0][n];
}
k+=2;
if(count==1)
{
goto loop;
}
}
else if((table[i][j]==word[k])&&(table[m][n]==word[k+1])&&(i!=m)&&(j!=n)) {
count=1;
word[k]=table[i][n];
word[k+1]=table[m][j];
k+=2;
if(count==1)
{
goto loop;
}
}
古典密码 密码学
}
}
}
}
printf("密文: ");
for(k=0;k<length;k++)
{
printf("%c ",word[k]);
}
printf("\n");
system("pause");
return 0;
}
运行结果:
3、Vernam(弗纳姆)加解密 主要步骤
1.按递增顺序把每个明文字母作为一个数字,A=0,B=1等等.
2.对输入密文中每一个字母做相同的处理.
3.将明文中的每个字母与密钥中的相应字母相加.
4.如果得到的和大于26,则从中减去26.
5.将和转化为字母,从而得到密文.
例如 明文: H O W A R E Y O U
古典密码 密码学
7 14 22 0 17 4 24 14 20
+ 2.密钥 N C B T Z Q A R X 13 2 1 19 25 16 0 17 23 3.初始和 20 16 23 19 42 20 24 31 43 4.大于25则模26 20 16 23 19 16 20 24 5 17
5.密文 U Q X T Q U Y F R
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string plain,ciper,key;
int len; //长度三者一致
void change(string &, vector<int>&);//字符变数字
vector<int> encrypt_compute(vector<int> m,vector<int> k);//加密计算 vector<int> discrypt_compute(vector<int> c,vector<int> k);//解密计算 void re_change( vector<int>&,string &);//数字变字符
cout<<"欢迎使用Vernam加解密:"<<endl;
cout<<"====================="<<endl;
int flag; //操作标记
do
{
cout<<"请选择操作:1、加密 2、解密 3、结束:"<<endl; cin>>flag;
if(flag==1)
{
cout<<"请输入明文:";
cin>>plain;
cout<<"请输入相同长度的密钥:";
cin>>key;
len = plain.size();
vector<int> p,c,k; //存变换的数字
change(plain, p);
change(key, k); //字母->数字
c = encrypt_compute(p,k);
re_change(c,ciper); //数字->字母
cout<<"密文是:"<<ciper<<endl;
}
if(flag==2)
{
古典密码 密码学
cout<<"请输入密文:";
cin>>ciper;
cout<<"请输入相同长度的密钥:";
cin>>key;
len = ciper.size();
vector<int> p,c,k; //存变换的数字
change(ciper, c);
change(key, k); //字母->数字
p = discrypt_compute(c,k);
plain="";//清空明文原来的值
re_change(p,plain);
cout<<"明文是:"<<plain<<endl;
}
}while(flag!=3);
return 0;
}
void change(string &plain, vector<int>&number) //字母变数字 {
for (unsigned int i=0;i<plain.size();i++)
{
number.push_back(plain[i]-97); //a为0
}
}
vector<int> encrypt_compute(vector<int> m,vector<int> k) //加密计算 {
vector<int> sum;
for(unsigned int i=0; i<m.size(); i++)
{
sum.push_back((m[i]+k[i])%26);
}
return sum;
}
vector<int> discrypt_compute(vector<int> c,vector<int> k) //解密计算 {
vector<int> resum;
int temp;
for(unsigned int i=0; i<c.size(); i++)
{
temp = c[i]-k[i];
if(temp<0) temp+=26;
resum.push_back(temp);
}
古典密码 密码学
return resum;
}
void re_change( vector<int>& sum,string &c) //数字变字符 {
string temp;//用于处理insert函数变量传递
for (unsigned int i=0;i<sum.size();i++)
{
temp=sum[i]+97;
c.insert(i,temp);//a为0
}
}
运行结果:
上一篇:磁盘调度算法三个java