目录+源码

目录
1.古典密码
1.1仿射密码
1.2维吉尼亚密码
1.3 PLAYFAIR
1.4 ADFGX
1.5 HILL加密
2.序列密码
2.1 LFSR
2.2 RC4
2.3 A5
3.DES加解密
3.1 DES
3.2 DES-ECB
3.3 DES-CBC
3.4 DES-CFB
3.5 DES-OFB
3.6 DES-CTR
3.7 模式选用和比较
4.RSA加密
5.Hash函数(MD5)
6.综合实验

源码:
1.古典密码
1.1仿射密码

#include<bits/stdc++.h>
using namespace std;
int k1,k2,k;
string s; 
char c;
int re()
{
    
    
	for(int i=1;;i++)
	 if((i*k1)%26==1)
	 {
    
    
	 	return i;
	 }
}
void encode(int x)
{
    
    
	x=(k1*x+k2)%26;
	c='A'+x-1;
	cout<<c;
}
void decode(int x)
{
    
    
	x=(x-k2)*k%26;
	while(x<0) x+=26;
	c='a'+x-1;
	cout<<c;
}
int main()
{
    
    
  cout<<"下标从1开始,加密输入小写字符,解密输入大写字母"<<endl; 
  while(1)
  {
    
    
  cout<<"请输入k1,k2 : ";
  cin>>k1>>k2;
  cout<<"请输入待处理的字符串 : "; 
  getline(cin,s);
  getline(cin,s);
  k=re();//计算k1的逆 
  for(int i=0;i<s.length();i++)
  {
    
    
  	if(s[i]>='a'&&s[i]<='z')
  	 encode(s[i]-'a'+1);
	else if(s[i]>='A'&&s[i]<='Z') decode(s[i]-'A'+1);
	else cout<<s[i];
  }
   cout<<endl;  	
  }
  return 0;
} 
//k1=7 k2=10
//明文:please send moneys   
//密文:RPSQMS MSDL WKDSCM

1.2维吉尼亚密码

#include<bits/stdc++.h>
using namespace std;
int k1,k2,k,len,tip=0;
string key,s; 
char c;
void encode(int x)
{
    
    
	x=(s[x]-'a'+key[tip]-'a')%26;
	c='A'+x;
	cout<<c;
}
void decode(int x)
{
    
    
    x=(s[x]-'A'-(key[tip]-'a'))%26;
    while(x<0) x+=26;
    c='a'+x;
    cout<<c;
}
int main()
{
    
    
  cout<<"下标从0开始,加密输入小写字符,解密输入大写字母"<<endl; 
  while(1)
  {
    
    tip=0;
  cout<<"请输入密钥(小写) :";
  getline(cin,key);
  cout<<"请输入待处理的字符串 : "; 
  getline(cin,s);
  len=key.length();
  for(int i=0;i<s.length();i++)
  {
    
    
  	if(s[i]>='a'&&s[i]<='z')
  	 encode(i),tip++;	
	else if(s[i]>='A'&&s[i]<='Z') decode(i),tip++;
	else cout<<s[i];
	tip%=len;
  }  
  cout<<endl;	
  } 
  return 0;
} 
//密钥:encryption
//明文:public key distribution
//密文:THDCGR DMM QMFVIGQNBWBR

1.3 PLAYFAIR

#include<bits/stdc++.h>
using namespace std;
struct node{
    
    
 int x,y;
}post[30];//记录每个单词的位置 
int bo[30];
string key,s;
char c,g[10][10];
void pre()//构造密码表 
{
    
    
	int i=0,j=0,t;
	for(int k=0;k<key.length();k++) //关键词填充 
	 if(key[k]>='a'&&key[k]<='z')
 	 {
    
    
		t=key[k]-'a';
		if(bo[t]==0)//判断是否重复 
		{
    
    
			bo[t]=1;
			post[t].x=i;post[t].y=j;g[i][j]=t+'A';
			j++;
			if(j>=5) j=0,i++;
		}
	 }
	if(bo[9]) post[8].x=post[9].x,post[8].y=post[9].y;
	for(int k=0;k<26;k++)
	 if(k!=9&&bo[k]==0&&!(k==8&&bo[9])) //剩余单词填充 
	 {
    
    
	 	bo[k]=1;
	 	post[k].x=i;post[k].y=j;g[i][j]=k+'A';
	 	j++;
	 	if(j>=5) j=0,i++;
	 }
	post[9].x=post[8].x,post[9].y=post[8].y;
}
int main()
{
    
    
  cout<<"密钥(小写),明文(小写),密文(大写)"<<endl; 
  while(1)
  {
    
    
  cout<<"请输入密钥:";
  getline(cin,key);
  cout<<"请输入字符串:"; 
  getline(cin,s);
  cout<<"请输入事先约定好的一个字母: ";
  cin>>c; 
  //
  pre();
  cout<<"输出密码表:"<<endl;
  for(int i=0;i<5;i++)
  {
    
    
  	cout<<"  ";
  	for(int j=0;j<5;j++)
  	 cout<<g[i][j];
  	cout<<endl;
  }
  for(int i=0;i<s.length();i++)
   if(s[i]==' ')
    s.erase(s.begin()+i);
  /
  int tip=0,top;
  if(s[0]>='a'&&s[0]<='z')//加密
  {
    
    
  	for(int i=0,j=1;j<s.length();)
  	{
    
    
  	  if(s[i]==s[j]) s.insert(i+1,1,c);//重复字符,插入 
	  i+=2;j+=2;
	}
	if(s.length()%2) s.insert(s.length(),1,c);
	for(int i=0;i<s.length();i+=2)
	{
    
    
		int tx=post[s[i]-'a'].x,ttx=post[s[i+1]-'a'].x,ty=post[s[i]-'a'].y,tty=post[s[i+1]-'a'].y;
	 	if(tx==ttx) //同行,取右边 
	 	{
    
    
	 		cout<<g[tx][(ty+1)%5]<<g[tx][(tty+1)%5];
		}
		else if(ty==tty)//同列。取下面 
	 	{
    
    
	 		cout<<g[(tx+1)%5][ty]<<g[(ttx+1)%5][ty];
		}
		else cout<<g[tx][tty]<<g[ttx][ty];//取两角 
		cout<<" ";
	} 
  }
  else
  {
    
    
  	char tmp[100000];int tip=0;
  	for(int i=0;i<s.length();i+=2)
	{
    
    
		
		int tx=post[s[i]-'A'].x,ttx=post[s[i+1]-'A'].x,ty=post[s[i]-'A'].y,tty=post[s[i+1]-'A'].y;
	 	if(tx==ttx)//同行,取左边 
	 	{
    
    
	 		tmp[tip]=(char)(g[tx][(ty-1+5)%5]-'A'+'a');
	 		tmp[tip+1]=(char)(g[tx][(tty-1+5)%5]-'A'+'a');
	 		tip+=2;
		}
		else if(ty==tty)//同列,取上面 
	 	{
    
    
	 		tmp[tip]=(char)(g[(tx-1+5)%5][ty]-'A'+'a');
	 		tmp[tip+1]=(char)(g[(ttx-1+5)%5][ty]-'A'+'a');
	 		tip+=2;
		}
		else //取反对角 
		{
    
    
			tmp[tip]=(char)(g[tx][tty]-'A'+'a');
			tmp[tip+1]=(char)(g[ttx][ty]-'A'+'a');
			tip+=2;
		}
	}
	if(tmp[tip]==c) tip--;
	for(int i=0;i+2<tip;i++)
	 if(tmp[i]==tmp[i+2]&&tmp[i+1]==c)//重复字母,去掉插入字母 
	  tmp[i+1]=' ';
	for(int i=0;i<tip;i++)
	  if(tmp[i]>='a'&&tmp[i]<='z')
	  cout<<tmp[i];
  } 
  cout<<endl;
  memset(bo,0,sizeof(bo));
  getline(cin,key);
  }
  return 0;
} 
//密钥:fivestars 
//明文:playfair cipher was actually
//密文:QK BW IT VA AS OK VB IG IC TA WT QZ KZ 
//字母:q 
//PPT:ch2 P42

1.4 ADFGX

#include<bits/stdc++.h>
using namespace std;
char g[6][6]={
    
    {
    
    ' ','A','D','F','G','X'},
              {
    
    'A','p','g','c','e','n'},
			  {
    
    'D','b','q','o','z','r'},
			  {
    
    'F','s','l','a','f','t'},
			  {
    
    'G','m','d','v','i','w'},
			  {
    
    'X','k','u','y','x','h'}}; //字母表 
