BUUCTF 每日打卡 2021-7-20

引言

[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) gcd(256,p1)解出d然后求解
但是发现 g c d ( 256 , p − 1 ) = 4 gcd(256,p-1)=4 gcd(256,p1)=4,无法用这种方法
只好找wp
原来直接用sympy库的nthroot_mod方法就行,该方法可以用来求解 x n ≡ a   m o d   p x^n \equiv a\space mod\space p xna mod 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 m256c mod 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} n1/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 c1mp mod nmp mod pqc2mq mod nmq mod pq
∃ t 1 ∈ Z \exists t_1\in \mathbb{Z} t1Z s . t . c 1 = m p + t 1 p q s.t. c_1 = m^p + t_1pq s.t.c1=mp+t1pq
于是有
c 1 ≡ m p   m o d   p c_1 \equiv m^{p}\space mod\space p c1mp mod p
费马小定理
m p ≡ m   m o d   p m^{p}\equiv m\space mod\space p mpm mod p

c 1 ≡ m   m o d   p c_1 \equiv m\space mod\space p c1m mod p
同理,有
c 2 ≡ m   m o d   q c_2 \equiv m\space mod\space q c2m mod q
∃ k 1 , k 2 ∈ Z \exists k_1,k_2\in \mathbb{Z} k1,k2Z 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} {c1=m+k1pc2=m+k2q

{ ( 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} {(c1+c2)m=2m2+(k1p+k2q)mc1c2=m2+(k1p+k2q)m+k1k2pq
① − ② ①-② 得:
( 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 (c1+c2)mc1c2=m2k1k2pq=m2k1k2n
移项,等式两边模 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 m2(c1+c2)m+c1c2=k1k2n0 mod n
所以只要在模 n n n的情况下(或者说是在整数模 n n n加法群中),求方程的根
参照wp,sage代码如下:
在这里插入图片描述
得到m直接long_to_bytes即可
结果为:
在这里插入图片描述

结语

摸了一天鱼,好累哦[doge]
关于sagemath的学习,官方文档看得挺累人的,推荐一个翻译的比较好的中文教程
油管上还找到一个入门教程,今年一月份的,用的是9.2版本,还比较新
希望继续坚持

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值