BUUCTF 每日打卡 2021-7-20

  • Post author:
  • Post category:其他




引言



[NPUCTF2020]共 模 攻 击

题目给了两个加密程序

一个是加密hint:

from gmpy2 import *
from Crypto.Util.number import *
from secret import hint

m = bytes_to_long(hint)
p = getPrime(256)
c = pow(m, 256, p)
print(p)

p, q = getPrime(256), getPrime(256)
n = p * q
e1, e2 = getPrime(32), getPrime(32)
c1, c2 = pow(c, e1, n), pow(c, e2, n)
print(n)
print(e1, c1)
print(e2, c2)

'''
107316975771284342108362954945096489708900302633734520943905283655283318535709
6807492006219935335233722232024809784434293293172317282814978688931711423939629682224374870233587969960713638310068784415474535033780772766171320461281579
2303413961 1754421169036191391717309256938035960912941109206872374826444526733030696056821731708193270151759843780894750696642659795452787547355043345348714129217723
2622163991 1613454015951555289711148366977297613624544025937559371784736059448454437652633847111272619248126613500028992813732842041018588707201458398726700828844249
'''

另一个是加密flag:

from gmpy2 import *
from Crypto.Util.number import *
from secret import flag

flag = flag.strip(b"npuctf{").strip(b"}")
m = bytes_to_long(flag)

p, q = getPrime(512), getPrime(512)
n = p * q
e1, e2 = p, q
c1, c2 = pow(m, e1, n), pow(m, e2, n)

print(n)
print(c1)
print(c2)

'''
128205304743751985889679351195836799434324346996129753896234917982647254577214018524580290192396070591032007818847697193260130051396080104704981594190602854241936777324431673564677900773992273463534717009587530152480725448774018550562603894883079711995434332008363470321069097619786793617099517770260029108149
96860654235275202217368130195089839608037558388884522737500611121271571335123981588807994043800468529002147570655597610639680977780779494880330669466389788497046710319213376228391138021976388925171307760030058456934898771589435836261317283743951614505136840364638706914424433566782044926111639955612412134198
9566853166416448316408476072940703716510748416699965603380497338943730666656667456274146023583837768495637484138572090891246105018219222267465595710692705776272469703739932909158740030049375350999465338363044226512016686534246611049299981674236577960786526527933966681954486377462298197949323271904405241585
'''

乍一看,确实很像共模攻击,但是一看这个加密指数是p和q并且未知,就知道没那么简单

首先来解密hint

第一步容易想到用共模攻击解密被加密的hint

代码如下:

import gmpy2
from Crypto.Util.number import *

# hint
e1 = 2303413961
e2 = 2622163991
c1 = 1754421169036191391717309256938035960912941109206872374826444526733030696056821731708193270151759843780894750696642659795452787547355043345348714129217723
c2 = 1613454015951555289711148366977297613624544025937559371784736059448454437652633847111272619248126613500028992813732842041018588707201458398726700828844249
p1 = 107316975771284342108362954945096489708900302633734520943905283655283318535709
n = 6807492006219935335233722232024809784434293293172317282814978688931711423939629682224374870233587969960713638310068784415474535033780772766171320461281579

gcd, s, t = gmpy2.gcdext(e1, e2)
if s < 0:
    s = -s
    c1 = gmpy2.invert(c1, n)
if t < 0:
    t = -t
    c2 = gmpy2.invert(c2, n)
c = gmpy2.powmod(c1, s, n) * gmpy2.powmod(c2, t, n) % n
print(c)

但下一步发现,加密hint的过程为

c = pow(m, 256, p)


原本是想类似于经典的RSA解密

p的欧拉函数为p-1,然后参考

[De1CTF2019]babyrsa

或者

EzRSA

,利用



g

c

d

(

256

,

p

1

)

gcd(256,p-1)






g


c


d


(


2


5


6


,




p













1


)





解出d然后求解

但是发现



g

c

d

(

256

,

p

1

)

=

4

gcd(256,p-1)=4






g


c


d


(


2


5


6


,




p













1


)




=








4





,无法用这种方法

只好找

wp


原来直接用sympy库的nthroot_mod方法就行,该方法可以用来求解



x

n

a

 

m

o

d

 

p

x^n \equiv a\space mod\space p







x










n




















a




m


o


d




p





,其中



n

,

a

,

p

n,a,p






n


,




a


,




p





为已知数

那么,有这么好的方法,能不能直接用来求解RSA问题呢?当然是不行的

因为求解本题的



m

256

c

 

m

o

d

 

p

m^{256} \equiv c\space mod\space p







m











2


5


6





















c




m


o


d




p





都要花上好几秒,求解RSA问题基本上不可能

这里附上

nthroot_mod的源代码

,感兴趣的师傅可以研究研究

完整解密代码如下:

import gmpy2
import sympy
from Crypto.Util.number import *

# hint
e1 = 2303413961
e2 = 2622163991
c1 = 1754421169036191391717309256938035960912941109206872374826444526733030696056821731708193270151759843780894750696642659795452787547355043345348714129217723
c2 = 1613454015951555289711148366977297613624544025937559371784736059448454437652633847111272619248126613500028992813732842041018588707201458398726700828844249
p1 = 107316975771284342108362954945096489708900302633734520943905283655283318535709
n = 6807492006219935335233722232024809784434293293172317282814978688931711423939629682224374870233587969960713638310068784415474535033780772766171320461281579