struct node{
    
    
	int x,y;
	bool operator<(const node &a) const{
    
    
	 if(x==a.x) return y<a.y;
	 return x<a.x;
	} 
}t;
map<char,node>post,wei;
string s,key;
int main()
{
    
    
  cout<<"输出密码表:"<<endl;
  for(int i=0;i<=5;i++)
  {
    
    
   cout<<" ";
   for(int j=0;j<=5;j++)
   {
    
    
   	cout<<g[i][j]<<" ";
   	t.x=i;t.y=j;post[g[i][j]]=t;
   }
   cout<<endl;	
  } 
  post['A'].x=1;post['A'].y=1;
  post['D'].x=2;post['D'].y=2;
  post['F'].x=3;post['F'].y=3;
  post['G'].x=4;post['G'].y=4;
  post['X'].x=5;post['X'].y=5;//存储每个字母在字母表中的位置 
  cout<<"明文(小写),密文(大写),关键字(大写,不能有重复字母)"<<endl;
  while(1)
  {
    
    
  cout<<"输入字符串:";
  getline(cin,s);
  cout<<"输入关键字:";
  getline(cin,key);
  for(int i=0;i<s.length();i++)//去空格 
   if(s[i]==' ')
    s.erase(s.begin()+i);
  for(int i=0;i<key.length();i++)
   if(key[i]==' ')
    key.erase(key.begin()+i);
  if(s[0]>='a'&&s[0]<='z')//加密 
  {
    
    
  	第一步:代替 
  	for(int i=0;i<s.length();)
	{
    
    
		int tx=post[s[i]].x,ty=post[s[i]].y;
		s.erase(s.begin()+i);
		s.insert(i,1,g[tx][0]);
		s.insert(i+1,1,g[0][ty]);
		i+=2;
	} 
	//第二步:关键字标记
	queue<char>q[30];//存储 
	char p[100000];
	int len=key.length(); 
	for(int i=0;i<len;i++)
	{
    
    
	 p[i]=key[i];
	 int tmp=key[i]-'A';
	 for(int j=i;j<s.length();j+=len)
	  q[tmp].push(s[j]);
	} 
	//排序,按列读 
	sort(p,p+len);
	for(int j=0;j<len;j++)
	  while(q[p[j]-'A'].size())
	  {
    
    
		if(q[p[j]-'A'].front()>='A'&&q[p[j]-'A'].front()<='Z')
		  	cout<<q[p[j]-'A'].front();
		q[p[j]-'A'].pop();
	  }
  }
  else//解密 
  {
    
    
  	queue<char>q[30];
  	char p[100000];
	int len=key.length(),res;
	map<char,int>po; 
	for(int i=0;i<len;i++)
	 p[i]=key[i],po[key[i]]=i;
	sort(p,p+len);//关键字排序 
	res=s.length()%len;
    for(int i=0,j=0;i<s.length()&&j<len;j++)//将密文分给不同的关键字字母 
    {
    
    
    	wei[p[j]].x=i;
    	if(po[p[j]]<res) wei[p[j]].y=i+s.length()/len;
    	else  wei[p[j]].y=i+s.length()/len-1;
    	for(int k=wei[p[j]].x;k<=wei[p[j]].y;k++)
    	 q[p[j]-'A'].push(s[k]);
    	i=wei[p[j]].y+1;
	}
	char tt[100000];int tip=0;
	for(int i=0;i<s.length();)//矩阵行读 
	{
    
    
		for(int j=0;j<len;j++)
		 if(q[key[j]-'A'].size())
		 {
    
    
		 	if(q[key[j]-'A'].front()>='A'&&q[key[j]-'A'].front()<='Z')
		 	 tt[tip]=q[key[j]-'A'].front(),tip++,i++;
		 	q[key[j]-'A'].pop();
		 }
	}
	for(int i=0;i<tip;i+=2)//通过行列找到明文 
	{
    
    
		int tx=post[tt[i]].x,ty=post[tt[i+1]].y;
		cout<<g[tx][ty];
	}
  }
  cout<<endl;
  }
  return 0;
} 
//明文:kaiser wilhelm    
//关键字:RHEIN 
//密文:FAGDFAFXFGFAXXDGGGXGXGDGAA 

1.5 HILL加密

#include<bits/stdc++.h>
using namespace std;
int k[300][300],k1[300][300],t[300][300],tmp[300][300];
string s;
int n;
int main()
{
    
    
  cout<<"输入 n = ";
  cin>>n;
  cout<<"请输入密钥(n*n矩阵):"<<endl;
  for(int i=1;i<=n;i++)
   for(int j=1;j<=n;j++)
   {
    
    
   	cin>>k[i][j];k[i][j]%=26;
   }
  cout<<"请输入字符串(长度为n*n ; 明文:小写):"<<endl;
  getline(cin,s);
  getline(cin,s);
  for(int i=0;i<s.length();i++)//去空格 
   if(s[i]==' ')
    s.erase(s.begin()+i);
  for(int i=1;i<=n;i++)//明文分组排列 
   for(int j=1;j<=n;j++)
   {
    
    
   	if(s[(n*(i-1))+j-1]>='a'&&s[(n*(i-1))+j-1]<='z') 
   	 tmp[i][j]=(s[(n*(i-1))+j-1]-'a')%26;
   	else tmp[i][j]=(s[(n*(i-1))+j-1]-'A')%26;
   }
 for(int i=1;i<=n;i++)
  for(int j=1;j<=n;j++)
 	t[i][j]=tmp[j][i];
  if(s[0]>='a'&&s[0]<='z')//加密 
  {
    
    
  	for(int i=1;i<=n;i++)//矩阵乘 
  	 for(int j=1;j<=n;j++)
  	 {
    
    
  	  k1[i][j]=0;
	  for(int kk=1;kk<=n;kk++)
	   k1[i][j]=(k1[i][j]+k[i][kk]*t[kk][j])%26;
	 }
	/
	for(int i=1;i<=n;i++)
	 for(int j=1;j<=n;j++)
	  cout<<(char)('A'+k1[j][i]);
  }
  else//解密 
  {
    
    
  	
  	
  	///求k的逆矩阵k1 
  	
  	for(int i=1;i<=n;i++)
  	 for(int j=1;j<=n;j++)
  	 {
    
    
  	  k[i][j]=0;
	  for(int kk=1;kk<=n;kk++)
	   k[i][j]=(k[i][j]+k1[i][kk]*t[kk][j])%26;
	 }
	/
	for(int i=1;i<=n;i++)
	 for(int j=1;j<=n;j++)
	  cout<<(char)('a'+k[j][i]);  	
  }
  return 0;
} 
//n=2;
//明文:good
//密钥: 11 8
//        3 7 
//密文:WMWL 

2.序列密码
2.1 LFSR

#include<bits/stdc++.h>
using namespace std;
int n,a[10000000],b[10000000],t[10000000],tmp,ans=0;
int ok()
{
    
    
	int T=0;
	for(int i=1;i<=n;i++)
	 T+=t[i];
	if(T==0) return 1;
	for(int i=1;i<=n;i++)
	{
    
    
	 if(t[i]!=b[i])
	  return 0;	
	 T+=t[i];
	}
	return 1;
}
int main()
{
    
    
  cout<<"请输入级数n = ";
  cin>>n;
  cout<<"请输入LFSR的特征多项式的系数(0或1)(x,x^2,...,x^n):"<<endl;
  for(int i=1;i<=n;i++)
   cin>>a[i];
  cout<<"特征多项式:";
  cout<<"1";
  for(int i=1;i<=n;i++)
   if(a[i])
    cout<<" + x^"<<i;
  cout<<endl; 
  cout<<"请输入初始状态:"<<endl;
  for(int i=n;i>=1;i--)
  {
    
    
  	cin>>b[i];t[i]=b[i];
  }
  cout<<"请输入是否显示过程:(1:显示 ; 0:不显示)"<<endl;
  int x;cin>>x; 
  while(1)
  {
    
    
  	if(x)  	cout<<"状态(an,...,a1)为:"; 
  	tmp=2;
  	for(int i=n;i>=1;i--)//计算 
  	{
    
    
  		if(x)  	cout<<t[i]<<" ";
  		if(a[i])
  		{
    
    
  		 if(tmp==2) tmp=t[i];
		 else tmp^=t[i];	
		}
	}
	if(x)
	{
    
    
	 cout<<endl;
  	 cout<<"输出为:"<<tmp<<endl; 	
	}
	for(int i=1;i<n;i++)//移位 
	 t[i]=t[i+1];
	t[n]=tmp;ans++;
	if(ok()) break;//判断是否重复 
  }
  cout<<"周期: "<<ans;
  return 0;
} 
//n=16
//本原多项式:x^16+x^12+x^3+x+1
//1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1
//初始状态: 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 

2.2 RC4

