2021“巅峰极客”网络安全技能挑战赛
crtrsa
题目:
from secret import flagn,p,q
#p and q are two primes generated by getPrime
import random
def key_gen():
while True:
dp = random.randint(1,1<<20)
dq = random.randint(1,q-1)
if gcd(dp, p - 1) == 1 and gcd(dq, q - 1) == 1:
d = crt([dp,dq],[p-1,q-1])
phi = (p-1)*(q-1)
R = Integers(phi)
e = R(d)^-1
return p*q,e
n,e = key_gen()
print e
print n
print pow(flagn,int(e),n)
'''
e = 2953544268002866703872076551930953722572317122777861299293407053391808199220655289235983088986372630141821049118015752017412642148934113723174855236142887
N = 6006128121276172470274143101473619963750725942458450119252491144009018469845917986523007748831362674341219814935241703026024431390531323127620970750816983
flag = 4082777468662493175049853412968913980472986215497247773911290709560282223053863513029985115855416847643274608394467813391117463817805000754191093158289399
'''
可以看到dp的范围是在[1,1048576],这个范围应该是可以进行穷举的。那如何利用这一点呢?
首先由以下公式和定理:
①
e
∗
d
≡
1
(
m
o
d
φ
(
n
)
)
=
=
>
e
∗
d
≡
1
(
m
o
d
(
p
−
1
)
)
)
②
d
p
≡
d
(
m
o
d
(
p
−
1
)
)
欧
拉
定
理
:
设
m
是
大
于
1
的
整
数
,
如
果
a
是
满
足
(
a
,
m
)
=
1
的
整
数
,
则
a
φ
(
m
)
≡
1
(
m
o
d
m
)
①e*d≡1\quad (mod\ φ(n)) ==>e*d≡1\quad (mod\ (p-1)))\\ ②dp≡d\quad (mod\ (p-1))\\ 欧拉定理: \\设m是大于1的整数,如果a是满足(a,m) = 1的整数,则\\ a^{φ(m)}≡1\quad(mod\ m)
①e∗d≡1(mod φ(n))==>e∗d≡1(mod (p−1)))②dp≡d(mod (p−1))欧拉定理:设m是大于1的整数,如果a是满足(a,m)=1的整数,则aφ(m)≡1(mod m)
由①,②得
e
∗
d
p
≡
1
(
m
o
d
(
p
−
1
)
)
=
=
>
e
∗
d
p
=
1
+
k
∗
(
p
−
1
)
e*dp≡1\quad(mod\quad(p-1))\\ ==> e*dp=1+k*(p-1)
e∗dp≡1(mod(p−1))==>e∗dp=1+k∗(p−1)
根据欧拉定理有(m∈(1,p),p是素数,即(m,p) = 1):
m
φ
(
p
)
≡
m
p
−
1
≡
1
(
m
o
d
p
)
m^{φ(p)}≡m^{p-1}≡1\quad(mod\ p)
mφ(p)≡mp−1≡1(mod p)
进一步化简:
m
p
−
1
≡
1
(
m
o
d
p
)
=
=
>
m
k
∗
(
p
−
1
)
+
1
≡
m
(
m
o
d
p
)
=
=
>
m
e
∗
d
p
≡
m
(
m
o
d
p
)
m^{p-1} ≡ 1\quad(mod\ p) ==> m^{k*(p-1)+1} ≡ m\quad(mod\ p)==>m^{e*dp} ≡ m\quad(mod\ p)
mp−1≡1(mod p)==>mk∗(p−1)+1≡m(mod p)==>me∗dp≡m(mod p)
所以有
p
∣
m
e
∗
d
p
−
m
p|m^{e * dp} - m
p∣me∗dp−m,又有p|n,进一步得出
g
c
d
(
n
,
m
e
∗
d
p
−
m
)
=
p
gcd(n,m^{e * dp} - m) = p
gcd(n,me∗dp−m)=p。
综上:我们可以随意选取m∈(1,p),通过枚举dp,根据 p = g c d ( n , m e ∗ d p − m ) ! = 1 p = gcd(n,m^{e * dp} - m) != 1 p=gcd(n,me∗dp−m)!=1来求出p,进而分解n。
代码:
import gmpy2
from Crypto.Util.number import *
e = 2953544268002866703872076551930953722572317122777861299293407053391808199220655289235983088986372630141821049118015752017412642148934113723174855236142887
n = 6006128121276172470274143101473619963750725942458450119252491144009018469845917986523007748831362674341219814935241703026024431390531323127620970750816983
c = 4082777468662493175049853412968913980472986215497247773911290709560282223053863513029985115855416847643274608394467813391117463817805000754191093158289399
#dp = d % (p-1) dq = d % (q-1)
m = 10000001
for dp in range(1,(1<<20)+1):
print(dp)
temp = pow(m,e*dp,n) - m
p = gmpy2.gcd(n,temp)
if p != 1:
q = n // p
try:
d = gmpy2.invert(e,(p-1)*(q-1))
flag = long_to_bytes(pow(c,d,n))
if b'flag' in flag or b'ctf' in flag:
print(flag)
break
except:
pass
#dp = 915155
#b'flag{d67fde91-f6c0-484d-88a4-1778f7fa0c05}'