几个密码学的实验(DES RSA Vigenere)

实验一:RSA公钥密码体制的实现

1.实验目的
RSA公钥密码体制的实现
2.实验工具
1)Windows 系列操作系统;
2) python 编程环境。
3. 实验方案
(说明:需要有流程图、原理等)
在 RSA 算法中,n=pq;φ( n)=(p-1)(q-1);1<e<φ(n),且 gcd(φ(n),e)=1;d*e ≡1 modφ(n)。这些参数中,公开的有 n 和 e,保密的有 p、q 和 d。 设明文分组 m,则加密算法为 c≡m^e mod n 对密文分组 c 的的解密算法为 m≡c^d mod n

4.实验步骤
(说明:具体步骤,后面的实验结果最好对应这里每步都能看到)
1、选择 p、q两个超级大的质数 ,都是1024位,显得咱们的程序货真价实。
  2、令n = p * q。取 φ(n) =(p-1) * (q-1)。 计算与n互质的整数的个数。
  3、取 e ∈ 1 < e < φ(n) ,( n , e )作为公钥对
  4、令 ed mod φ(n) = 1,计算d,( n , d ) 作为私钥对。 计算d可以利用扩展欧几里的算法进行计算,非常简单,不超过5行代码就搞定。
  5、销毁 p、q。密文 = 明文 ^ e mod n , 明文 = 密文 ^ d mod n。
具体的代码的实现:

def gcd(a, b): #求最大公因子
  if b == 0:
    return a
  else:
    return gcd(b, a % b)


def ext_gcd(a, b):  #求逆元
  if b % a == 0:
    return 0
  for i in range(2,int(b/2)):
    if i * a % b == 1:
      return i
  return 0


def exp_mode(base, exponent, n):
  bin_array = bin(exponent)[2:][::-1]
  r = len(bin_array)
  base_array = []
  pre_base = base
  base_array.append(pre_base)
  for _ in range(r - 1):
    next_base = (pre_base * pre_base) % n
    base_array.append(next_base)
    pre_base = next_base
  a_w_b = __multi(base_array, bin_array)
  return a_w_b % n


def __multi(array, bin_array):
  result = 1
  for index in range(len(array)):
    a = array[index]
    if not int(bin_array[index]):
      continue
    result *= a
  return result

def gen_key(p, q):
  n = p * q
  fy = (p - 1) * (q - 1)   # 计算与n互质的整数个数 欧拉函数
  e = 3
  # generate d
  a = e
  b = fy
  x= ext_gcd(a, b)
  d = x
  # 返回:  公钥   私钥
  return  (n, e), (n, d)


##### 加密 m是被加密的信息 加密成为c
def encrypt(m, pubkey):
  n = pubkey[0]
  e = pubkey[1]
  c = exp_mode(m, e, n)
  return c
#解密 c是密文,解密为明文m
def decrypt(c, selfkey):
 n = selfkey[0]
   d = selfkey[1]
   m = exp_mode(c, d, n)
return m


if __name__ == "__main__":
  '''公钥私钥中用到的两个大质数p,q'''
  p = int(input("请输入第一个大质数:"))
  q = int(input("请输入第二个大质数:"))
  '''生成公钥私钥'''
  pubkey, selfkey = gen_key(p, q)
  '''需要被加密的信息转化成数字,长度小于秘钥n的长度,如果信息长度大于n的长度,那么分段进行加密,分段解密即可。'''
  m = int(input("请输入要加密的明文:"))
 # m = decrypt(c, selfkey)
  c = encrypt(m,pubkey)
  print(c)

用两个大素数11和23,明文165测试,得到密文110 测试成功
反之输入密文110 得到明文,测试成功

实验二:DES

1.实验目的
1)熟悉分组密码加密/解密算法的基本原理,加深对所提供的部分源程序的理解。
2)分析源程序中密码算法的加密/解密和子密钥生成等典型模块的主要功能,并对源程序加上注释。
3)在已提供的部分源程序的基础上,添加源程序缺省的部分。
4)对给定的消息分组进行加密/解密运算和验证。