#include<bits/stdc++.h>
using namespace std;
int qpow(int a,int b)//快速幂 
{
    
    
	int c=1;
	while(b)
	{
    
    
	 if(b%2) c*=a;
	 a*=a;b/=2;	
	} 
	return c;
}
int main()
{
    
    
  while(1)
  {
    
    
   int n,s[100000],k[100000];
   string key,S;
   cout<<"请输入位数 n=";
   cin>>n;
   int len=qpow(2,n);
   for(int i=0;i<len;i++)//初始化S表 
    s[i]=i;
   cout<<"请输入密钥(由0-2^n-1的数组成):"<<endl;
   getline(cin,key);
   getline(cin,key);
   int tip=0;
   for(int i=0;i<len;i++)//填充密钥数据表 
    k[i]=key[tip]-'0',tip++,tip%=key.length();
   for(int j=0,i=0;i<len;i++)//初始变换 
    j=(j+s[i]+k[i])%len,swap(s[i],s[j]); 
   cout<<"请输入字符串:"<<endl;
   getline(cin,S);
   tip=0;cout<<"解为:"<<endl; 
   for(int i=0;i<S.length();i++) 
   {
    
    
   	int t=((((S[i]&240)>>4)^s[tip])<<4)+(S[i]&15)^s[tip+1];
   	cout<<(char)t;
   	tip+=2;tip%=len;
   }//11110000=240  00001111=15  
   cout<<endl;
  } 
  return 0;
} 
//n=3
//123
//zxcvbnm

2.3 A5

#include<bits/stdc++.h>
using namespace std;
int n,a[30],b[30],c[30],x,y,z,t1;
void mova()
{
    
    
  t1=a[13]^a[16]^a[17]^a[18];
  for(int i=18;i>=1;i--)
   a[i]=a[i-1];
  a[0]=t1;
}
void movb()
{
    
    
  t1=b[12]^b[16]^b[20]^b[21];
  for(int i=21;i>=1;i--)
   b[i]=b[i-1];
  b[0]=t1;
}
void movc()
{
    
    
  t1=c[17]^c[18]^c[21]^c[22];
  for(int i=22;i>=1;i--)
   c[i]=c[i-1];
  c[0]=t1;
}
int main()
{
    
    
  cout<<"请输入寄存器 A 的 初始状态(19位):"<<endl;
  for(int i=0;i<19;i++)
   cin>>a[i];
  cout<<"请输入寄存器 B 的 初始状态(22位):"<<endl;
  for(int i=0;i<22;i++)
   cin>>b[i];
  cout<<"请输入寄存器 C 的 初始状态(23位):"<<endl;
  for(int i=0;i<23;i++)
   cin>>c[i];    
  cout<<"继续:1 ,退出: 0 "<<endl; 
  while(cin>>n&&n)
  {
    
    
  	x=a[9];y=b[11];z=c[11];
  	cout<<"输出: "<<(a[18]^b[21]^c[22])<<endl;//计算输出 
  	//择多移位 
    if((x+y+z)>=2)
	{
    
    
	 if(x) mova();
	 if(y) movb();
	 if(z) movc();	
	}
	else
	{
    
    
	 if(x==0) mova();
	 if(y==0) movb();
	 if(z==0) movc();	
	}
	cout<<" A 的中位数 : "<<x<<"; "<<" B 的中位数 : "<<y<<"; "<<" C 的中位数 : "<<z<<"; "<<endl;
	cout<<"寄存器 A 的状态为: "<<endl;
	for(int i=0;i<19;i++)
	 cout<<a[i]<<" ";
	cout<<endl;
	cout<<"寄存器 B 的状态为: "<<endl;
	for(int i=0;i<22;i++)
	 cout<<b[i]<<" ";
	cout<<endl;
	cout<<"寄存器 C 的状态为: "<<endl;
	for(int i=0;i<23;i++)
	 cout<<c[i]<<" ";
	cout<<endl;
  }
  return 0;
} 
// A: 1 0 1 0 1 0 1 0 0 1 1 0 0 1 1 0 1 0 1 
// B: 0 1 0 1 1 0 1 0 1 1 0 1 0 1 0 1 0 1 1 1 0 1
// C: 0 1 1 1 0 0 1 0 1 0 1 0 1 0 0 1 1 0 1 0 1 0 1

3.DES加解密
3.1 DES

#include<bits/stdc++.h>
using namespace std;
int IP_Table[64]={
    
    58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
    57, 49, 41, 33, 25, 17,  9, 1, 59, 51, 43, 35, 27, 19, 11, 3,61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 };
int IPR_Table[64]={
    
    40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
    36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41,  9, 49, 17, 57, 25 };    
int E_Table[48]={
    
    32,  1,  2,  3,  4,  5,  4,  5,  6,  7,  8,  9,8,  9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17,
    16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32,  1};//扩展 
int P_Table[32]={
    
    16, 7, 20, 21, 29, 12, 28, 17, 1,  15, 23, 26, 5,  18, 31, 10,2,  8, 24, 14, 32, 27, 3,  9,  19, 13, 30, 6,  22, 11, 4,  25};
int PC1_Table[56]={
    
    57, 49, 41, 33, 25, 17,  9,  1, 58, 50, 42, 34, 26, 18,10,  2, 59, 51, 43, 35, 27, 19, 11,  3, 60, 52, 44, 36,
    63, 55, 47, 39, 31, 23, 15,  7, 62, 54, 46, 38, 30, 22,14,  6, 61, 53, 45, 37, 29, 21, 13,  5, 28, 20, 12,  4};
int PC2_Table[48]={
    
    14, 17, 11, 24,  1,  5,  3, 28, 15,  6, 21, 10,23, 19, 12,  4, 26,  8, 16,  7, 27, 20, 13,  2,
    41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32};
