密码学课程设计

仿射密码

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)

 

posted @ 2021-01-25 09:20  Evening_Breeze  阅读(396)  评论(0编辑  收藏  举报