2.实验工具
1)Windows 系列操作系统;
2) python 编程环境。
3. 实验方案
(说明:需要有流程图、原理等)
分组密码将明文分成一组一组,在密钥的控制下,经过加密变换生产一组一组的密文。具体而言,分组密码就是将明文消息列m1,m2,···,mi,···划分成等长的消息组(m1,m2,···,mn),(mn+1,mn+2,···,m2n),···, 在密钥k1,k2,···,ki的控制下按固定的加密算法一组一组进行加密,输出一组一组密文(c1,c2,···cl),(cl+1,cl+2,···,c2l),···。
下面的实验以DES算法为例。DES算法明文分组长为64bit,加密后得到64bit密文,输入初始种子密钥为64bit,第8、16、24、32、40、48、56、64为奇偶校验位,实际的密钥长为56bit。DES加密过程由三个阶段来完成:

  1. 初始置换IP,用于重排明文分组的64bit数据。
  2. 相同结构的16轮迭代,每轮中都有置换和代换运算,第16轮变换的输出分为左、右两半,并交换次序。
  3. 逆初始置换IP-1(为IP的逆)后,产生64bit的密文。
    4.实验步骤
    (说明:具体步骤,后面的实验结果最好对应这里每步都能看到)
#include <string.h>
#include <stdio.h>

class DES{
public:
	~DES() {}	//析构函数 

	void set_key(const unsigned char *);	//密钥扩展
	void en_ctransform(const unsigned char *,unsigned char *);    //加密变换
	void de_ctransform(const unsigned char *,unsigned char *);    //解密变换
private:
	bool enckey[16][48];//存放加密子密钥 
	bool deckey[16][48];//存放解密子密钥

	const static unsigned char IP_Table[64];
	//初置换 
	
	const static unsigned char IPR_Table[64];
	// 逆置换 
	
	const static unsigned char E_Table[48];
	//E表 
	
	const static unsigned char P_Table[32];
	//置换选择 
	
	const static unsigned char PC1_Table[56];
	//置换选择1
	
	const static unsigned char PC2_Table[48];
	//置换选择2
		
	const static unsigned char LOOP_Table[16];
	// 密钥位移(左移次数) 
	
	const static unsigned char S_Box[8][4][16];
	// S盒 
};

const unsigned char DES::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
};
// 初置换 

const unsigned char DES::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
};
// 逆初始置换 

const unsigned char DES::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
};
// E表 

const unsigned char DES::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
};
// 置换选择 

const unsigned char DES::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
};
//置换选择1

const unsigned char DES::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
};
//置换选择2 

const unsigned char DES::LOOP_Table[16] = {
	1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
};
// 密钥位移(左移次数) 

const unsigned char DES::S_Box[8][4][16] = {
	// 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
};

void chaifen(char byte,int a[64],int q){
	int i;
	for(i=0;i<8;i++){
		a[7-i+q]=byte & 1;
		byte>>=1;
		//把byte右移一位的值赋值给byte
	}
}

void DES::set_key( unsigned char const *yonghu_key/*用户输入的64位密钥首地址*/ ){
    //密钥扩展算法
	int arr[64];
	int ary[56];
	int i,curry=0;
	for(i=0;i<8;i++){
		chaifen(yonghu_key[i],arr,curry);
		curry=curry+8;
	}
		for(i=0;i<56;i++){
			ary[i]=arr[PC1_Table[i]-1];
		}
			for(i=0;i<16;i++){
				if(i==0 || i==1 || i==8 || i==15){
					int j,temp0,temp1;
					temp0=ary[0];temp1=ary[28];
						for(j=0;j<28;j++){
							ary[j]=ary[j+1];
							ary[j+28]=ary[j+29];
						}
				ary[27]=temp0;ary[55]=temp1;
			}
					else{
						int j,temp0,temp1;
						temp0=ary[0];temp1=ary[28];
							for(j=0;j<28;j++){
								ary[j]=ary[j+1];
								ary[j+28]=ary[j+29];
							}
						ary[27]=temp0;ary[55]=temp1;
						temp0=ary[0];temp1=ary[28];
							for(j=0;j<28;j++){
								ary[j]=ary[j+1];
								ary[j+28]=ary[j+29];
							}
						ary[27]=temp0;ary[55]=temp1;
					}
				int j;
				for(j=0;j<48;j++)
				enckey[i][j]=(bool)ary[PC2_Table[i]-1];
			}		
}