int S_Box[8][4][16]={
    
         
    14, 4,  13,     1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
    4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13,// S1
    15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
    0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9,// S2
    10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
    13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12, // S3
    7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
    10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14, // S4
    2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
    4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3,// S5
    12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
    9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13,// S6
    4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
    1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12,// S7
    13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
    7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11// S8
};
//把CHAR转换为INT
void CharToBit(const char input[],int output[])
{
    
    
    for(int j=0;j<8;j++)
     for(int i=0;i<8;i++)
      output[8*j+7-i]=(input[j]>>i)&1;//右移i位取最后一位 
};
//把INT转换为CHAR
void BitToChar(const int intput[],char output[])
{
    
    
    for(int j=0;j<8;j++)
     for(int i=0;i<8;i++)
      output[j]=output[j]*2+intput[i+8*j];//0101 0101
}; 
//异或
static void Xor(int *INA,int *INB,int len)
{
    
    
    for(int i=0;i<len;i++)
     *(INA+i)=*(INA+i)^*(INB+i);
};
static void Change(const int input[],int output[],int table[],int t)//t==64: 初始IP,逆IP置换;
																	//t==56:PC_1;
                                                                    //t==48: PC_2,E扩展;
																	//t==32:P置换;													
{
    
    
    for(int i=0;i<t;i++)
     output[i]=input[table[i]-1];
};
//S盒压缩
static void S(const int input[48],int output[32],int table[8][4][16])
{
    
    
    int i=0,j=0,INT[8];
    for(;i<48;i+=6,j++)//48->32
      INT[j]=table[j][(input[i]<<1)+(input[i+5])][(input[i+1]<<3)+(input[i+2]<<2)+(input[i+3]<<1)+(input[i+4])];//(<<i)==(*2^i)
    for(j=0;j<8;j++)
     for(i=0;i<4;i++)
     output[4*j+3-i]=(INT[j]>>i)&1;//将十进制转为二进制 
};
//完成DES算法轮变换,就是f函数的内部实现,就是一个异或而已
static void F_func(int input[32],int output[32], int subkey[48])
{
    
    
    int len=48, temp[48]={
    
    0},temp_1[32]={
    
    0};
    Change(input,temp,E_Table,48);//E扩展:32->48
    Xor(temp,subkey,len);//与密钥异或 
    S(temp,temp_1,S_Box);//S盒:48->32
    Change(temp_1,output,P_Table,32);//P盒:位数不变
};
//秘钥循环左移
static void RotateL(const int input[28],int output[28], int leftCount)
{
    
    
    int len=28;
    for(int i=0;i<len;i++)
     output[i]=input[(i+leftCount)%len];
};
//子密钥生成
static void subKey_fun(const int input[64],int Subkey[16][48])
{
    
    //注意输入和输出的位数,int只存放01,密钥为18位16轮
    int loop=1,loop_2=2;
    int c[28],d[28],pc_1[56]={
    
    0},pc_2[16][56]={
    
    0},rotatel_c[16][28]={
    
    0},rotatel_d[16][28]={
    
    0};
    Change(input,pc_1,PC1_Table,56);//置换选择1,转为56位,去掉了奇偶校验位 
    for(int i=0;i<28;i++){
    
    
        c[i]=pc_1[i];d[i]=pc_1[i+28];//分为两组,各28位 
    }
    int leftCount=0;
    for(int i=1;i<17;i++)//循环左移 
	{
    
    
        if(i==1||i==2||i==9||i==16) leftCount+=loop;//左移一位
        else  leftCount+=loop_2;//左移两位
        RotateL(c,rotatel_c[i-1],leftCount);
        RotateL(d,rotatel_d[i-1],leftCount);
    }
    for(int i=0;i<16;i++)//合并为56位 
        for(int j=0;j<28;j++)
		{
    
    
            pc_2[i][j]=rotatel_c[i][j];
            pc_2[i][j+28]=rotatel_d[i][j];
        }
    for(int i=0;i<16;i++)//置换选择2,变为48位 
        Change(pc_2[i],Subkey[i],PC2_Table,48);
};
//加密实现
static void  DES_Efun(char input[8],char key_in[8],int output[64])
{
    
    
    int Ip[64]={
    
    0};//存储初始置换后的矩阵
    int output_1[64]={
    
    0},subkeys[16][48],chartobit[64]={
    
    0},key[64],l[17][32],r[17][32];
    CharToBit(input,chartobit);//把明文转换为64个二进制数
    Change(chartobit,Ip,IP_Table,64);//IP初始置换
    CharToBit(key_in,key);//把密钥转换为64个二进制数
    subKey_fun(key,subkeys);//子密钥生成 
    for(int i=0;i<32;i++)//把IP分为左右两边 
	{
    
    
        l[0][i]=Ip[i];
        r[0][i]=Ip[32+i];
    }
    for(int j=1;j<=16;j++)
	{
    
    //前16轮的操作:Li=Ri-1  Ri=Li-1 ^ F(Ri-1,Ki) 
        for(int k=0;k<32;k++)
            l[j][k]=r[j-1][k];
        F_func(r[j-1],r[j],subkeys[j-1]);//F函数内部实现 
        Xor(r[j],l[j-1],32);//实现的结果和Li-1异或 
    }
    for(int k=0;k<32;k++)//最后一轮:交换l,r 
       swap(r[16][k],l[16][k]); 
    for(int i=0;i<32;i++)//将l,r合并 
	{
    
    
        output_1[i]=l[16][i];
        output_1[32+i]=r[16][i];
    }
    Change(output_1,output,IPR_Table,64);//IP逆初始置换 
};
//解密实现
static void  DES_Dfun(int input[64],char key_in[8],char output[8])
{
    
    
    int Ip[64]={
    
    0};//存储初始置换后的矩阵
    int output_1[64]={
    
    0},output_2[64]={
    
    0},subkeys[16][48];
    //int chartobit[64]={0};
    int key[64],l[17][32],r[17][32];
    Change(input,Ip,IP_Table,64);//IP初始置换
    CharToBit(key_in,key);//把密钥转换为64个二进制数
    subKey_fun(key,subkeys);//子密钥生成 
    for(int i=0;i<32;i++)//把IP分为左右两边
	{
    
    
        l[0][i]=Ip[i];
        r[0][i]=Ip[32+i];
    }
    for(int j=1;j<=16;j++)
	{
    
    //前16轮的操作:Li=Ri-1  Ri=Li-1 ^ F(Ri-1,Ki) 
        for(int k=0;k<32;k++)
            l[j][k]=r[j-1][k];
        //子密钥相反顺序 
        F_func(r[j-1],r[j],subkeys[16-j]);//F函数内部实现,就是密钥使用顺序换了 
        Xor(r[j],l[j-1],32);//实现的结果和Li-1异或 
    }
    for(int k=0;k<32;k++)//最后一轮:交换l,r 
       swap(r[16][k],l[16][k]); 
    for(int i=0;i<32;i++)//将l,r合并 
	{
    
    
        output_1[i]=l[16][i];
        output_1[32+i]=r[16][i];
    }
    Change(output_1,output_2,IPR_Table,64);//IP逆初始置换 
    BitToChar(output_2,output);//将二进制转为字符串 
};
int main()
{
    
    
	int X;
    cout<<"功能选择:加密(1),解密(2),退出(3)"<<endl;
    cout<<"请输入X:"; 
	while(cin>>X&&X!=3)
	{
    
    
	  int output[64]={
    
    0};
      string s;
      char key[9]={
    
    0},S[9]={
    
    0};
      getline(cin,s);
	  cout<<"请输入待处理的串(不足以0填补):"<<endl;
      getline(cin,s);
      cout<<"请输入密钥(只取前8位):"<<endl;
      gets(key);
      for(int i=0;i<s.length();i++)
       if(s[i]==' ') s.erase(s.begin()+i);
      cout<<"结果:"<<endl; 
	  if(X==1)
	  {
    
    
	  	for(int i=0;i<s.length();i+=8)
        {
    
    
    	 for(int j=0;j<8;j++) S[j]=s[i+j];//截取8个字符 
         DES_Efun(S,key,output);//加密 
         for(int i=0;i<64;i++)
    	 {
    
    
		  if(i%4==0) cout<<" ";
		  cout<<output[i];
         }
        }
       }
       else
	   {
    
    
	     for(int i=0;i<s.length();i+=64)
	     {
    
    
	      for(int j=0;j<64;j++) output[j]=s[i+j]-'0';//截取64位字符串 
	      DES_Dfun(output,key,S);//解密 
          for(int i=0;i<8;i++) cout<<S[i];   
		 }
	   } 
       cout<<endl<<"请输入X:";
	}
    return 0;
}
//1
//明文:asdfghjkl
//密钥:zxcvbn
// 0101 0001 1100 1111 1001 1001 1000 1100 1010 1101 1010 1010 1111 1101 1111 1101 1011 0011 1110 0001 0101 1011 0010 0110 0010 0010 1111 0010 0001 0110 0010 1010

3.2 DES-ECB 3.3 DES-CBC 3.4 DES-CFB 3.5 DES-OFB 3.6 DES-CTR

# -*- coding: utf-8 -*-
import re
import base64
import sys

# 密钥pc1置换
pc1_ = (
    57, 49, 41, 33, 25, 17, 9,
    1, 58, 50, 42, 34, 26, 18,
    10, 2, 59, 51, 43, 35, 27,
    19, 11, 3, 60, 52, 44, 36,
    63, 55, 47, 39, 31, 23, 15,
    7, 62, 54, 46, 38, 30, 22,
    14, 6, 61, 53, 45, 37, 29,
    21, 13, 5, 28, 20, 12, 4
)

# 每轮循环左移位数
left_shift_ = (
    1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
)

# 密钥pc2置换
pc2_ = (
    14, 17, 11, 24, 1, 5, 3, 28,
    15, 6, 21, 10, 23, 19, 12, 4,
    26, 8, 16, 7, 27, 20, 13, 2,
    41, 52, 31, 37, 47, 55, 30, 40,
    51, 45, 33, 48, 44, 49, 39, 56,
    34, 53, 46, 42, 50, 36, 29, 32
)

# 初始置换IP
ip_ = (
    58, 50, 42, 34, 26, 18, 10, 2,
    60, 52, 44, 36, 28, 20, 12, 4,
    62, 54, 46, 38, 30, 22, 14, 6,
    64, 56, 48, 40, 32, 24, 16, 8,
    57, 49, 41, 33, 25, 17, 9, 1,
    59, 51, 43, 35, 27, 19, 11, 3,
    61, 53, 45, 37, 29, 21, 13, 5,
    63, 55, 47, 39, 31, 23, 15, 7
)

# 扩展变换
e_box_ = (
    32, 1, 2, 3, 4, 5, 4, 5,
    6, 7, 8, 9, 8, 9, 10, 11,
    12, 13, 12, 13, 14, 15, 16, 17,
    16, 17, 18, 19, 20, 21, 20, 21,
    22, 23, 24, 25, 24, 25, 26, 27,
    28, 29, 28, 29, 30, 31, 32, 1
)

# S 盒
s_box_ = [
    # S1
    [[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7],
     [0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8],
     [4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0],
     [15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13]],
    # S2
    [[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10],
     [3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5],
     [0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15],
     [13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9]],
    # S3
    [[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8],
     [13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1],
     [13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7],
     [1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12]],
    # S4
    [[7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15],
     [13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9],
     [10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4],
     [3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14]],
    # S5
    [[2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9],
     [14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6],
     [4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14],
     [11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3]],
    # S6
    [[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11],
     [10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8],
     [9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6],
     [4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13]],
    # S7
    [[4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1],
     [13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6],
     [1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2],
     [6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12]],
    # S8
    [[13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7],
     [1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2],
     [7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8],
     [2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11]]
]

# P-盒置换
p_box_ = (
    16, 7, 20, 21, 29, 12, 28, 17,
    1, 15, 23, 26, 5, 18, 31, 10,
    2, 8, 24, 14, 32, 27, 3, 9,
    19, 13, 30, 6, 22, 11, 4, 25
)

# 末尾IP逆置换
inverse_ip_ = (
    40, 8, 48, 16, 56, 24, 64, 32,
    39, 7, 47, 15, 55, 23, 63, 31,
    38, 6, 46, 14, 54, 22, 62, 30,
    37, 5, 45, 13, 53, 21, 61, 29,
    36, 4, 44, 12, 52, 20, 60, 28,
    35, 3, 43, 11, 51, 19, 59, 27,
    34, 2, 42, 10, 50, 18, 58, 26,
    33, 1, 41, 9, 49, 17, 57, 25
)


# 字符串转2进制
def str2bin(text):
    res = ''
    for i in text:
        tmp = bin(ord(i))[2:].zfill(8)
        res += tmp
    return res
