密码学与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