void DES::en_ctransform( const unsigned char *In /*待解密的64位数据首地址*/,unsigned char *Out ){
    //加密变换算法
	int arr[64];
	int ary[64];
	int i,j,curry=0;
	for(i=0;i<8;i++){
		chaifen(In[i],arr,curry);
		curry=curry+8;
	}
		for(i=0;i<64;i++){
		ary[i]=arr[IP_Table[i]-1];
		}

		int larr[32];
		int rarr[32];
			for(i=0;i<32;i++){
				larr[i]=ary[i];
				rarr[i]=ary[i+32];
			}
				for(i=0;i<16;i++){
					int temp[32];
					for(j=0;j<32;j++){
						temp[j]=larr[j];
						larr[j]=rarr[j];
					}
				int i0,j0,q;
				int e[48];
					for(i0=0;i0<48;i0++)
					e[i0]=rarr[E_Table[i0]-1];
					int w;
						for(w=0;w<48;w++){
							e[w]=(e[w]+enckey[i][w])%2;
						}

						for(j0=0;j0<8;j0++){
							int hang=e[j0*6]*2+e[j0*6+5];
							int lie=e[j0*6+1]*8+e[j0*6+2]*4+e[j0*6+3]*2+e[j0*6+4];
							int num=S_Box[j0][hang][lie];
								for(q=0;q<4;q++){
									rarr[j0*4+3-q]=num&1;
									num>>=1;
								}				
						}	
				int temp0[32];
				for(j=0;j<32;j++){
					temp0[j]=rarr[j];
				}
					for(j=0;j<32;j++){
				rarr[j]=temp0[P_Table[j]-1];
					}

						for(j=0;j<32;j++){
							rarr[j]=((rarr[j]+temp[j])%2);
						}
				}

		int temp[32];
		for(i=0;i<32;i++){
			temp[i]=larr[i];
			larr[i]=rarr[i];
			rarr[i]=temp[i];
		}
			for(i=0;i<32;i++){
				ary[i]=larr[i];
				ary[i+32]=rarr[i];
			}
				for(i=0;i<64;i++){
	 				arr[i]=ary[IPR_Table[i]-1];   	
				}

		for(i=0;i<8;i++){
			Out[i]=arr[i*8]*128+arr[i*8+1]*64+arr[i*8+2]*32+arr[i*8+3]*16+arr[i*8+4]*8+arr[i*8+5]*4+arr[i*8+6]*2+arr[i*8+7];
		}
}

void DES::de_ctransform( const unsigned char *In /*待加密的64位数据首地址*/, unsigned char *Out){
//解密变换算法
	int arr[64];
	int ary[64];
	int i,j,curry=0;
	

	for(i=0;i<8;i++){
		chaifen(In[i],arr,curry);
		curry+=8;
	}
		for(i=0;i<64;i++){
			ary[i]=arr[IP_Table[i]-1];
		}

	int larr[32];
	int rarr[32];
		for(i=0;i<32;i++){
			larr[i]=ary[i];
			rarr[i]=ary[i+32];
		}


			for(i=0;i<16;i++){
				int temp[32];
					for(j=0;j<32;j++){
						temp[j]=larr[j];
						larr[j]=rarr[j];
					}
				int i0,j0,q;
				int e[48];
					for(i0=0;i0<48;i0++)
						e[i0]=rarr[E_Table[i0]-1];
						int w;
							for(w=0;w<48;w++){
								e[w]=(e[w]+enckey[15-i][w])%2;
							}

			for(j0=0;j0<8;j0++){
				int hang=e[j0*6]*2+e[j0*6+5];
				int lie=e[j0*6+1]*8+e[j0*6+2]*4+e[j0*6+3]*2+e[j0*6+4];
				int num=S_Box[j0][hang][lie];
					for(q=0;q<4;q++){
						rarr[j0*4+3-q]=num&1;
						num>>=1;
					}
			}
			
			int temp0[32];
				for(j=0;j<32;j++){
				temp0[j]=rarr[j];
				}
					for(j=0;j<32;j++){
					rarr[j]=temp0[P_Table[j]-1];
					}
						for(j=0;j<32;j++){
							rarr[j]=((rarr[j]+temp[j])%2);
						}

	}
	int temp[32];
	for(i=0;i<32;i++){
		temp[i]=larr[i];
		larr[i]=rarr[i];
		rarr[i]=temp[i];
	}

			for(i=0;i<32;i++){
				ary[i]=larr[i];
				ary[i+32]=rarr[i];
			}
				for(i=0;i<64;i++){
					arr[i]=ary[IPR_Table[i]-1];   
			}
				for(i=0;i<8;i++){
					Out[i]=arr[i*8]*128+arr[i*8+1]*64+arr[i*8+2]*32+arr[i*8+3]*16+arr[i*8+4]*8+arr[i*8+5]*4+arr[i*8+6]*2+arr[i*8+7];
			}
}