gcd, s, t = gmpy2.gcdext(e1, e2)
if s < 0:
    s = -s
    c1 = gmpy2.invert(c1, n)
if t < 0:
    t = -t
    c2 = gmpy2.invert(c2, n)
c = gmpy2.powmod(c1, s, n) * gmpy2.powmod(c2, t, n) % n
print(c)
m = sympy.nthroot_mod(c, 256, p1)
print(long_to_bytes(m))

结果为:

在这里插入图片描述

提示m的位数小于400,有什么用吗?

wp中说可以由此联想到Coppersmith

确实,在一些高位或低位泄露的题目中,Coppersmith是常用的手段,但是只知道位数小于400怎么用呢?

wp一下的解题过程也确实没有用到Coppersmith

不过,wp给了Coppersmith定理一个比较通俗的解释:在一个



e

e






e





阶的以



n

n






n





为模的多项式



f

(

x

)

f(x)






f


(


x


)





中,如果有一个根小于



n

1

/

e

n^{1/e}







n











1


/


e













,就可以运用一个O(log n)的算法求出这些根。其中的“阶”大概就是指(循环)群的阶

在这里重新推导一遍解题思路

由加密程序可得:





c

1

m

p

 

m

o

d

 

n

m

p

 

m

o

d

 

p

q

c

2

m

q

 

m

o

d

 

n

m

q

 

m

o

d

 

p

q

c_1 \equiv m^{p}\space mod\space n \equiv m^{p}\space mod\space pq\\ c_2 \equiv m^{q}\space mod\space n \equiv m^{q}\space mod\space pq







c










1






























m











p












m


o


d




n














m











p












m


o


d




p


q









c










2






























m











q












m


o


d




n














m











q












m


o


d




p


q











t

1

Z

\exists t_1\in \mathbb{Z}










t










1






























Z










s

.

t

.

c

1

=

m

p

+

t

1

p

q

s.t. c_1 = m^p + t_1pq






s


.


t


.



c










1




















=









m










p











+









t










1


















p


q






于是有





c

1

m

p

 

m

o

d

 

p

c_1 \equiv m^{p}\space mod\space p







c










1






























m











p












m


o


d




p









费马小定理







m

p

m

 

m

o

d

 

p

m^{p}\equiv m\space mod\space p







m











p





















m




m


o


d




p













c

1

m

 

m

o

d

 

p

c_1 \equiv m\space mod\space p







c










1





























m




m


o


d




p







同理,有





c

2

m

 

m

o

d

 

q

c_2 \equiv m\space mod\space q







c










2





























m




m


o


d




q











k

1

,

k

2

Z

\exists k_1,k_2\in \mathbb{Z}










k










1


















,





k










2






























Z










s

.

t

.

s.t.






s


.


t


.










{

c

1

=

m

+

k

1

p

c

2

=

m

+

k

2

q

\begin{cases} c_1=m+k_1p\\ c_2=m+k_2q \end{cases}








{















c










1




















=




m




+





k










1


















p









c










2




















=




m




+





k










2


















q

































{

(

c

1

+

c

2

)

m

=

2

m

2

+

(

k

1

p

+

k

2

q

)

m

c

1

c

2

=

m

2

+

(

k

1

p

+

k

2

q

)

m

+

k

1

k

2

p

q

\begin{cases} (c_1+c_2)m=2m^2+(k_1p+k_2q)m \cdots ①\\ c_1c_2=m^2+(k_1p+k_2q)m+k_1k_2pq \cdots ② \end{cases}








{














(



c










1




















+





c










2


















)


m




=




2



m










2











+




(



k










1


















p




+





k










2


















q


)


m



















c










1



















c










2




















=





m










2











+




(



k










1


















p




+





k










2


















q


)


m




+





k










1



















k










2


















p


q








































①-②


























得:





(

c

1

+

c

2

)

m

c

1

c

2

=

m

2

k

1

k

2

p

q

=

m

2

k

1

k

2

n

(c_1+c_2)m-c_1c_2=m^2-k_1k_2pq=m^2-k_1k_2n






(



c










1




















+









c










2


















)


m














c










1



















c










2




















=









m










2





















k










1



















k










2


















p


q




=









m










2





















k










1



















k










2


















n







移项,等式两边模



n

n






n





,得:





m

2

(

c

1

+

c

2

)

m

+

c

1

c

2

=

k

1

k

2

n

0

 

m

o

d

 

n

m^2-(c_1+c_2)m+c_1c_2=k_1k_2n \equiv 0\space mod \space n







m










2




















(



c










1




















+









c










2


















)


m




+









c










1



















c










2




















=









k










1



















k










2


















n













0




m


o


d




n







所以只要在模



n

n






n





的情况下(或者说是在整数模



n

n






n





加法群中),求方程的根

参照wp,sage代码如下:

在这里插入图片描述

得到m直接long_to_bytes即可

结果为:

在这里插入图片描述



结语

摸了一天鱼,好累哦[doge]

关于sagemath的学习,官方文档看得挺累人的,推荐一个翻译的比较好的

中文教程


油管上还找到一个

入门教程

,今年一月份的,用的是9.2版本,还比较新

希望继续坚持



版权声明:本文为weixin_52446095原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。