# 2进制转字符串
def bin2str(bin_text):
    res = ""
    tmp = re.findall(r'.{8}', bin_text)
    for i in tmp:
        res += chr(int(i, 2))
    return res
# 字符串转16进制
def str2hex(text):
    res = ''
    for ch in text:
        tmp = hex(ord(ch))[2:].zfill(2)
        res += tmp
    return res
# 16进制转字符串
def hex2str(hex_text):
    res = ''
    tmp = re.findall(r'.{2}', hex_text)
    for i in tmp:
        res += chr(int('0x' + i, 16))
    return res


# 预处理保证输入的密钥长度位为64位
def key_process(key):
    # 小于64位补0
    if len(key) < 64:
        key += '0' * (64 - len(key))
    # 大于64位截断
    elif len(key) > 64:
        key = key[:64]
    return key


# 预处理保证输入的明文长度位数为num的倍数,否则在后面补0
def message_process(message, num):
    # 不是num的倍数,则补0
    if len(message) % num != 0:
        message += '0' * (num - (len(message) % num))
    return message


# PC-1盒置换: 64位 -> 56位
def pc_1(key):
    res = ''
    for i in pc1_:
        res += key[i - 1]
    return res


# PC-2盒置换: 56位 -> 48位
def pc_2(key):
    res = ''
    for i in pc2_:
        res += key[i - 1]
    return res


# 循环左移num位
def rol(key, num):
    return key[num:] + key[:num]


# 16论迭代得到密钥列表
def get_key(key):
    key_list = []
    pc1_output = pc_1(key)  # pc1置换
    c = pc1_output[:28]
    d = pc1_output[28:]
    # 循环左移16轮迭代
    for i in left_shift_:
        c = rol(c, i)
        d = rol(d, i)
        key = pc_2(c + d)  # pc2置换得到一个密钥
        key_list.append(key)
    return key_list


# 初始IP置换
def ip(message):
    res = ''
    for i in ip_:
        res += message[i - 1]
    return res


# 末尾IP逆置换
def ip_inverse(message):
    res = ''
    for i in inverse_ip_:
        res += message[i - 1]
    return res


# 扩展置换(E盒): 32位 -> 48位
def e_box(message):
    res = ''
    for i in e_box_:
        res += message[i - 1]
    return res


# 密钥加: 48位^48位
def xor(message, key):
    res = ''
    for i in range(len(message)):
        res += str(int(message[i]) ^ int(key[i]))
    return res


# 代换盒(S盒): 48位 -> 32位
def s_box(message):
    res = ''
    box_index = 0
    for i in range(0, len(message), 6):
        block = message[i:i + 6]  # 6位为一个子块
        row = int(block[0] + block[5], 2)
        col = int(block[1] + block[2] + block[3] + block[4], 2)  # 其余4位确定列号
        out = bin(s_box_[box_index][row][col])[2:]  # 查表得到输出并转为2进制
        if len(out) != 4:  # 将输出补全到4位
            out = '0' * (4 - len(out)) + out
        res += out
        box_index += 1
    return res


# 置换运算(P盒): 32位 -> 32位
def p_box(message):
    res = ''
    for i in p_box_:
        res += message[i - 1]
    return res


# F函数(EBox -> XOR -> SBox -> PBox): 32位->32位
def f_func(message, key):
    e_out = e_box(message)  # 扩展置换
    xor_out = xor(e_out, key)  # 密钥加
    s_out = s_box(xor_out)  # 代换盒
    p_out = p_box(s_out)  # 置换运算
    return p_out


def des_encrypt(message, key):
    """
    DES加密函数
    :param message: 明文(不大于64位2进制)
    :param key: 密钥(任意2进制,补0或截断至64位)
    :return: 密文(64位2进制)
    """
    message = message_process(message, 64)  # 对明文进行预处理
    key = key_process(key)   # 对密钥进行预处理
    key_list = get_key(key)  # 密钥编排得到16组子密钥
    # 初始IP置换
    ip_out = ip(message)
    # L0||R0 = IP <64位密文>
    left_part = ip_out[:32]
    right_part = ip_out[32:]
    # 15轮相同迭代
    for i in range(15):
        left_temp = left_part
        right_temp = right_part
        # L_i = R_i-1
        left_part = right_part
        # R_i = L_i-1^F(R_i-1, K_i)
        right_part = xor(left_temp, f_func(right_temp, key_list[i]))
    # 第16轮迭代有所不同(L_16 = L_15^F(R_15, K_16); R_16 = R_15)
    left_last = xor(left_part, f_func(right_part, key_list[15]))
    right_last = right_part
    # IP逆置换
    cipher = ip_inverse(left_last + right_last)
    return cipher


def des_decrypt(cipher, key):
    """
    DES解密函数
    :param cipher: 密文(64位2进制)
    :param key: 密钥(任意2进制,后续补0或截断至64位)
    :return: 明文(64位2进制)
    """
    key = key_process(key)  # 对密钥进行预处理(正确的cipher位数应该是64的倍数,无需处理)
    key_list_inverse = get_key(key)[::-1]  # 与加密时的密钥顺序相反
    # IP置换
    ip_out = ip(cipher)
    # L16||R16 = IP <64位密文>
    left_part = ip_out[:32]
    right_part = ip_out[32:]
    # 15轮相同迭代
    for i in range(15):
        left_temp = left_part
        right_temp = right_part
        # L_i-1 = R_i
        left_part = right_part
        # R_i-1 = L_i^F(R_i, K_i)
        right_part = xor(left_temp, f_func(right_temp, key_list_inverse[i]))
    # 第16轮迭代有所不同(L_0 = L_1^F(R_1, K_1); R_1 = R_1)
    left_last = xor(left_part, f_func(right_part, key_list_inverse[15]))
    right_last = right_part
    # IP逆置换
    message = ip_inverse(left_last + right_last)
    return message.strip("\x00")


def des_ecb_encrypt(message, key, output_mode='h'):
    message_bin = message_process(str2bin(message), 64)
    # 将密钥转为2进制
    key_bin = str2bin(key)
    # 将明文分组
    message_list = re.findall(r'.{64}', message_bin)
    cipher_bin = ''
    for i in message_list:
        cipher_bin += des_encrypt(i, key_bin)

    if output_mode == 'H' or output_mode == 'h':
        cipher = str2hex(bin2str(cipher_bin))
    elif output_mode == 'B' or output_mode == 'b':
        cipher = base64.b64encode(bin2str(cipher_bin).encode('latin')).decode('latin')
    return cipher


def des_ecb_decrypt(cipher, key, input_mode='b'):
    if input_mode == 'h' or input_mode == 'H':
        cipher_bin = str2bin(hex2str(cipher))
    elif input_mode == 'b' or input_mode == 'B':
        cipher_bin = str2bin(base64.b64decode(cipher).decode('latin'))
    # 将密钥转为2进制
    key_bin = str2bin(key)
    # 将密文分组
    cipher_list = re.findall(r'.{64}', cipher_bin)
    message_bin = ''
    for i in cipher_list:
        message_bin += des_decrypt(i, key_bin)
    # 明文2进制转字符串
    message = bin2str(message_bin).strip("\x00")
    return message


def des_cbc_encrypt(message, key, iv, output_mode='h'):
    # 将密钥转为2进制
    key_bin = str2bin(key)
    # iv处理方式与key相同(少于8字节补0,大于8字节截断)
    iv_bin = key_process(str2bin(iv))
    # 将明文进行预处理
    message_bin = message_process(str2bin(message), 64)
    # 将明文分组
    message_list = re.findall(r'.{64}', message_bin)
    cipher_bin = ''
    # 第一组的反馈即为iv
    c = iv_bin
    for i in message_list:
        # 与反馈进行异或
        m = xor(c, i)
        c = des_encrypt(m, key_bin)
        # 链接密文分组
        cipher_bin += c

    if output_mode == 'H' or output_mode == 'h':
        cipher = str2hex(bin2str(cipher_bin))
    elif output_mode == 'B' or output_mode == 'b':
        cipher = base64.b64encode(bin2str(cipher_bin).encode('latin')).decode('latin')
    return cipher


def des_cbc_decrypt(cipher, key, iv, input_mode='b'):
    # 将密钥转为2进制
    key_bin = str2bin(key)
    # 对iv进行处理
    iv_bin = key_process(str2bin(iv))
    # 密文转2进制
    if input_mode == 'h' or input_mode == 'H':
        cipher_bin = str2bin(hex2str(cipher))
    elif input_mode == 'b' or input_mode == 'B':
        cipher_bin = str2bin(base64.b64decode(cipher).decode('latin'))
    # 对密文进行分组
    cipher_list = re.findall(r'.{64}', cipher_bin)
    message_bin = ''
    for i in cipher_list:
        temp = des_decrypt(i, key_bin)
        m = xor(iv_bin, temp)
        message_bin += m
        # 保存当前密文分组,用于下一个分组的解密异或
        iv_bin = i
    # 明文转换为字符串
    message = bin2str(message_bin).strip("\x00")
    return message