int main(){
	unsigned int seq[8];
	unsigned char key[9];	//密钥 
	unsigned char plain[9];		//明文 
	unsigned char cipher[9];	//密文 
	char shuruzi[17];	//键盘输入的字符 
	char choice=' ';
	DES mydes;	//类 
	int i,j;
	int s; 

	while(true){
		do{
			printf("请选择:\n    1.加密\n    2.解密\n    3.退出\n");
			scanf("\n%c",&choice);
		}
			while(choice != '1' && choice != '2' && choice != '3');
		
			switch(choice){
			case '1':
			printf("请输入秘钥(长度=16):\n****************\n");
			scanf("%s",shuruzi);
			sscanf(shuruzi,"%2x%2x%2x%2x%2x%2x%2x%2x",&seq[0],&seq[1],&seq[2],&seq[3],&seq[4],&seq[5],&seq[6],&seq[7]);
			for(i=0;i<8;i++)
				key[i]=seq[i];
			//将输入的字符一个一个存到密钥数组中
			printf("\n");
			printf("请输入明文(长度=16):\n****************\n");
			scanf("%s",shuruzi);
			printf("\n");
			sscanf(shuruzi,"%2x%2x%2x%2x%2x%2x%2x%2x",&seq[0],&seq[1],&seq[2],&seq[3],&seq[4],&seq[5],&seq[6],&seq[7]);
				for(j=0;j<8;j++)
					plain[j]=seq[j];
			//将输入的字符一个一个存到明文数组中 
			
				mydes.set_key(key);
				mydes.en_ctransform(plain,cipher);
			 //调用加密算法函数完成加密
			  
					for(s=0;s<8;s++)
						seq[s]=cipher[s];
			printf("密文:\n%02x%02x%02x%02x%02x%02x%02x%02x\n",seq[0],seq[1],seq[2],seq[3],seq[4],seq[5],seq[6],seq[7]);
			//将密文数组中的字符存入缓存数组并输出 
			printf("\n");
			break;
			
			
		case '2':
			printf("请输入秘钥(长度=16):\n****************\n");
			scanf("%s",shuruzi);
			sscanf(shuruzi,"%2x%2x%2x%2x%2x%2x%2x%2x",&seq[0],&seq[1],&seq[2],&seq[3],&seq[4],&seq[5],&seq[6],&seq[7]);
			for(i=0;i<8;i++)
				key[i]=seq[i];
			//将输入的字符一个一个存到明文数组中 
			printf("\n");
			printf("请输入密文(长度=16):\n****************\n");
			scanf("%s",shuruzi);
			printf("\n");
			sscanf(shuruzi,"%2x%2x%2x%2x%2x%2x%2x%2x",&seq[0],&seq[1],&seq[2],&seq[3],&seq[4],&seq[5],&seq[6],&seq[7]);
				for(j=0;j<8;j++)
					cipher[j]=seq[j];
			//将输入的字符一个一个存到密文数组中 
			
					mydes.set_key(key);
					mydes.de_ctransform(cipher,plain);
			//调用解密算法函数完成解密
			 
						for(s=0;s<8;s++)
							seq[s]=plain[s];
				printf("明文:\n%02x%02x%02x%02x%02x%02x%02x%02x\n",seq[0],seq[1],seq[2],seq[3],seq[4],seq[5],seq[6],seq[7]);
				printf("\n");
			break;
			
			
		case '3':
			return 0;
			break;
		}		
	}
}                                    

实验三:维吉尼亚密码

1.实验目的

1) 编写 Vigenere 密码加密程序,在指定的目录下建立明文文件,输入任意选取的密钥, 加密后得到密文文件。
2) 编写 Vigenere 密码解密程序,在已知密钥的情况下将密文文件解密得到明文文件。
3) 给出一段密文,在不知密钥的情况下,破解该密文,恢复出明文

2.实验工具

1) Windows 系列操作系统。
2) VC6.0 编程环境

3. 实验方案

