不多bb,直接上图
有一说一,这个题目刚拿到手被吓到了,作为咸鱼的我慌得很 ) 正好前几节课大佬正好讲了pycryptodoom这个库,赶紧看看 导入库之后漫长的读代码时间,不要误会,不是读这个库,是读大佬写好的代码,因为不需要签名,我主要读了这三个函数
def generate_key(bits): return RSA.generate(bits) def encrypt(message, pk, hasher=Hash.SHA1): cipher_obj = cipher.new(RSA.importKey(pk)) org_bytes = message.encode() length_en = RSA.RsaKey.size_in_bytes(RSA.importKey(pk)) - 2 * hasher.digest_size - 2 res_en = b'' for i in range(0, len(org_bytes), length_en): res_en += cipher_obj.encrypt(org_bytes[i: i + length_en]) cipher_text = res_en return cipher_text def decrypt(cipher_text, sk): cipher_obj = cipher.new(RSA.importKey(sk)) length_de = RSA.RsaKey.size_in_bytes(RSA.importKey(sk)) res_de = b'' for i in range(0, len(cipher_text), length_de): #res_de += cipher_obj.decrypt(cipher_text[i:i + length_de], 'DecryptError') # for pkcs res_de += cipher_obj.decrypt(cipher_text[i:i + length_de]) # for oaep plaint_text = res_de.decode() return plaint_text运行时先创建公私钥,然后调用加密解密函数就可以了,这是RSA库的功能。没啥可说的,先读库的说明,里边有举例(主要大佬例子明显),懂得都懂
RSA算法大家都懂,基本计算机上过带学的都知道
参数参数说明公钥n,en=p*q,e和(p-1)(q-1)互质私钥n,dd·e=1mod[(p-1)(q-1))]加密C,M,e C = M e m o d ( n ) C=M^emod(n) C=Memod(n)解密M,C,d M = C d m o d ( n ) M=C^dmod(n) M=Cdmod(n)看起来很简单吧,感觉主要简单数论知识就明白了原理,我开始也是这么想的,实现起来被RSA狠狠暴打一顿,RSA算法实现的几个重要的点:
产生两个随机的质数p,q,要是不查表只能手搓了E和乘积互质,听起来简单吧,算起来也挺要命求d,其实是在求e的逆,多亏刚考了数论,还能hold住在加密时 M e M^e Me时 模指数运算问题,正常算太慢这次是真的学到了,每次考试的小素数分解式多么简单,这些问题属实要命,没招,只能回炉重造(百度),找到了一些解决方法
产生随机质数的方法:米勒罗宾算法, 这算法的原理如下: (1).若p是素数,则 a 2 m o d p = 1 a^2mod p=1 a2modp=1当且仅当 a m o d p = 1 或 a m o d p = − 1 amodp=1或a mod p=-1 amodp=1或amodp=−1成立; (2).若p是素数,有 p − 1 = 2 k q , p-1=2^kq, p−1=2kq,设a为整数且1<a<p-1,则 a q m o d p = 1 a^qmodp=1 aqmodp=1即费马小定理 证明如下: 代码实现:
def montgomery(a, q, k, n): if quick_power_mod(a, q, n) == 1: return False else: for i in range(0, k): if quick_power_mod(a, 2 ** i * q, n) == n - 1: return False return True2.e和乘积互质解决方法:判断最大公因数是不是1,用欧几里得算法,不多说了上代码;
def GCD(a, b): while b != 0: temp = b b = a % b a = temp return a3.求逆,用扩展欧几里得算法,也不多说了上代码;
def exgcd(e, phi_n): a = phi_n b = e x0, y0 = 1, 0 x1, y1 = 0, 1 x, y = 0, 1 r = a % b q = (a - r) // b while r != 0: x = x0 - q * x1 y = y0 - q * y1 x0, y0 = x1, y1 x1, y1 = x, y a = b b = r r = a % b q = (a - r) // b return y4.快速求模指数,利用模除的性质,代码如下
def quick_power_mod(alpha, plpha, nlpha): b = alpha p = plpha n = nlpha a = 1 b = b % n while(p): if p & 1 == 1: a = a * b % n p = p >> 1 a = a b = (b * b) % n return a除此之外别的就好说了 剩下的关键代码如下:
def RSA_Encrypt(string, e, n): bit = 0 tempn = n while tempn > 0: bit += 1 tempn = tempn >> 1 s = random.randint(2, bit - 1) string = string.encode('utf-8') bit64 = _bytes_2_64bit_(string) P = _64bit_2_sbit(bit64, s) C = [] for i in range(len(P)): tempC = quick_power_mod(P[i], e, n) C.append(tempC) return C,s def RSA_Decrypt(C, d, n,s): P = [] for i in range(len(C)): tempP = quick_power_mod(C[i], d, n) P.append(tempP) P = _sbit_2_64bit(P, s) P = _64bit_2_bytes(P) return P.decode('utf-8')至此RSA两大块完成
要求前边已经提过,这部分实现起来原理很简单,但过程很困难,主要难点在类型转换,比如np数组和list;2,10,16进制和字符串等格式转换等;还有个问题是pythonClass的使用,在实体化一个class的时候,我的参数有一个无法调用,最终被迫使用函数完成(代码行数少了,但写的很难看). 有个小技巧,在字符串不好调用时可以输出,输出再读取,可能有奇效,也可能是我会改格式,哈哈 不多说了,上代码:
def LFSR_self_fankui(state,seq): fpoly1 = [13, 12, 6, 5, 4, 3] b = np.logical_xor(state[fpoly1[0] - 1], state[fpoly1[1] - 1]) # 异或最后一位和第一位 if len(fpoly1) > 2: for i in range(2, len(fpoly1)): b = np.logical_xor(state[fpoly1[i] - 1], b) # 反馈多项式启动 state = np.roll(state, 1) # 沿着给定轴滚动数组元素。超出最后位置的元素将会滚动到第一个位置。 state[0] = b * 1 # 反馈位填入第一位 # if self.verbose: # 输出每轮的值 if seq.size==0: seq = state[1] seq = np.append(seq, state[4]) seq = np.append(seq, state[8]) seq = np.append(seq, state[7]) seq = np.append(seq, state[17]) seq = np.append(seq, state[99]) seq = np.append(seq, state[137]) seq = np.append(seq, state[221]) else: seq = np.append(seq, state[1]) seq = np.append(seq, state[4]) seq = np.append(seq, state[8]) seq = np.append(seq, state[7]) seq = np.append(seq, state[17]) seq = np.append(seq, state[99]) seq = np.append(seq, state[137]) seq = np.append(seq, state[221]) # 过滤密钥流 return (state,seq) def LFSR_self(): state_1 = np.array(sha_1) state1 = state_1.astype(int) state_2 = np.array(sha_1) state2 = state_2.astype(int) state_3 = np.array(sha_1) state3 = state_3.astype(int) state_4 = np.array(sha_1) state4 = state_4.astype(int) # 初始化4个LFSR verbose 控制是否显示每轮结果,测试时改为true seq=np.zeros(1) # L1首先进行一轮操作 state1,seq=LFSR_self_fankui(state1,seq) # 过滤的密钥值放入总的密钥流中 for i in range(255): # 轮换执行n-1次 state2,seq=LFSR_self_fankui(state2,seq) state2[0] = state2[0] ^ state1[0] state3, seq = LFSR_self_fankui(state3, seq) state3[0] = state3[0] ^ state2[0] state4,seq=LFSR_self_fankui(state4,seq) state4[0] = state4[0] ^ state3[0] state1,seq=LFSR_self_fankui(state1,seq) state1[0] = state1[0] ^ state4[0] state2, seq = LFSR_self_fankui(state2, seq) state2[0] = state2[0] ^ state1[0] state3, seq = LFSR_self_fankui(state3, seq) state3[0] = state3[0] ^ state2[0] state4, seq = LFSR_self_fankui(state4, seq) state4[0] = state4[0] ^ state3[0] hex_num = hex_change(seq) # 将产生的二进制密钥流转为16进制字符 text_save("seq_self.txt", hex_num) # 保存生成的密钥流字符串到文件中 q = open("seq_self.txt", "rb") seq = q.read(1024) q.close() mingwen = "mingwen.txt" miwen = "jiami_self.txt" jiemip = "jiemi_self.txt" jiami(mingwen, miwen, seq) jiemi(miwen, jiemip, seq)基本就这了,学到了很多,学哭了都. 最后附上一张友情赞助的可爱小图:
我感觉蛮不错的,很喜欢这种黑白画风,大家品一品,欢迎留言