def des_cfb_encrypt(message, key, iv, output_mode='h'):
    # 对参数进行预处理
    key_bin = str2bin(key)
    iv_bin = key_process(str2bin(iv))
    message_bin = message_process(str2bin(message), 8)
    # 对明文进行分组(8位一组)
    message_list = re.findall(r'.{8}', message_bin)
    cipher_bin = ''
    # 初始化移位寄存器
    reg = iv_bin
    for i in message_list:
        # 对寄存器64位进行加密
        enc_out = des_encrypt(reg, key_bin)
        # 选择加密结果的前8位与明文分组异或
        c = xor(i, enc_out[:8])
        # 寄存器左移8位,并在最右边填充前一密文分组
        reg = reg[8:] + c
        # 连接密文分组
        cipher_bin += c
    if output_mode == 'H' or output_mode == 'h':
        cipher = str2hex(bin2str(cipher_bin))
    elif output_mode == 'B' or output_mode == 'b':
        cipher = base64.b64encode(bin2str(cipher_bin).encode('latin')).decode('latin')
    return cipher


def des_cfb_decrypt(cipher, key, iv, input_mode='b'):
    # 参数预处理
    key_bin = str2bin(key)
    iv_bin = key_process(str2bin(iv))
    if input_mode == 'h' or input_mode == 'H':
        cipher_bin = str2bin(hex2str(cipher))
    elif input_mode == 'b' or input_mode == 'B':
        cipher_bin = str2bin(base64.b64decode(cipher).decode('latin'))
    # 对密文进行分组(8位一组)
    cipher_list = re.findall(r'.{8}', cipher_bin)
    message_bin = ''
    # 初始化移位寄存器
    reg = iv_bin
    for i in cipher_list:
        # 对移位寄存器进行加密
        enc_out = des_encrypt(reg, key_bin)
        # 选择加密结果的前8位与密文分组异或
        m = xor(i, enc_out[:8])
        # 寄存器左移8位,并在最右边填充前一密文分组
        reg = reg[8:] + i
        # 连接明文分组
        message_bin += m
    # 明文转换为字符串
    message = bin2str(message_bin).strip("\x00")
    return message


def des_ofb_encrypt(message, key, iv, output_mode='h'):
    key_bin = str2bin(key)
    iv_bin = key_process(str2bin(iv))
    message_bin = message_process(str2bin(message), 8)
    # 对明文进行分组(8位一组)
    message_list = re.findall(r'.{8}', message_bin)
    cipher_bin = ''
    # 初始化移位寄存器
    reg = iv_bin
    for i in message_list:
        # 对寄存器64位进行加密
        enc_out = des_encrypt(reg, key_bin)
        # 选择加密结果的前8位与明文分组异或
        c = xor(i, enc_out[:8])
        # 寄存器左移8位,并在最右边填充加密结果的前8位
        reg = reg[8:] + enc_out[:8]
        # 连接密文分组
        cipher_bin += c
    if output_mode == 'H' or output_mode == 'h':
        cipher = str2hex(bin2str(cipher_bin))
    elif output_mode == 'B' or output_mode == 'b':
        cipher = base64.b64encode(bin2str(cipher_bin).encode('latin')).decode('latin')
    return cipher


def des_ofb_decrypt(cipher, key, iv, input_mode='b'):
    # 参数预处理
    key_bin = str2bin(key)
    iv_bin = key_process(str2bin(iv))
    if input_mode == 'h' or input_mode == 'H':
        cipher_bin = str2bin(hex2str(cipher))
    elif input_mode == 'b' or input_mode == 'B':
        cipher_bin = str2bin(base64.b64decode(cipher).decode('latin'))
    # 对密文进行分组(8位一组)
    cipher_list = re.findall(r'.{8}', cipher_bin)
    message_bin = ''
    # 初始化移位寄存器
    reg = iv_bin
    for i in cipher_list:
        # 对移位寄存器进行加密
        enc_out = des_encrypt(reg, key_bin)
        # 选择加密结果的前8位与密文分组异或
        m = xor(i, enc_out[:8])
        # 寄存器左移8位,并在最右边填充加密结果的前8位
        reg = reg[8:] + enc_out[:8]
        # 连接明文分组
        message_bin += m
    # 明文转换为字符串
    message = bin2str(message_bin).strip("\x00")
    return message


def des_ctr_encrypt(message, key, nonce, output_mode='h'):
    # 参数预处理
    key_bin = str2bin(key)
    nonce_bin = key_process(str2bin(nonce))
    message_bin = message_process(str2bin(message), 64)
    # 明文分组
    message_list = re.findall(r'.{64}', message_bin)
    cipher_bin = ''
    # 初始化计数器
    counter = nonce_bin
    for i in message_list:
        enc_out = des_encrypt(counter, key_bin)
        cipher_bin += xor(i, enc_out)
        # 计数器加1(mod 2^64)
        counter = bin(int('0b' + counter, 2) + int('0b1', 2) % pow(2, 64))[2:].zfill(64)

    if output_mode == 'H' or output_mode == 'h':
        cipher = str2hex(bin2str(cipher_bin))
    elif output_mode == 'B' or output_mode == 'b':
        cipher = base64.b64encode(bin2str(cipher_bin).encode('latin')).decode('latin')
    return cipher


def des_ctr_decrypt(cipher, key, nonce, input_mode='b'):
    # 参数预处理
    key_bin = str2bin(key)
    nonce_bin = key_process(str2bin(nonce))
    if input_mode == 'h' or input_mode == 'H':
        cipher_bin = str2bin(hex2str(cipher))
    elif input_mode == 'b' or input_mode == 'B':
        cipher_bin = str2bin(base64.b64decode(cipher).decode('latin'))
    # 对密文进行分组(8位一组)
    cipher_list = re.findall(r'.{64}', cipher_bin)
    message_bin = ''
    # 初始化计数器
    counter = nonce_bin
    for i in cipher_list:
        enc_out = des_encrypt(counter, key_bin)
        message_bin += xor(i, enc_out)
        # 计数器加1(mod 2^64)
        counter = bin(int('0b' + counter, 2) + int('0b1', 2) % pow(2, 64))[2:].zfill(64)
    # 明文转换为字符串
    message = bin2str(message_bin).strip("\x00")
    return message


def main():
    while True:
        mode = input("\n请选择模式:\n[E]加密\t[D]解密\t[Q]退出\n")
        if mode == 'E' or mode == 'e':
            try:
                message = input("请输入信息:\n")
                key = input("请输入钥匙:\n")
                work_mode = input("请选择工作模式:\n[1]ECB\t[2]CBC\t[3]CFB\t[4]OFB\t[5]CTR\n")
                # ECB加密模式
                if work_mode == '1':
                    output_way = input("请选择输出方式:\n[B]Base64\t[H]Hex\n")
                    cipher = des_ecb_encrypt(message, key, output_way)
                    print("密文为:\n" + cipher)
                # CBC加密模式
                elif work_mode == '2':
                    iv = input("请输入IV:\n")
                    output_way = input("请选择输出方式:\n[B]Base64\t[H]Hex\n")
                    cipher = des_cbc_encrypt(message, key, iv, output_way)
                    print("密文为:\n" + cipher)
                # CFB加密模式
                elif work_mode == '3':
                    iv = input("请输入IV:\n")
                    output_way = input("请选择输出方式:\n[B]Base64\t[H]Hex\n")
                    cipher = des_cfb_encrypt(message, key, iv, output_way)
                    print("密文为:\n" + cipher)
                # OFB加密模式
                elif work_mode == '4':
                    iv = input("请输入IV:\n")
                    output_way = input("请选择输出方式:\n[B]Base64\t[H]Hex\n")
                    cipher = des_ofb_encrypt(message, key, iv, output_way)
                    print("密文为:\n" + cipher)
                # CTR加密模式
                elif work_mode == '5':
                    nonce = input("请输入nonce:\n")
                    output_way = input("请选择输出方式:\n[B]Base64\t[H]Hex\n")
                    cipher = des_ctr_encrypt(message, key, nonce, output_way)
                    print("密文为\n" + cipher)
            except:
                print("错误!")
                sys.exit()
        elif mode == 'D' or mode == 'd':
            try:
                cipher = input("请输入密文:\n")
                key = input("请输入钥匙:\n")
                work_mode = input("请选择工作模式:\n[1]ECB\t[2]CBC\t[3]CFB\t[4]OFB\t[5]CTR\n")
                # ECB解密模式
                if work_mode == '1':
                    input_way = input("请选择输入方式:\n[B]Base64\t[H]Hex\n")
                    message = des_ecb_decrypt(cipher, key, input_way)
                    print("消息是:\n" + message)
                # CBC解密模式
                elif work_mode == '2':
                    iv = input("请输入IV:\n")
                    input_way = input("请选择输入方式:\n[B]Base64\t[H]Hex\n")
                    message = des_cbc_decrypt(cipher, key, iv, input_way)
                    print("消息是:\n" + message)
                # CFB解密模式
                elif work_mode == '3':
                    iv = input("请输入IV:\n")
                    input_way = input("请选择输入方式:\n[B]Base64\t[H]Hex\n")
                    message = des_cfb_decrypt(cipher, key, iv, input_way)
                    print("消息是:\n" + message)
                # CFB解密模式
                elif work_mode == '4':
                    iv = input("请输入IV:\n")
                    input_way = input("请选择输入方式:\n[B]Base64\t[H]Hex\n")
                    message = des_ofb_decrypt(cipher, key, iv, input_way)
                    print("消息是:\n" + message)
                # CTR解密模式
                elif work_mode == '5':
                    nonce = input("请输入nonce:\n")
                    input_way = input("请选择输入方式:\n[B]Base64\t[H]Hex\n")
                    message = des_ctr_decrypt(cipher, key, nonce, input_way)
                    print("消息是:\n" + message)
            except:
                print("错误!")
                sys.exit()
        elif mode == 'Q' or mode == 'q':
            break
        else:
            continue

