A = [randint(1, 5)] # 可以自行修改初始值 sum = A[0] for i inrange(1, 8): A.append(sum+randint(1, 5)) sum += A[i]
生成公钥
首先取两个素数p,q并确保满足以下条件
p>i=1∑nai,q∈[1,p−1],(p,q)=1
q将作为解密时的私钥。
接下来通过模乘计算出一个新的序列B=(b1,b2,...,bn):
bi≡qai(modp)
公钥即生成的新序列(背包)B和素数p。
1 2 3 4 5 6 7 8 9 10 11 12
from Crypto.Util.number import getPrime
p = getPrime(16) q = getPrime(16) B = [] while q >= p: q = getPrime(16) for i in A: B.append(q * i % p)
print(A, q) print(B, p)
加密
对于明文m,将其构造成一个序列M=(x1,x2,...,xn),利用公钥(B,p)加密如下:
E=i=1∑nxibimodp
1 2 3 4 5 6 7 8
M = [0, 1, 1, 0, 1, 1, 0, 1] # 明文二进制序列 E = 0 cnt = 0 while cnt < len(M): E += M[cnt] * B[cnt] cnt += 1 E %= p print(E)
解密
对于密文E,在我们拥有私钥(A,q)的情况下,按如下方式解密:
首先计算E′
E′=Eq−1modp
再对E′利用超递增背包解密即可得到明文的二进制M。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
from sympy import mod_inverse
Q = mod_inverse(q, p) E = E * Q % p print(E) decrypted = [] for i in A[::-1]: if E >= i: decrypted.insert(0, 1) E -= i else: decrypted.insert(0, 0) if E != 0: print("Decryption failed") else: print(decrypted)
from random import randint from Crypto.Util.number import getPrime, bytes_to_long, long_to_bytes from sympy import mod_inverse
A = B = [] p = q = sum = 0
defgeneratePrivateKey(length, init, maxAdd): global A, sum A = [init] sum = A[0] for i inrange(1, length): A.append(sum + randint(1, maxAdd)) sum += A[i]
defgeneratePublicKey(): global A, B, p, q size = 16 p = getPrime(16) q = getPrime(16) while p <= sum: p = getPrime(size := size + 1) q = getPrime(size) while q >= p: q = getPrime(size) B = [q * i % p for i in A]
defencrypt(message): global A, B, p, q M = [int(i) for i inbin(bytes_to_long(message))[2:]] generatePrivateKey(len(M), 1, 5) generatePublicKey() E = 0 for cnt inrange(len(M)): E += M[cnt] * B[cnt] print("Private Key (A):", A) print("Public Key (B):", B) print("Public p:", p) print("Private q:", q) print("Encrypted (E):", E) return E
defdecrypt(encrypted): global A, B, p, q Q = mod_inverse(q, p) encrypted = encrypted * Q % p decrypted = [] for i in A[::-1]: if encrypted >= i: decrypted.insert(0, 1) encrypted -= i else: decrypted.insert(0, 0) if encrypted != 0: print("Decryption failed") else: text = "".join([str(i) for i in decrypted]) print("Decrypted (text):", long_to_bytes(int(text, 2)))