密码学课程设计
仿射密码
def fangshe_encrypt(m, a, b): res = '' for i in range(len(m)): if m[i] >= 'A' and m[i] <= 'Z': res += chr(((ord(m[i]) - 65) * a + b) % 26 + 65) return res def get_re(a): #得逆元 for i in range(1, 27): #因为数量较小,就直接一一匹配 if i * a % 26 == 1: return i def fangshe_decrypt(c, a, b): res = '' a_1 = get_re(a) for i in range(len(c)): if c[i] >= 'A' and c[i] <= 'Z': res += chr((((ord(c[i]) - 65) - b) * a_1) % 26 + 65) return res m = input("plz input your plaintext(A~Z):") #m = 'ILOVEFANGSHE' a = 19 b = 3 c = fangshe_encrypt(m, a, b) print("加密后结果:",c) d = fangshe_decrypt(c, a, b) print("解密后结果:",d)
维吉尼亚密码
w ='ABCDEFGHIJKLMNOPQRSTUVWXYZ' def create_k_list(k): #创建密钥数据形式 res = [] for i in range(len(k)): res.append(ord(k[i].upper())-65) #全部大写 return res def Vigenere_encrypt(m,k): res = '' K = create_k_list(k) #创建密钥数据形式 t = 0 #存放K的下标 for i in range(len(m)): if t == len(K): t = 0 if m[i]>='A' and m[i]<='Z': res += w[(ord(m[i]) + K[t] - 65) % 26] t +=1 elif m[i]>='a' and m[i]<='z': res += w[(ord(m[i])+K[t]-97)%26] t+=1 else: res += m[i] return res def Vigenere_decrypt(c,k): res = '' K = create_k_list(k) t = 0 for i in range(len(c)): if t == len(K): t = 0 if c[i]>='A' and c[i]<='Z': res += w[(ord(c[i]) - K[t] - 65) % 26] t +=1 elif c[i]>='a' and c[i]<='z': res += w[(ord(c[i])-K[t]-97)%26] t+=1 else: res += c[i] return res flag = input("输入E加密,输入D解密:") if flag == 'E': m = input("请输入明文:") k = input("请输入密钥:") c = Vigenere_encrypt(m, k) print("加密结果为:",c) elif flag == 'D': c = input("请输入密文:") k = input("请输入密钥:") d = Vigenere_decrypt(c, k) print("解密结果为:",d) # m = 'ILOVEVIGENERE' # m = 'WhenthemediareportnewsaboutChinesesecondrichgenerationtheyareoftendescribedtobeviolentrudeandimpoliteTheserichkidslivethecomfortablelifebuttheirparentshaventeducatedthemwellbecausetheyarebusywiththeirbusinessOrthesekidsaresenttostudyabroadtheyarestillthewildchildren' # k = 'thisiskey' # c = Vigenere_encrypt(m,k) # print("加密结果为:",c) # d = Vigenere_decrypt(c, k) # print("解密结果为:",d)
线性反馈移位寄存器
# 本原多项式:x^17 + x^3 + 1 a = [0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0,1] #初始状态 aa = [0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0,1] #对比状态 count = 0 print("预期周期是:",2**17-1) while True: b = (a[0] + a[14]) %2 a.append(b) #右进,左出,是相反的 del a[0] count += 1 if a == aa: print("运算后的周期是:",count) break
RSA
import random import libnum #扩展欧几里得算法。 def ex_gcd(a, b): if b == 0: return 1, 0 else: q = a // b r = a % b s, t = ex_gcd(b, r) s, t = t, s - q * t return [s, t] # Miller Rabin算法检验 def rabin_miller(num): s = num - 1 t = 0 while s % 2 == 0: # 如果是偶数,直到奇数 s = s // 2 # 整除2 t += 1 # 记录除的次数 for trials in range(15): #15次检验 a = random.randrange(2, num - 1) # 生成随机数 v = pow(a, s, num) # (a**num-1) %num 费马小定理,余数为v if v != 1: # 如果模不等于1 i = 0 while v != (num - 1): # 就是 v自乘取模后不为1,就继续 if i == t - 1: # 当t-1次,仍不为1,就是 v ** (2 ** t-1) != 1 mod num return False # 失败,费马定理失败,则一定是合数 else: i = i + 1 # 次数+1 v = (v ** 2) % num # 自乘取模 # 如果v自乘取模后为1,费马定理成功,有一定概率是素数 # 15次检验都成功,极大概率是素数。 return True # 判断是否为素数 def is_prime(num): # 排除0,1和负数 if num < 2: return False # 创建小素数的列表,可以大幅加快速度 # 如果是小素数,那么直接返回true small_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997] if num in small_primes: return True # 若大数能整除小素数,则错误,是合数 for prime in small_primes: if num % prime == 0: return False # 若以上均通过,用rabin_miller算法检验 return rabin_miller(num) # 得到大整随机数 def get_prime(key_size): while True: # 生成随机数,范围是[2**(key_size-1), 2**key_size) num = random.randrange(2 ** (key_size - 1), 2 ** key_size) # 判断是否是素数 if is_prime(num): return num # 快速幂 def qmi(a, b, p): res = 1 while b: if b & 1: # 最小位是否为1 res = res * a % p a = a * a % p b >>= 1 return res # 创建d def create_d(e, f_n): d = ex_gcd(e, f_n)[0]%f_n # 扩展欧几里德,辗转相除得到d。 return d # 创建各种参数 def create_p_q_n_f_n_e_d(): p = get_prime(1024) q = get_prime(1024) n = p * q f_n = (p - 1) * (q - 1) e = 65537 d = create_d(e, f_n) return p, q, n, f_n, e, d # 加密 def RSA_encrypt(m, e, n): M = "".join("{:02x}".format(ord(x)) for x in m) M = int(M, 16) return qmi(M, e, n) # C = M^e (mod n) # 解密 def RSA_decrypt(c, d, n): res = pow(c, d, n) # plaintext = C^d (mod n) res = str(bytes.fromhex('{:x}'.format(res))) return res[2:len(res) - 1] m = input("plz input your plaintext:") # 生成各种参数 p, q, n, f_n, e, d = create_p_q_n_f_n_e_d() # 加密 C = RSA_encrypt(m, e, n) print("加密后数据为:", C) # 解密 M = RSA_decrypt(C, d, n) print("解密后数据为:", M)
MD5
import math #左移位数数组 r = [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 ] #正弦函数 T = [int(math.floor(abs(math.sin(i + 1)) * (2 ** 32))) for i in range(64)] # 字符串转二进制 def str_to_bin(input): input1 = input.encode("utf-8").hex() res = '' for i in range(len(input1)): res += bin(int(input1[i], 16))[2:].rjust(4, "0") return res #填充0-1 def add_0_1(input): # 最后长度直接填在最后 l = bin(len(input))[2:] #取二进制输入字符串的长度 res = input flag = 0 # 填充10 while len(res) % 512 != 448: #填充一个1和若干0 if flag == 0: res += '1' flag = 1 else: res += '0' while (len(res) + len(l)) % 512 != 0: #高位补齐0 res += '0' res += l #填充长度数据 return res # 初始化寄存器 def create_register(): # 小端序后 A = 0x67452301 B = 0xefcdab89 C = 0x98badcfe D = 0x10325476 return A, B, C, D #二进制转512数组 def bin_to_512hexarr(input): res = [] rehex = '' inhex = '' if len(input) % 512 != 0: print("wrong1!!") return 0 else: # 除最后前512位,先全部转16进制,再八位置换, 再放进数组 for i in range(len(input) - 512): inhex = hex(int(input[0:len(input) - 512], 2))[2:] for i in range(len(inhex) // 8): re = '' for t in range(7, -1, -2): rehex += inhex[i * 8:i * 8 + 8][t - 1:t + 1] for i in range(len(rehex) // 128): res.append(rehex[i * 128:i * 128 + 128]) # 取最后512位 a = input[len(input) - 512:len(input)] # 对剩下的512bit操作,前448同上操作,后64bit填入长度 # 前448位转16进制 b = hex(int(a[0:448], 2))[2:] # 前448位小端序 res1 = '' for i in range(len(b) // 8): c = b[i * 8:i * 8 + 8] # 每八位放在c中 for j in range(7, -1, -2): d = c[j - 1:j + 1] # 倒叙结果 res1 += d # 最后64位 num = hex(int(a[448:512], 2))[2:] if len(num) <= 8: # 如果小于8位,就先放高位,然后再放低位0 res1 += num.rjust(8, "0") for i in range(8): res1 += "0" else: num1 = num[0:8] num2 = num[8:] res1 += num1 res1 += num2.rjust(8, "0") res.append(res1) return res #512bit数组转32bit def hexarr_512_to_32(input): if len(input) != 128: # 128组 print("wrong2") return 0 else: res = [] for i in range(16): res.append(input[i * 8:i * 8 + 8]) return res #左移 def leftround(input, round): return (input << round | input >> (32 - round)) & 0xffffffff #ABCD组合,小端序排列相加 def conclude_ABCD(A, B, C, D): res = '' A = hex(A)[2:] B = hex(B)[2:] C = hex(C)[2:] D = hex(D)[2:] for i in range(7, -1, -2): a = A[i - 1:i + 1] res += a for i in range(7, -1, -2): a = B[i - 1:i + 1] res += a for i in range(7, -1, -2): a = C[i - 1:i + 1] res += a for i in range(7, -1, -2): a = D[i - 1:i + 1] res += a return res #字符串转16进制 def str_to_hex(input): if len(input) != 8: print("wrong") return 0 else: res = 0 for i in range(len(input)): a = int(input[i], 16) b = a << 4 c = res << 4 d = c + a res = d return res #md5加密函数 def md5_hash(input): bin_str = str_to_bin(input) #ascii变成01进制字符串 whole_bin_str = add_0_1(bin_str) #附加填充位 A, B, C, D = create_register() #初始化链接变量 # 将附加填充为后的二进制字符串分成512bit为一组的Mi分组,同时对其进行小端化处理 hex_512arr = bin_to_512hexarr(whole_bin_str) for i in range(len(hex_512arr)): #分别对每个Mi进行hash hex_32arr = hexarr_512_to_32(hex_512arr[i]) # 每个Mi分成32bit为一组的mi,共16组 AA, BB, CC, DD = A, B, C, D #寄存器初始值备份 for j in range(64): #4轮16个步函数,共64步 if j < 16: f = (B & C) | ((~B) & D) #非线性函数 flag = j #m[i] 即书上的M[j] elif j < 32: f = (B & D) | (C & (~D)) flag = (5 * j + 1) % 16 elif j < 48: f = (B ^ C ^ D) flag = (3 * j + 5) % 16 else: f = C ^ (B | (~D)) flag = (7 * j) % 16 #步函数执行过程 temp = B + leftround((A + f + T[j] + str_to_hex(hex_32arr[flag])) & 0xffffffff, r[j]) #寄存器换位 A, B, C, D = D, temp & 0xffffffff, B, C A = (A + AA) & 0xffffffff #执行完寄存器A和备份相加 B = (B + BB) & 0xffffffff C = (C + CC) & 0xffffffff D = (D + DD) & 0xffffffff res = conclude_ABCD(A, B, C, D) #四个寄存器值小端序组合拼接 return res input = input("plz input your plain text:") #input = 'iscbupt' a = md5_hash(input) print(a)