密码学与python的那些事

密码学与python的那些事

仿射变换

公式如下:

在这里插入图片描述

加密

"""
c代表密文,m代表明文,a, b表示密钥
c = a*m + b (mod 26)
m = a的逆元*(c-b) (mod 26)
"""
m = "security".lower()
c = ""
a = 7
b = 21
for i in range(0, len(m)):
    c = c + chr((((ord(m[i])-97)*a+b)%26)+97)
print(c)

解密

求逆元可以使用libnum库,也可以使用gmpy2库,也可以手写代码。

求逆元使用libnum库:

"""
c代表密文,m代表明文,a, b表示密钥
c = a*m + b (mod 26)
m = a的逆元*(c-b) (mod 26)
d表示a的逆元
"""
import libnum


c = "vlxijh".lower()
m = ""
a = 7
b = 21
d = libnum.xgcd(a, 26)[0]
for i in range(0, len(c)):
    m = m + chr((((ord(c[i])-97)-b+26)*d)%26 + 97)
print(m)

求逆元使用gmpy2库

"""
c代表密文,m代表明文,a, b表示密钥
c = a*m + b (mod 26)
m = a的逆元*(c-b) (mod 26)
d表示a的逆元
"""
import gmpy2


c = "vlxijh".lower()
m = ""
a = 7
b = 21
d = gmpy2.invert(a, 26)
print(d)
for i in range(0, len(c)):
    m = m + chr((((ord(c[i])-97)-b+26)*d)%26 + 97)
print(m)

求逆元使用手写代码:

"""
c代表密文,m代表明文,a, b表示密钥
c = a*m + b (mod 26)
m = a的逆元*(c-b) (mod 26)
d表示a的逆元
"""


def egcd(a, b):
    if (b == 0):
        return 1, 0, a
    else:
        x, y, q = egcd(b, a % b)  # q = GCD(a, b) = GCD(b, a%b)
        x, y = y, (x - (a // b) * y)
        return x, y, q


def mod_inv(a, b):
    return egcd(a, b)[0] % b  # 求a模b得逆元


c = "vlxijh".lower()
m = ""
a = 7
b = 21
d = mod_inv(a, 26)
for i in range(0, len(c)):
    m = m + chr((((ord(c[i])-97)-b+26)*d)%26 + 97)
print(m)

多表代换密码

加密:

import numpy as np


q = input("输入矩阵A:(格式为:[[11, 2, 19], [5, 23, 25], [20, 7, 17]]):")
a = np.mat(eval(q))
w = input("输入矩阵B:")
# 将矩阵B转置
b = np.mat(eval(w)).T
# 原文与矩阵转换
e = input("输入原文:")

elist = list(e)
for i in range(len(elist)):
    elist[i] = ord(elist[i]) - 97
x = np.zeros((3, int(len(elist) / 3)), dtype=int)
m = np.mat(x)

i = 0
h = 0
for i in range(int(len(elist) / 3)):
    j = 0
    for j in range(3):
        m[j, int(h / 3)] = elist[h]
        h = h + 1
# 提取矩阵的某一列
# print(m[:, 0])
# 加密算法
c = m
for i in range(0, int(len(elist) / 3)):
    c[:, i] = (np.dot(a, m[:, i]) + b) % 26

# print(c)
# 矩阵与密文转换
i = 0
h = 0
print("加密结果")
crypto = ""
for i in range(int(len(elist) / 3)):
    j = 0
    for j in range(3):
        crypto = crypto + chr(c[j, int(h / 3)] + 97)
        # sys.stdout.write(chr(c[j, int(h / 3)] + 97))
        h = h + 1
print(crypto)


# [[11, 2, 19], [5, 23, 25], [20, 7, 17]]
# [0,0,0]
# yourpinnoisfouronetwosix

解密:

import numpy as np
from numpy.linalg import *


# 矩阵取摸
def my_int_inv(mat, n=26):
    x = np.zeros(mat.shape, dtype=np.int16)
    for i in range(mat.shape[0]):
        for j in range(mat.shape[1]):
            x[i, j] = int(round(mat[i, j])) % n
    return x


# 欧几里德算法
def gcd(a, b):
    while a != 0:
        a, b = b % a, a
    return b


# 扩展欧几里德算法
def exgcd(a, m):
    if gcd(a, m) != 1:
        return None
    u1, u2, u3 = 1, 0, a
    v1, v2, v3 = 0, 1, m
    while v3 != 0:
        q = u3 // v3
        v1, v2, v3, u1, u2, u3 = (u1 - q * v1), (u2 - q * v2), (u3 - q * v3), v1, v2, v3
    return u1 % m


q = input("输入矩阵A:(格式为:[[11, 2, 19], [5, 23, 25], [20, 7, 17]]):")
a = np.mat(eval(q))
w = input("输入矩阵B:")
# 将矩阵B转置
b = np.mat(eval(w)).T
# 密文与矩阵转换
e = input("输入密文:")

elist = list(e)
for i in range(len(elist)):
    elist[i] = ord(elist[i]) - 97
x = np.zeros((3, int(len(elist) / 3)), dtype=int)
c = np.mat(x)


i = 0
h = 0
for i in range(int(len(elist) / 3)):
    j = 0
    for j in range(3):
        c[j, int(h / 3)] = elist[h]
        h = h + 1

# print(c)
# 提取矩阵的某一列
# print(m[:, 0])

# 求a的逆元
a_inv = a.I
a_det = det(a)
a_adju = my_int_inv(a_det * a_inv)
a_det_inv = exgcd(int(round((det(a) % 26))), 26)
aa_inv = my_int_inv(a_det_inv * a_adju)

# 解密算法
m = c
for i in range(0, int(len(elist) / 3)):
    m[:, i] = (np.dot(aa_inv, c[:, i]) + b) % 26

# print(c)





# 矩阵与密文转换
i = 0
h = 0
print("解密结果")
plantext = ""
for i in range(int(len(elist) / 3)):
    j = 0
    for j in range(3):
        plantext = plantext + chr(c[j, int(h / 3)] + 97)
        # sys.stdout.write(chr(c[j, int(h / 3)] + 97))
        h = h + 1
print(plantext)


# [[11, 2, 19], [5, 23, 25], [20, 7, 17]]
# [0,0,0]
# wgifgjtmrlhhxthwbxzpsbrb
原文地址:https://www.cnblogs.com/v01cano/p/11798433.html