if __name__ == '__main__':
    main()

3.7 模式选用和比较
**4.RSA加密

from random import randint
import sys
import libnum
import time

# 设置最大递归深度,否则在fast_mod中可能会报错
sys.setrecursionlimit(2147483647)

def extended_gcd(a, b):#扩展欧几里得
    if b == 0:
        return a, 1, 0
    else:
        g, x, y = extended_gcd(b, a % b)
        return g, y, x - (a // b) * y

def mod_inverse(a, m):#计算模逆
    g, x, y = extended_gcd(a, m)  # ax + my = 1
    # 若a,m不互素,则不可逆
    if g != 1:
        raise Exception(str(a) + ' is not invertible!')
    else:
        return x % m

def fast_mod(a, b, p):#快速幂 a^b %p
    a = a % p
    c = 1
    while b!=0:
        if b & 1:
            c = (c * a) % p
        b >>= 1
        a = (a * a) % p
    return c

def miller_rabin(n, k=10):#素性检验,次数10
    if n % 2 == 0:
        return False
    s, t = 0, n - 1
    while t % 2 == 0:# 将n-1分解为(2^s)t
        s += 1
        t //= 2
    for i in range(k): # 进行k次检验
        b = randint(2, n - 2)
        x = fast_mod(b, t, n)
        if x == 1 or x == n - 1:
            continue
        else:
            flag = 0
            for r in range(s):
                x = fast_mod(x, 2, n)
                if x == n - 1:
                    flag = 1
                    break
            if flag == 0:
                return False
    return True

def get_prime(n):#得到一个n位的素数
    while True:
        num = randint(1,9)
        for i in range(n - 1):
            x = randint(0, 9)
            num = num*10 + x
        if miller_rabin(num):
            return num

def get_keys(len):
    len = int(len)
    while True:
        p = get_prime(len)
        q = get_prime(len)
        if p == q:
            continue
        N = p * q
        phiN = (p - 1) * (q - 1)
        while True:
            e = randint(2, phiN - 1)
            if extended_gcd(e, phiN)[0] == 1:
                d = mod_inverse(e, phiN)# 计算私钥
                if d*e%phiN==1:#确保互逆
                    return e, N, d

def main():
    while True:
        mode = input("\n请选择模式:1:加密\t0:解密\n")
        if mode == '1':
            m = input("请输入明文:\n")
            len = input("请输入q,p位数:\n")
            e, n, d = get_keys(len)
            print("公钥e为: " + str(e))
            print("公钥n为: " + str(n))
            print("私钥d为: " + str(d))
            print("明文为: " + m)
            m = libnum.s2n(m)
            c = fast_mod(m, int(e), int(n))
            print("密文为(10进制): " + str(c))
        elif mode == '0':
            c = input("请输入密文(10进制):\n")
            d = input("请输入私钥d:\n")
            n = input("请输入公钥n:\n")
            m = fast_mod(int(c), int(d),int(n))
            m = libnum.n2s(m)
            print("明文为: " + str(m))
        else:
            continue

if __name__ == '__main__':
    main()

5.Hash函数(MD5)

import math
import re
import sys

# 初始链接变量(小端序表示)
IV_A, IV_B, IV_C, IV_D = (0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476)

# 每轮步函数中循环左移的位数
shift_ = ((7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22),
          (5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20),
          (4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23),
          (6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21))

# 每步选择m得索引
M_index_ = ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
            (1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12),
            (5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2),
            (0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9))


# 非线性函数F、G、H、I
def F(x, y, z): return (x & y) | (~x & z)


def G(x, y, z): return (x & z) | (y & ~z)


def H(x, y, z): return x ^ y ^ z


def I(x, y, z): return y ^ (x | (~z))


# 生成伪随机常数
def T(i): return math.floor(abs(math.sin(i)) * pow(2, 32))


# 二进制的循环左移
def rol(x, n): return (x << n) | (x >> 32 - n)


# 模32加
def mod_add(x, y):
    return (x + y) % pow(2, 32)


# 字符串转2进制
def str2bin(text):
    res = ''
    for i in text:
        tmp = bin(ord(i))[2:].zfill(8)
        res += tmp
    return res


# 大端序转小端序(16进制)
def hex2little(x):
    res = re.findall(r'.{2}', x)[::-1]
    res = ''.join(res)
    return res


# 大端序转小端序(2进制)
def bin2little(x):
    res = re.findall(r'.{8}', x)[::-1]
    res = ''.join(res)
    return res


# 对消息进行填充
def message_padding(m):
    # 计算附加的64为长度(小端序表示)
    len_padding = bin2little(bin(len(m))[2:].zfill(64))
    m += '1'
    while len(m) % 512 != 448:
        m += '0'
    return m + len_padding


# 压缩函数(对每个512bit分组进行处理)
def compress_func(a, b, c, d, m):
    """
    压缩函数函数,对每512bit得分组进行处理,包括4轮,每轮16步
    :param a, b, c, d:  输入链接变量(即前一个分组的输出链接变量)
    :param m: 512bit的消息分组
    :return: A,B,C,D 输出链接变量
    """
    # 对每一分组的初始链接变量进行备份
    A, B, C, D = a, b, c, d
    # 将512bit分为16组,每组32bit
    m_list_32 = re.findall(r'.{32}', m)
    # 每个分组经过4轮函数
    for round_index in range(4):
        # 每轮有16步
        for step_index in range(16):
            # 对每一步的链接变量进行备份
            AA, BB, CC, DD = A, B, C, D
            # 每一轮选择不同的非线性函数
            if round_index == 0:
                func_out = F(B, C, D)
            elif round_index == 1:
                func_out = G(B, C, D)
            elif round_index == 2:
                func_out = H(B, C, D)
            else:
                func_out = I(B, C, D)
            A, C, D = D, B, C
            # B模加非线性函数的输出
            B = mod_add(AA, func_out)
            # 模加消息分组(注意为大端序)
            B = mod_add(B, int(bin2little(m_list_32[M_index_[round_index][step_index]]), 2))
            # print(type(B))
            # 模加伪随机常数
            B = mod_add(B, T(16 * round_index + step_index + 1))
            # 循环左移s位
            B = rol(B, shift_[round_index][step_index])
            # 模加BB
            B = mod_add(B, BB)
    # 与该分组的初始链接变量异或
    A = mod_add(A, a)
    B = mod_add(B, b)
    C = mod_add(C, c)
    D = mod_add(D, d)

    return A, B, C, D


def md5(m):
    # 转为2进制
    m = str2bin(m)
    # 消息填充
    m = message_padding(m)
    # 对消息分组,每组512位
    m_list_512 = re.findall(r'.{512}', m)
    # 初始链接变量
    A, B, C, D = IV_A, IV_B, IV_C, IV_D
    # 对每512bit进行分组处理,前一组的4个输出连接变量作为下一组的4个输入链接变量
    for i in m_list_512:
        A, B, C, D = compress_func(A, B, C, D, i)
    # 把最后一次的分组4个输出连接变量再做一次大端小端转换
    A = hex2little(hex(A)[2:]).zfill(8)
    B = hex2little(hex(B)[2:]).zfill(8)
    C = hex2little(hex(C)[2:]).zfill(8)
    D = hex2little(hex(D)[2:]).zfill(8)
    # 拼接到一起的得到最终的md5值
    return A + B + C + D


def main():
    while True:
        try:
            message = input("\n请输入要进行md5的内容:\n")
            if len(str2bin(message)) > pow(2, 64):
                print("最多只能处理2^64位!\n")
                continue
            digest = md5(message)
            print("\nmd5后的散列值为:\n" + digest)
        except:
            print("出错了!")
            sys.exit()


if __name__ == '__main__':
    main()

6.综合实验**

from random import randint
from pyDes import des, CBC, PAD_PKCS5
import binascii
import sys
import libnum
import time
import math
import re
import os
import random
import string
import socket
import libnum
from base64 import b64encode
# 设置最大递归深度,否则在fast_mod中可能会报错
sys.setrecursionlimit(2147483647)