Vigenere 密码在加密/解密时,把英文字母映射为 0-25 的数字再进行计算,并按 n 个 字母一组进行变换。明文空间、密钥空间及密文空间都是长度为 n 的英文字母串的集合。 设密钥 k=(k1,k2,···, kn),明文 m=(m1,m2,···, mn),则加密算法为 Ek(m)=(c1,c2,···, cn) 其中,ci=(mi+ki)( mod 26), i=1,2,···, n。 对密文 c=(c1,c2,···, cn),解密算法为 Dk(c)=(m1,m2,···, mn) 其中,mi=(ci-ki)( mod 26), i=1,2,···, n

4.实验步骤
(说明:具体步骤,后面的实验结果最好对应这里每步都能看到)

1) Vigenere 密码加密程序步骤

  1. 读明文文件
  2. 通过加密公式得出密文
  3. 写入密文文件
    具体代码如下:
clear_passwords = open('C:/Users/qqq/Desktop/clear.txt').read()  #读文件
clear_password=list(clear_passwords)
secret_key=input("请输入密钥:")
secret_key=[int(x) for x in secret_key.split(" ")]
key_lengths=len(secret_key)
clear_lengths = len(clear_password)
ciphertext=[]
for i in range (clear_lengths):
    ciphertext.append(0)
for i in range(clear_lengths):
    k = i % key_lengths
    if ord(clear_password[i]) > 96 :
        ciphertext[i] = chr(((ord(clear_password[i]) - 97 + secret_key[k]) % 26) + 97)  #核心算法
    else:
        ciphertext[i] = chr(((ord(clear_password[i]) - 65 + secret_key[k]) % 26) + 65)
file = open('C:/Users/qqq/Desktop/key.txt','w')
file.write(" ".join(str(i)for i in ciphertext))  #写文件
file.close()
print("Encrypt successful")

2) 已知密钥情况下解密

  1. 读密文文件
  2. 通过解密公式得出密文
  3. 写入明文文件
    具体代码如下:
ciphertext = open('C:/Users/qqq/Desktop/key.txt').read()  #读文件
ciphertext_list=list(ciphertext)
secret_key=input("请输入密钥:")
secret_key=[int(x) for x in secret_key.split(" ")]
key_lengths=len(secret_key)
ciphertext_lengths = len(ciphertext_list)
clearpassword=[]
for i in range (ciphertext_lengths):
    clearpassword.append(0)
for i in range(ciphertext_lengths):
    k = i % key_lengths
    if ord(ciphertext_list[i]) > 96 :
        clearpassword[i] = chr(((ord(ciphertext_list[i]) - 97 + 26 - secret_key[k]) % 26) + 97)  #核心算法
    else:
        clearpassword[i] = chr(((ord(ciphertext_list[i]) - 65 + 26 - secret_key[k]) % 26) + 65)
for i in range(ciphertext_lengths):
    print(clearpassword[i])
file = open('C:/Users/qqq/Desktop/clear.txt','w')  #写文件
file.write(" ".join(str(i)for i in clearpassword))
file.close()
3)	未知密钥情况下,找到密钥,破解密文恢复明文
import math
def c_alpha(cipher):   # 去掉非字母后的密文
    cipher_alpha = ''
    for i in range(len(cipher)):
        if (cipher[i].isalpha()):
            cipher_alpha += cipher[i]
    return cipher_alpha

# 计算cipher的重合指数
def count_CI(cipher):
    N = [0.0 for i in range(26)]
    cipher = c_alpha(cipher)
    L = len(cipher)
    if cipher == '':
        return 0
    else:
        for i in range(L):     #计算所有字母的频数,存在数组N当中
            if (cipher[i].islower()):
                 N[ord(cipher[i]) - ord('a')] += 1
            else:
                 N[ord(cipher[i]) - ord('A')] += 1
    CI_1 = 0
    for i in range(26):
        CI_1 += ((N[i] / L) * ((N[i]-1) / (L-1)))
    return CI_1

# 计算秘钥长度为 key_len 的重合指数
def count_key_len_CI(cipher,key_len):
    un_cip = ['' for i in range(key_len)]    # un_cip 是分组
    aver_CI = 0.0
    count = 0
    for i in range(len(cipher)):
        z = i % key_len
        un_cip[z] += cipher[i]
    for i in range(key_len):
        un_cip[i]= count_CI(un_cip[i])
        aver_CI += un_cip[i]
    aver_CI = aver_CI/len(un_cip)
    return aver_CI

