可以发现采用RSA对message列表进行了加密,并将每组的 < N , e , c >
from AITMCLAB.Crypto.Util.number import getPrime
from AITMCLAB.libnum import s2n
def RSA_encrypt(message):
m = s2n(message)
p = getPrime(1024)
q = getPrime(1024)
N = p * q
e = 5
c = pow(m, e, N)
return N, e, c
messages = ["*******", "*******", "************", "*********", "**********", "********",
"**********", "*************", "**************", "******", "**********",
"***************", "*********", "*********", "*******"]
fp = open('output4.txt', 'w')
for m in messages:
N, e, c = RSA_encrypt(m)
fp.write("n = %s" % N + '\n')
fp.write("e = %s" % e + '\n')
fp.write("c = %s" % c + '\n')
fp.write('\n')
1 < e < ( p − 1 ) ( q − 1 ) g c d ( e , ( p − 1 ) ( q − 1 ) ) = 1 1
d e = 1 m o d ( p − 1 ) ∗ ( q − 1 ) de=1~mod~(p-1)*(q-1) de=1 mod (p−1)∗(q−1)
'''
Bangzhu likes talking with his junior schoolmate, but he is so lazy.
So he sometimes sends the same files of messages to elaborate them.
To avoid being discovered by Doc Gao and Doc Wang, he uses an encryption to send messages.
As a good students like you, you want to accuse Bangzhu and let your teachers know.
Could u find the flag hidden in the messages?
'''
也就是LAB3的名称——LOW e,加密指数e很小,常见是 e = 3 e=3 e=3或者 e = 2 16 + 1 = 65537 e=2^{16}+1=65537 e=216+1=65537
指采用同样的加密指数 e e e采用不同的N对一份密文多次加密(这就是我之前强调的注释内容)
设 m 1 , m 2 , . . . , m r 是两两互素的自然数, 令 m = m 1 m 2 . . . m r , M i = m m i , i = 1 , . . . , r , 则方程组: { x ≡ b 1 ( m o d m 1 ) x ≡ b 2 ( m o d m 2 ) . . . x ≡ b r ( m o d m r ) 的解为: x ≡ M 1 ′ M 1 b 1 + M 1 ′ M 2 b 2 + . . . M r ′ M r b r ( m o d m ) 即 x ≡ ∑ i = 1 r M i ′ M i b i ( m o d m ) 其中 M i ′ 满足 M i ′ M i ≡ 1 ( m o d m i ) 设m_1,m_2,...,m_r是两两互素的自然数,\\ 令m=m_1m_2...m_r,~M_i=\frac{m}{m_i},~i=1,...,r,则方程组:\\ \begin{cases} x\equiv b_1~(mod~m_1)\\ x\equiv b_2~(mod~m_2)\\ ~~ ...\\ x\equiv b_r~(mod~m_r) \end{cases} ~~的解为:\\ x\equiv M_1'M_1b_1+M_1'M_2b_2+...M_r'M_rb_r~(mod~m)\\ 即~x\equiv \sum_{i=1}^r~M_i'M_ib_i~(mod~m)\\ 其中~M_i'~满足~M_i'M_i\equiv 1~(mod~ m_i) 设m1,m2,...,mr是两两互素的自然数,令m=m1m2...mr, Mi=mim, i=1,...,r,则方程组:⎩ ⎨ ⎧x≡b1 (mod m1)x≡b2 (mod m2) ...x≡br (mod mr) 的解为:x≡M1′M1b1+M1′M2b2+...Mr′Mrbr (mod m)即 x≡i=1∑r Mi′Mibi (mod m)其中 Mi′ 满足 Mi′Mi≡1 (mod mi)
信心满满打算写一个判断互素的函数来判断这15组 < N , e , c >
def is_coprime(n_lst):
"""判断是否两两互素"""
l_n = len(n_lst)
for a in range(l_n):
for b in range(l_n):
if gcd(n_lst[a], n_lst[b]) == 1:
print(a, b)
运行结果有点无语,OS:???怎么两两互素!?
设有集合 A ,由 A 的所有子集组成的集合,称为 A 的幂集, 记作 2 A ,即 : 2 A = { S ∣ S ⊆ A } 若 ∣ A ∣ = n , 则 ∣ 2 A ∣ = 2 n 设有集合A,由A的所有子集组成的集合,称为A的幂集,\\ 记作2^A,即:2^A=\{S|S\subseteq A\}\\ 若\left|A\right|=n,则\left|2^A\right|=2^n 设有集合A,由A的所有子集组成的集合,称为A的幂集,记作2A,即:2A={S∣S⊆A}若∣A∣=n,则∣ ∣2A∣ ∣=2n
∣ n m o d _ l s t ∣ = 15 故其子集个数(分组情况可能为) 2 15 − 1 = 32767 ( 除去空集 ) \left|nmod\_lst\right|=15\\ 故其子集个数(分组情况可能为)2^{15}-1=32767~(除去空集) ∣ ∣nmod_lst∣ ∣=15故其子集个数(分组情况可能为)215−1=32767 (除去空集)
方法:每一次遍历,在已有集合中加上一个新的元素
对于集合 [ 1 , 2 , 3 ] , 有 { [ ] [ ] [ 1 ] [ ] [ 1 ] [ 2 ] [ 1 , 2 ] [ ] [ 1 ] [ 2 ] [ 1 , 2 ] [ 1 , 3 ] [ 2 , 3 ] [ 1 , 2 , 3 ] 对于集合[1,2,3],有\\ \begin{cases} [~]\\ [~]~[1]\\ [~]~[1]~[2]~[1,2]\\ [~]~[1]~[2]~[1,2]~[1,3]~[2,3]~[1,2,3]\\ \end{cases} 对于集合[1,2,3],有⎩ ⎨ ⎧[ ][ ] [1][ ] [1] [2] [1,2][ ] [1] [2] [1,2] [1,3] [2,3] [1,2,3]
def subsets(lst):
"""生成集合的所有子集"""
sub_lsts = [[]]
for sub in lst:
sub_lsts += [sub_lst + [sub] for sub_lst in sub_lsts]
return sub_lsts
在k个一组的所有情况中,当且仅当 k = 5 = e k=5=e k=5=e时有不重复的三(15/5)组对应解,即得到三段明文,于是我写了挑选出大小为5的子集的函数:
def judge_5(lsts):
"""挑选长度为5的列表"""
sub_5 = []
for lst in lsts:
if len(lst) == 5:
sub_5.append(lst)
return sub_5
当 k = 2 / 3 / 4 k=2/3/4 k=2/3/4时,也可以解出有效明文,但是有重复
主要代码实现如下:
if __name__ == "__main__":
t1 = time.time()
e = 5
filename = "output4.txt"
cipher_lst, nmod_lst = file_proc(filename)
# 从文件读取c/n列表
cipher_lst = judge_5(subsets(cipher_lst))
nmod_lst = judge_5(subsets(nmod_lst))
# 生成子集->挑出长度5的
lth = len(cipher_lst)
msg = ""
for i in range(lth):
# CRT计算x^e
xe = crt(cipher_lst[i], nmod_lst[i])
# gmpy2.iroot()返回一个元组(int:整数部分,bool:是否成功开根)
res = gmpy2.iroot(xe, e)
if res[1]:
msg = n2s(int(res[0])).decode("utf-8")
print(msg)
t2 = time.time()
print(t2 - t1)
这个部分的数学原理困扰了我好几天,直到我翻阅了出题人gfy大佬提供的一份英文文献(英文看不太懂,一知半解的去百度发现有中文译文(x)
数学原理(证明略,有兴趣的同学可以看中文版在这里面找Low Public Exponent RSA
假设 N 1 , N 2 , . . . , N k 为 k 个互素的整数。设 N m i n = m i n ( N i ) , g i ∈ Z N i [ x ] ( 模 N i 的多项式完全剩余系 ) 为 k 个次数为 d 的多项式 假设存在唯一的 M < N m i n , 使得 g i ( M ) ≡ C i ( m o d N i ) , i ∈ 1 , 2 , . . . , k 故,如果 k ≥ d , 可以有效的从( N i , g i , C i ) i = 1 k 中找到 M 假设N_1,N_2,...,N_k为k个互素的整数。设N_{min}=min(N_i),\\ g_i\in\mathbb{Z}_{N_i}[x](模N_i的多项式完全剩余系)为k个次数为d的多项式\\假设存在唯一的M
设 N 是整数, f ∈ Z N [ x ] 是 d 阶的一元多项式( x d 的系数为 1 ) 那么我们可以找到所有的 x ∈ Z , 使 ∣ x ∣ ≤ B 和 f ( X ) ≡ 0 ( m o d N ) 其中 B = N 1 d 设N是整数,f\in\mathbb{Z}_N[x]是d阶的一元多项式(x^d的系数为1)\\ 那么我们可以找到所有的x\in\mathbb{Z},使\left|x\right|\leq B和f(X)\equiv0~(mod~N) \\其中B=N^{\frac{1}{d}} 设N是整数,f∈ZN[x]是d阶的一元多项式(xd的系数为1)那么我们可以找到所有的x∈Z,使∣x∣≤B和f(X)≡0 (mod N)其中B=Nd1
设 h i = g i − C i , 1 ≤ i ≤ k . 接下来寻找 M ,使得 h i ( M ) ≡ 0 ( m o d N i ) , i ∈ [ 1 , k ] 使用 C R T 进行组合: h ( x ) = ∑ i = 1 k T i h i ( x ) ( m o d N 1 N 2 . . . N k ) 其中 T i 的选择使用 C R T ,以满足: T i = { 1 ( m o d N j ) , i = j 0 ( m o d N j ) , i ≠ j 故 h ( x ) 满足: 1. 阶(次数) d = 3 2. 首一的 ( x d 的系数为 1 模任何 N i ) 3. h ( M ) ≡ 0 ( m o d N 1 N 2 . . . N k ) 设h_i=g_i-C_i, 1\leq i \leq k.接下来寻找M,使得h_i(M)\equiv 0~(mod~N_i),i\in [1,k]\\ 使用CRT进行组合:\\ h(x)=\sum_{i=1}^kT_ih_i(x)~(mod~N_1N_2...N_k)\\ 其中T_i的选择使用CRT,以满足:\\ T_i=\begin{cases} 1~(mod~N_j),~i=j\\ 0~(mod~N_j),~i\neq j \end{cases}\\ 故h(x)满足:\\ 1.阶(次数)d=3\\ 2.首一的(x^d的系数为1模任何N_i)\\ 3.h(M)\equiv 0~(mod~N_1N_2...N_k) 设hi=gi−Ci,1≤i≤k.接下来寻找M,使得hi(M)≡0 (mod Ni),i∈[1,k]使用CRT进行组合:h(x)=i=1∑kTihi(x) (mod N1N2...Nk)其中Ti的选择使用CRT,以满足:Ti={1 (mod Nj), i=j0 (mod Nj), i=j故h(x)满足:1.阶(次数)d=32.首一的(xd的系数为1模任何Ni)3.h(M)≡0 (mod N1N2...Nk)
由 k ≥ d 可得 M < N m i n ≤ ( N 1 N 2 . . . N k ) 1 k ≤ ( N 1 N 2 . . . N k ) 1 d 由k\geq d可得\\ M
这也就解释了为什么2/3/4/5均可以解出明文的原因:
本LAB中, d = e = 5 d=e=5 d=e=5,且实际上三段明文各加密 k = 5 ≥ d k=5\geq d k=5≥d次满足条件
M < ( N 1 N 2 . . . N k ) 1 d = ( N 1 N 2 . . . N k ) 1 5 < ( N 1 N 2 . . . N k ) 1 2 / 3 / 4 M<(N_1N_2...N_k)^{\frac{1}{d}}=(N_1N_2...N_k)^{\frac{1}{5}} <(N_1N_2...N_k)^{\frac{1}{2/3/4}} M<(N1N2...Nk)d1=(N1N2...Nk)51<(N1N2...Nk)2/3/41
故 d = 5 d=5 d=5是M有解的一个上界,2/3/4也满足有解条件但是会导致重复(取1的时候显然不能使用CRT)
# _*_ coding: utf-8 _*_
"""
Time: 2022/9/19 17:21
Author: 刘征昊(£·)
Version: V 1.1
File: lab3_solution.py
Describe:
"""
import time
from AITMCLAB.libnum import n2s, gcd
import gmpy2
from functools import reduce
def crt(cpr_lst, n_lst):
"""
中国剩余定理求解: x == c (mod n)
params:
cpr-lst 余数c列表
n_lst 模数n列表
return: x
"""
# 累积 m = n1*n2*...*nk
m = reduce(lambda x, y: x * y, (ni for ni in n_lst))
result = 0
data = zip(cpr_lst, n_lst)
for ci, ni in data:
mi = m // ni
di = gmpy2.invert(mi, ni)
result += (ci * mi * di) % m
return result % m
def file_proc(fn):
"""
文件处理函数:从文件中读取每组 n 和 c
params: fn文件名(含后缀名)
return: 返回c和n的列表
"""
cipher = []
nmod = []
with open(fn, "r") as fp:
for line in fp:
line = line.strip('\n')
if line.startswith('n'):
n = int(line.split(' ')[-1])
nmod.append(n)
elif line.startswith('c'):
c = int(line.split(' ')[-1])
cipher.append(c)
else:
continue
return cipher, nmod
def is_coprime(n_lst):
"""判断是否两两互素"""
l_n = len(n_lst)
for a in range(l_n):
for b in range(l_n):
if gcd(n_lst[a], n_lst[b]) == 1:
print(a, b)
def subsets(lst):
"""生成集合的所有子集"""
sub_lsts = [[]]
for sub in lst:
sub_lsts += [sub_lst + [sub] for sub_lst in sub_lsts]
return sub_lsts
def judge_5(lsts):
"""挑选长度为5的列表"""
sub_5 = []
for lst in lsts:
if len(lst) == 4:
sub_5.append(lst)
return sub_5
if __name__ == "__main__":
t1 = time.time()
e = 5
filename = "output4.txt"
cipher_lst, nmod_lst = file_proc(filename)
# 从文件读取c/n列表
cipher_lst = judge_5(subsets(cipher_lst))
nmod_lst = judge_5(subsets(nmod_lst))
# 生成子集->挑出长度5的
lth = len(cipher_lst)
msg = ""
for i in range(lth):
xe = crt(cipher_lst[i], nmod_lst[i])
res = gmpy2.iroot(xe, e)
if res[1]:
msg = n2s(int(res[0])).decode("utf-8")
print(msg)
t2 = time.time()
print(t2 - t1)
# aitmc{Chicken_soup_is_tasty_CRT_is_tasty_for_you_too}
# Ahahahaha, here is the chicken soup!! Hahaha A~*sigh*.The dish is all here, why don't you eat? Lao Feng, everyone is afraid to eat it!Someone said that that someone had poisoned the chicken soup. WTF?Captain Wang. You are such a joker. aitmc{Chicken_soup_is_tasty_CRT_is_tasty_for_you_too}. Not salty and not light. The taste is really good!