IV_A, IV_B, IV_C, IV_D = (0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476)# 初始值,大端序

shift = ((7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22),
          (5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20),
          (4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23),
          (6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21))# 每轮步循环左移的位数

index= ((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
            (1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12),
            (5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2),
            (0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9))#每轮以不同次序使用16个字

#4轮非线性函数
def F(x, y, z): return (x & y) | (~x & z)
def G(x, y, z): return (x & z) | (y & ~z)
def H(x, y, z): return x ^ y ^ z
def I(x, y, z): return y ^ (x | (~z))

def T(i): return math.floor(pow(2, 32) * abs(math.sin(i)))# 生成伪随机常数

def rol(x, n): return (x << n) | (x >> 32 - n)# 二进制的循环左移

def mod_add(x, y):# 模2^32加
    return (x + y) % pow(2, 32)

def str2bin(text):# 字符串转2进制
    res = ''
    for i in text:
        tmp = bin(ord(i))[2:].zfill(8)
        res += tmp
    return res

#大端模式:高字节保存在内存的低地址,小端模式:高字节保存在内存的高地址
def hex2little(x):# 大端序转小端序(16进制)
    res = re.findall(r'.{2}', x)[::-1]
    res = ''.join(res)
    return res

def bin2little(x):# 大端序转小端序(2进制)
    res = re.findall(r'.{8}', x)[::-1]
    res = ''.join(res)
    return res

def message_padding(m):# 消息填充
    m += '1'
    while len(m) % 512 != 448:
        m += '0'
    len_add = bin2little(bin(len(m))[2:].zfill(64))
    return m + len_add

def solve(a, b, c, d, m):#对每个512bit分组进行处理
    A, B, C, D = a, b, c, d
    m_list_32 = re.findall(r'.{32}', m)# 将512bit分为16组,每组32bit
    for i in range(4):#4轮,每轮16步
        for j in range(16):
            AA, BB, CC, DD = A, B, C, D
            # 每一轮选择不同的非线性函数
            if i == 0:
                x = F(B, C, D)
            elif i == 1:
                x = G(B, C, D)
            elif i == 2:
                x = H(B, C, D)
            else:
                x = I(B, C, D)
            A, C, D = D, B, C
            B = mod_add(AA, x)
            B = mod_add(B, int(bin2little(m_list_32[index[i][j]]), 2))# 模加消息分组,大端序转小端序2进制
            B = mod_add(B, T(16 * i + j + 1))# 模加伪随机常数, +1:下标从0开始
            B = rol(B, shift[i][j])# 循环左移s位
            B = mod_add(B, BB)
    A = mod_add(A, a)
    B = mod_add(B, b)
    C = mod_add(C, c)
    D = mod_add(D, d)
    return A, B, C, D

def md5(m):
    m = str2bin(m)# 转为2进制
    m = message_padding(m)# 消息填充
    m_list_512 = re.findall(r'.{512}', m)#消息分组,每组512位
    A, B, C, D = IV_A, IV_B, IV_C, IV_D# 初始值
    for i in m_list_512:# 对每组512位进行分组处理
        A, B, C, D = solve(A, B, C, D, i)
    # 把最后一次的分组4个输出连接变量再做一次大端小端转换,16进制
    A = hex2little(hex(A)[2:]).zfill(8)
    B = hex2little(hex(B)[2:]).zfill(8)
    C = hex2little(hex(C)[2:]).zfill(8)
    D = hex2little(hex(D)[2:]).zfill(8)
    return A + B + C + D#拼接

def extended_gcd(a, b):#扩展欧几里得
    if b == 0:
        return a, 1, 0
    else:
        g, x, y = extended_gcd(b, a % b)
        return g, y, x - (a // b) * y

def mod_inverse(a, m):#计算模逆
    g, x, y = extended_gcd(a, m)  # ax + my = 1
    # 若a,m不互素,则不可逆
    if g != 1:
        raise Exception(str(a) + ' is not invertible!')
    else:
        return x % m

def fast_mod(a, b, p):#快速幂 a^b %p
    a = a % p
    c = 1
    while b!=0:
        if b & 1:
            c = (c * a) % p
        b >>= 1
        a = (a * a) % p
    return c

def miller_rabin(n, k=10):#素性检验,次数10
    if n % 2 == 0:
        return False
    s, t = 0, n - 1
    # 将n-1分解为(2^s)t
    while t % 2 == 0:
        s += 1
        t //= 2
    # 进行k次检验
    for i in range(k):
        b = randint(2, n - 2)
        x = fast_mod(b, t, n)
        if x == 1 or x == n - 1:
            continue
        else:
            flag = 0
            for r in range(s):
                x = fast_mod(x, 2, n)
                if x == n - 1:
                    flag = 1
                    break
            if flag == 0:
                return False
    return True

def get_prime(n):#得到一个n位的素数
    while True:
        # 最高位为1,保证是n位
        num = randint(1,9)
        # 随机生成n-2位数
        for i in range(n - 1):
            x = randint(0, 9)
            num = num*10 + x
        if miller_rabin(num):
            return num

def get_keys(len):
    len = int(len)
    while True:
        p = get_prime(len)
        q = get_prime(len)
        if p == q:
            continue
        N = p * q
        phiN = (p - 1) * (q - 1)
        e = randint(2, phiN-1)
        if extended_gcd(e, phiN)[0] == 1:
            # 计算私钥
            d = mod_inverse(e, phiN)
            if d*e%phiN==1:#确保互逆
             return e, N, d

def RSA(mode,s,e,n,d):#对字符串s进行加解密(1:加密 0:解密)
    if mode == '1':
        print("明文为: " + s)
        s = libnum.s2n(s)
        s = fast_mod(s, int(e), int(n))
        print("密文为(10进制): " + str(s))
    elif mode == '0':
        d = input("请输入RSA私钥d:\n")
        n = input("请输入RSA公钥n:\n")
        s = fast_mod(int(s), int(d),int(n))
        s = libnum.n2s(s)
        print("明文为: " + str(s))

def get_des_param():#DES CBC:产生64位随机的key和IV
    while True:
        key = ''.join(random.sample(string.ascii_letters + string.digits, 8))
        IV = ''.join(random.sample(string.ascii_letters + string.digits, 8))
        if key != IV:
            break
    return key, IV

def des_encrypt(s,key,IV):
    secret_key = key
    iv = IV
    k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
    en = k.encrypt(s, padmode=PAD_PKCS5)
    return binascii.b2a_hex(en)


def des_descrypt(s,key,IV):
    secret_key = key
    iv = IV
    k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
    de = k.decrypt(binascii.a2b_hex(s), padmode=PAD_PKCS5)
    return de

def main():
    while True:
        try:
            while True:
                    #前期准备
                    key,IV = get_des_param()#DES CBC key,iv
                    len = input("请输入RSA q,p位数:\n")

                    #RSA公钥e,n 私钥d
                    Alice_e, Alice_n, Alice_d = get_keys(len)
                    Bob_e, Bob_n, Bob_d = get_keys(len)

                    print("Alice action:\n")
                    #RSA:用Bob的公钥加密key
                    KEY = libnum.s2n(key)
                    KEY = fast_mod(KEY, int(Bob_e), int(Bob_n))
                    print("加密后的key:" + str(KEY))

                    #文本DES
                    s = input("\n请输入待处理字符串:\n")
                    enc = des_encrypt(s,key,IV)
                    print("DES加密后的文本:" + str(enc))

                    #将文本hash
                    t = str(int(enc, 16))
                    m = md5(t)

                    #将hash值用Alice的私钥签名
                    sign = libnum.s2n(m)
                    sign = fast_mod(int(sign),int(Alice_d),int(Alice_n))
                    print("Alice签名为:" + str(sign))

                    ####Bob获得加密后的key,DES后的文本,和Alice的签名
                    print("\nBob action:\n")
                    # RSA:用Bob的私钥解密key
                    key = fast_mod(int(KEY), int(Bob_d), int(Bob_n))
                    key = libnum.n2s(key)
                    print("解密后的key:" + str(key))

                    # 将文本hash
                    t = str(int(enc, 16))
                    m = md5(t)
                    print("md5后的散列值为:" + str(m))

                    # 将签名用Alice的公钥处理
                    has = fast_mod(int(sign), int(Alice_e), int(Alice_n))
                    has = libnum.n2s(has)
                    print("签名处理后的值:" + str(has))
                    #用处理值与hash值进行比对,判断是否有篡改或者假签名
                    if(m != has):
                        print("篡改或者假签名")
                    else:
                        #将文本进行DES解密
                        des = des_descrypt(enc, key, IV)
                        print("解密后的文本:" + str(des))
        except:
            print("出错了!")
            sys.exit()

if __name__ == '__main__':
    main()

猜你喜欢

转载自blog.csdn.net/weixin_43540515/article/details/113329555
今日推荐