## 找出\秘钥长度
def pre_2(cipher):
    M = [(1,count_CI(cipher))]+[(0,0.0) for i in range(49)]
    for i in range(2,50):
        M[i] = (i,abs(0.065 - count_key_len_CI(cipher,i)))   #abs返回数字的绝对值
    M = sorted(M,key = lambda x:x[1])   #按照数组第二个元素排序  (因为列表内部是一个元组所以需要用到 key=lambda隐函数,x指的是列表内的元组,x[1]指的是按照第一个数据排序,从0 开始
    m = []
    for x in range(1,3):
        for i ,j in M:
            m.append(i)
    num = (math.gcd(m[1],m[2]))
    return num


# 猜测单个秘钥得到的重合指数
def count_CI2(cipher,n):     # n 代表我们猜测的秘钥,也即偏移量
    N = [0.0 for i in range(26)]
    cipher = c_alpha(cipher)
    L = len(cipher)
    F = [
        0.0651738, 0.0124248, 0.0217339,
        0.0349835, 0.1041442, 0.0197881,
        0.0158610, 0.0492888, 0.0558094,
        0.0009033, 0.0050529, 0.0331490,
        0.0202124, 0.0564513, 0.0596302,
        0.0137645, 0.0008606, 0.0497563,
        0.0515760, 0.0729357, 0.0225134,
        0.0082903, 0.0171272, 0.0013692,
        0.0145984, 0.0007836
    ]  # 英文字符频率。
    for i in range(L):     #计算所有字母的频数,存在数组N当中
        if (cipher[i].islower()):
            N[(ord(cipher[i]) - ord('a') - n)%26] += 1
        else:
            N[(ord(cipher[i]) - ord('A') - n)%26] += 1
    CI_2 = 0
    for i in range(26):
        CI_2 += ((N[i] / L) * F[i])
    return CI_2


def one_key(cipher,key_len):
    un_cip = ['' for i in range(key_len)]
    cipher_alpha = c_alpha(cipher)
    for i in range(len(cipher_alpha)):     # 完成分组工作
        z = i % key_len
        un_cip[z] += cipher_alpha[i]
    key_list = []
    for i in range(key_len):
        key_list.extend(pre_key(un_cip[i])) ####这里应该将5个分组的秘钥猜测全部打印出来
    return key_list

找出最可能的单个秘钥

def pre_key(cipher):
    M = [(0,0.0) for i in range(26)]
    for i in range(26):
        M[i] = (i,abs(0.065 - count_CI2(cipher,i)))
    M = sorted(M,key = lambda x:x[1])   #按照数组第二个元素排序
    m = []
    s = []
    for x in range(1, 5):
        for i, j in M:
            m.append(i)
    s.append(m[0])
    return s

def decode(cipher): #解密
    num = pre_2(cipher)
    key_len = num
    key = one_key(cipher, key_len)
    cipher_list = list(cipher)
    cipher_len = len(cipher_list)
    plaintext = ['0'] * cipher_len
    for i in range(cipher_len):
        k = i % key_len
        if ord(cipher_list[i]) > 96:
            plaintext[i] = chr(((ord(cipher_list[i]) - 97 + 26 - key[k]) % 26) + 97)
        else:
            plaintext[i] = chr(((ord(cipher_list[i]) - 65 + 26 - key[k]) % 26) + 65)
    for i in range(cipher_len):
       print(plaintext[i], end='')

cipher ='Vvhqwvvrhmusgjgthkihtssejchlsfcbgvwcrlryqtfsvgahwkcuhwauglqhnslrljshbltspisprdxljsvee Ghlqwkasskuwepwqtwvspgoelkcqyfnsvwljsniqkgnrgybwlwgoviokhkazkqkxzgyhcecmeiujoqkwf wvefqhkijrclrlkbienqfrjljsdhgrhlsfqtwlauqrhwdmwlgusgikkflryvcwvspgpmlkassjvoqxeggveyggzm ljcxxljsvpaivwikvrdrygfrjljslveggveyggeiapuuisfpbtgnwwmuczrvtwglrwugumnczvile'
cipher = c_alpha(cipher)
print("秘钥长度为:")
print(pre_2(cipher))
print()
decode(cipher)
  • 4
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值