前言
最近复现了一道NCTF的压轴密码题。这道密码题我打比赛的时候是懵逼的,后来看了出题人soreatu师傅的wp才学习到了这个算法(其实原理还是有些地方不太懂。。。)
AMM
全称为Adleman-Mander-Miller Method。在1977年他们发表的论文里只涉及了开平方根的方法,开n次方根并没有很详细的介绍。《Adleman-Manders-Miller Root Extraction Method Revisited》里三位中国人补充了他们开n次方根的方法。
平方根(x2≡ δ mod p)
AMM里开平方根的算法与Tonelli–Shanks算法几乎一样,只不过后面乘积时一个是从大到小一个是从小到大,所以我简要的介绍一下开平方根的思路。
首先令 p − 1 = 2 t s p-1=2^ts p−1=2ts
接着计算出模p的二次非剩余 ρ
根据欧拉准则,我们有
(
δ
s
)
2
t
−
1
≡
1
m
o
d
p
(δ^s)^ {2^{t-1}}\equiv1\ mod \ p
(δs)2t−1≡1 mod p
(
ρ
s
)
2
t
−
1
≡
−
1
m
o
d
p
(ρ^s)^ {2^{t-1}}\equiv-1\ mod \ p
(ρs)2t−1≡−1 mod p
如果
t
=
1
t=1
t=1,则
(
δ
s
+
1
2
)
2
≡
1
m
o
d
p
(δ^{\frac{s+1}{2}})^2\equiv1\ mod \ p
(δ2s+1)2≡1 mod p
所以
δ
s
+
1
2
δ^{\frac{s+1}{2}}
δ2s+1就是开平方根的结果。
如果 t ≥ 2 t\geq2 t≥2,
那么
(
δ
s
)
2
t
−
1
(δ^s)^ {2^{t-1}}
(δs)2t−1开平方根以后的结果就是1或者-1。
即:
(
δ
s
)
2
t
−
2
m
o
d
p
∈
{
1
,
−
1
}
(δ^s)^ {2^{t-2}}mod \ p\in \{1,-1\}
(δs)2t−2mod p∈{1,−1}
但我们仍有办法使它变成1。令
k
1
=
0
o
r
1
k_1=0\ or\ 1
k1=0 or 1,使得
(
δ
s
)
2
t
−
2
(
ρ
s
)
2
t
−
1
k
1
≡
1
m
o
d
p
(δ^s)^ {2^{t-2}}(ρ^s)^{2^{t-1}k_1} \equiv 1\ mod\ p
(δs)2t−2(ρs)2t−1k1≡1 mod p
因为 ( ρ s ) 2 t − 1 ∗ 0 = 1 (ρ^s)^{2^{t-1}*0}=1 (ρs)2t−1∗0=1, ( ρ s ) 2 t − 1 ∗ 1 = − 1 (ρ^s)^{2^{t-1}*1}=-1 (ρs)2t−1∗1=−1
同样的,对上式继续开平方根,使得:
(
δ
s
)
2
t
−
3
(
ρ
s
)
2
t
−
2
k
1
m
o
d
p
∈
{
1
,
−
1
}
(δ^s)^ {2^{t-3}}(ρ^s)^{2^{t-2}k_1}mod \ p\in \{1,-1\}
(δs)2t−3(ρs)2t−2k1mod p∈{1,−1}
令
k
2
=
0
o
r
1
k_2=0\ or\ 1
k2=0 or 1,则
(
δ
s
)
2
t
−
3
(
ρ
s
)
2
t
−
2
k
1
(
ρ
s
)
2
t
−
1
k
2
≡
1
m
o
d
p
(δ^s)^ {2^{t-3}}(ρ^s)^{2^{t-2}k_1}(ρ^s)^{2^{t-1}k_2} \equiv 1\ mod\ p
(δs)2t−3(ρs)2t−2k1(ρs)2t−1k2≡1 mod p
同样的,我们取
k
3
,
k
4
,
.
.
.
,
k
t
−
1
∈
{
1
,
−
1
}
k_3,k_4,...,k_{t-1}\in\{1,-1\}
k3,k4,...,kt−1∈{1,−1},则
(
δ
s
)
(
ρ
s
)
2
k
1
+
2
2
k
2
+
.
.
.
+
2
t
−
2
k
t
−
1
≡
1
m
o
d
p
(δ^s)(ρ^s)^{2k_1+2^2k_2+...+2^{t-2}k_{t-1}} \equiv 1\ mod\ p
(δs)(ρs)2k1+22k2+...+2t−2kt−1≡1 mod p
两边同时乘δ并提出平方,则:
(
δ
s
+
1
2
)
(
ρ
s
)
k
1
+
2
k
2
+
.
.
.
+
2
t
−
3
k
t
−
1
(δ^{\frac{s+1}{2}})(ρ^s)^{k_1+2k_2+...+2^{t-3}k_{t-1}}
(δ2s+1)(ρs)k1+2k2+...+2t−3kt−1
就是开平方根的结果。
算法如下:
n次方根(xr≡ δ mod q)
(很不成熟,所以有些解决不了的推论当作已知来处理)
解n次方根需要考虑两种情况:
(1) g c d ( r , q − 1 ) = 1 gcd(r,q-1)=1 gcd(r,q−1)=1
(2) r ∣ ( q − 1 ) r|(q-1) r∣(q−1)
如果 r 和 q-1 互素,直接求逆元就能解决(普通RSA解密)
如果 r ∣ ( q − 1 ) r|(q-1) r∣(q−1)
令 q − 1 = r t s q-1=r^ts q−1=rts.
因为δ是r次剩余,所以我们有 δ q − 1 r ≡ ( X r ) q − 1 r ≡ X q − 1 ≡ 1 m o d q δ^{\frac{q-1}{r}}\equiv({X^r})^{\frac{q-1}{r}}\equiv X^{q-1}\equiv 1\ mod\ q δrq−1≡(Xr)rq−1≡Xq−1≡1 mod q
找一个最小的非负整数α使得 s ∣ r α − 1 s|rα-1 s∣rα−1 (后面要开r次方根)
所以 ( δ r α − 1 ) r t − 1 ≡ 1 (δ^{rα-1})^{r^{t-1}}\equiv 1 (δrα−1)rt−1≡1
如果 t = 1 t=1 t=1,则开根结果为δα.
若 t ≥ 2 t\geq2 t≥2,
取r次非剩余 ρ ρ ρ( ρ q − 1 r ≠ 1 m o d q ρ^{\frac{q-1}{r}}\neq1\ mod\ q ρrq−1=1 mod q)
令 K i = ( ρ s ) i ∗ r t − 1 a n d K = { K 0 , K 1 , . . . K r − 1 } K_i=(ρ^s)^{i*r^{t-1}} and\ K=\{K_0,K_1,...K_{r-1}\} Ki=(ρs)i∗rt−1and K={K0,K1,...Kr−1}
且对于所有的 K i K_i Ki,都是模1开r次方根的结果,即 ( K i ) r ≡ 1 (K_i)^r\equiv1 (Ki)r≡1.
而且我们还知道
K
i
K_i
Ki互不相同,即:
(
ρ
s
)
i
∗
r
t
−
1
≠
(
ρ
s
)
j
∗
r
t
−
1
i
≠
j
a
n
d
i
,
j
∈
{
0
,
1
,
.
.
.
,
r
−
1
}
(ρ^s)^{i*r^{t-1}}\neq(ρ^s)^{j*r^{t-1}} \ i\neq j\ and\ i,j\in \{0,1,...,r-1\}
(ρs)i∗rt−1=(ρs)j∗rt−1 i=j and i,j∈{0,1,...,r−1}
也就是说模1开r次方根的结果的集合都在K这个集合里。
而且 K i ∗ K r − i ≡ 1 ( r − i ≡ − i m o d r ) K_i*K_{r-i}\equiv1\ (r-i\equiv -i\ mod\ r) Ki∗Kr−i≡1 (r−i≡−i mod r)
这两步我真的不懂,就当作已知了(可是验算出来都是正确的)
2020.5.12 更新:
(来填坑了,之前不理解的现在理解了)
ρ
ρ
ρ是之前取的一个
r
r
r次非剩余,我们可以定义一个生成元为
ρ
ρ
ρ的模
q
q
q的循环群
G
G
G
G
=
{
1
,
ρ
2
,
ρ
3
,
.
.
.
,
ρ
q
−
1
}
G=\{1,ρ^2,ρ^3,...,ρ^{q-1}\}
G={1,ρ2,ρ3,...,ρq−1}
在该循环群
G
G
G中,我们再定义
ρ
1
=
ρ
p
−
1
r
ρ_1=ρ^{\frac{p-1}{r}}
ρ1=ρrp−1,所以可以得到一个生成元为
ρ
1
ρ_1
ρ1的子群
H
H
H为
H
=
{
1
,
ρ
q
−
1
r
,
ρ
q
−
1
r
∗
2
,
ρ
q
−
1
r
∗
3
,
.
.
.
,
ρ
q
−
1
r
∗
(
r
−
1
)
}
H=\{1,ρ^{\frac{q-1}{r}},ρ^{\frac{q-1}{r}*2},ρ^{\frac{q-1}{r}*3},...,ρ^{\frac{q-1}{r}*(r-1)}\}
H={1,ρrq−1,ρrq−1∗2,ρrq−1∗3,...,ρrq−1∗(r−1)}
在这个子群里,所有的元素都是由
ρ
1
=
ρ
p
−
1
r
ρ_1=ρ^{\frac{p-1}{r}}
ρ1=ρrp−1生成的,所以所有元素的
r
r
r次方都为1,因为子群
H
H
H里正好有
r
r
r个元素,所以
H
H
H是模1开r次方根的结果的集合。(解释了第一个问题)
对于群来说每个元素都存在逆元,而且因为
ρ
q
−
1
=
1
m
o
d
p
ρ^{q-1}=1 mod\ p
ρq−1=1mod p,所以对于子群里任何一个元素
ρ
p
−
1
r
∗
i
ρ^{\frac{p-1}{r}*i}
ρrp−1∗i来说,都有:
ρ
q
−
1
r
∗
i
∗
ρ
q
−
1
r
∗
(
r
−
i
)
=
ρ
q
−
1
=
1
m
o
d
q
ρ^{\frac{q-1}{r}*i}*ρ^{\frac{q-1}{r}*(r-i)}=ρ^{{q-1}}= 1 mod\ q
ρrq−1∗i∗ρrq−1∗(r−i)=ρq−1=1mod q
(解释了第二个问题)
题外话:其实并不需要群理论,只用把 ( ρ s ) i ∗ r t − 1 (ρ^s)^{i*r^{t-1}} (ρs)i∗rt−1换成 ( ρ ) q − 1 r ∗ i (ρ)^{\frac{q-1}{r}*i} (ρ)rq−1∗i来理解就很好理解了。
有了这两个条件,我们可以开始像解平方根那样解n次方根了:
首先
(
(
δ
r
α
−
1
)
r
t
−
2
)
r
≡
1
((δ^{rα-1})^{r^{t-2}})^r\equiv 1
((δrα−1)rt−2)r≡1
开r次方后余数为集合
K
K
K中的一个数,设为
K
r
−
j
K_{r-j}
Kr−j,即:
(
δ
r
α
−
1
)
r
t
−
2
≡
K
r
−
j
(δ^{rα-1})^{r^{t-2}}\equiv K_{r-j}
(δrα−1)rt−2≡Kr−j
求逆元,得:
(
δ
r
α
−
1
)
r
t
−
2
K
j
≡
1
(δ^{rα-1})^{r^{t-2}}K_{j}\equiv 1
(δrα−1)rt−2Kj≡1
即:
(
δ
r
α
−
1
)
r
t
−
2
(
ρ
s
)
j
∗
r
t
−
1
≡
1
(δ^{rα-1})^{r^{t-2}}(ρ^s)^{j*r^{t-1}}\equiv 1
(δrα−1)rt−2(ρs)j∗rt−1≡1
同样的,继续开方,最终得到:
(
δ
r
α
−
1
)
(
ρ
s
)
j
1
∗
r
1
+
j
2
∗
r
2
+
.
.
.
+
j
t
−
1
∗
r
t
−
1
≡
1
(δ^{rα-1})(ρ^s)^{j_1*r^{1}+j_2*r^2+...+j_{t-1}*r^{t-1} } \equiv 1
(δrα−1)(ρs)j1∗r1+j2∗r2+...+jt−1∗rt−1≡1
最后乘δ提取r次方:
( δ α ) r ( ( ρ s ) j 1 + j 2 ∗ r 1 + . . . + j t − 1 ∗ r t − 2 ) r ≡ δ (δ^{α})^r((ρ^s)^{j_1+j_2*r^1+...+j_{t-1}*r^{t-2} } )^r\equiv δ (δα)r((ρs)j1+j2∗r1+...+jt−1∗rt−2)r≡δ
得到最终结果:
δ α ( ρ s ) j 1 + j 2 ∗ r 1 + . . . + j t − 1 ∗ r t − 2 δ^{α}(ρ^s)^{j_1+j_2*r^1+...+j_{t-1}*r^{t-2} } δα(ρs)j1+j2∗r1+...+jt−1∗rt−2
算法如下:
其实开n次方根的方法还有很多,只不过我目前只学了这一种。。。
真题实战(2019NCTF——babyRSA)
CTF三大谎言:baby、easy、warmup
题目只给了e,p,q,c
然而e|p-1,e|q-1,根本无从下手。
其实我们可以先用中国剩余定理展开
m e ≡ c m o d p m^e \equiv c\ mod\ p me≡c mod p m e ≡ c m o d q m^e \equiv c\ mod\ q me≡c mod q
由于e比较小,所以可以用上述开n次方的方法,在模p和模q中分别找到一个0x1337次方的根 m 0 m_0 m0。
然而实际上0x1337开根会产生1337个根,那么如何找到剩余的0x1336个根呢?
根据公式:
(
x
p
−
1
e
)
e
≡
x
q
−
1
≡
1
(x^{\frac{p-1}{e}})^e\equiv x^{q-1}\equiv 1
(xep−1)e≡xq−1≡1
所以可以通过用 m 0 ∗ x p − 1 e m_0*x^{\frac{p-1}{e}} m0∗xep−1的方式找到剩余的0x1336个根。
最后模p的0x1337个根和模q的0x1337个根,一共有4919*4919=24196561种组合,再利用中国剩余定理,就能算出最终的flag。
提示:
list=set()
while(len(list)<r):
p=pow(random.randint(1,q-1),(q-1)/r,q)
list.add(p)
这几行代码可以保证生成的子根不会有重复
最终结果:
后记
第一次学到了这种开方的姿势,眼光宽广了很多,以后也会继续努力滴!