Crypto_[NPUCTF2020]共 模 攻 击

[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
'''

先求一求hint是什么。

分析程序,发现算是有两段加密;第二层加密显然是共模攻击即可

第一层加密是 m 256 ≡ c   ( m o d   p ) m^{256}\equiv c~(mod~p) m256c (mod p);这里的 p p p是只是一个大素数

最先开始以为也是正常的RSA求解,但是求d的时候发现 e = 256 e=256 e=256 f a i ( p ) fai(p) fai(p)不互素;求了公约数等于4,本以为当 e / 4 e/4 e/4之后就可以继续计算但是发现依然 e / 4 e/4 e/4 f a i ( p ) fai(p) fai(p)不互素;之后发现 e = 256 = 2 8 e=256=2^8 e=256=28也就是说要除以 4 4 4^4 44之后才满足互素条件…显然用正常的RSA求解行不通

用一个函数sympy.nthroots_mod(c,e,n)可以直接求解 m m m​,但是目前我所了解的是这个函数只能用于e不是很大的时候并且正常的RSA求解行不通的时候;

h i n t hint hint

b’m.bit_length() < 400’

再看task.py文件

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
'''

hint给出flag的字节长度;试着应用Coppersmith定理(在一个e阶的mod n多项式f(x)中,如果有一个根小于 n 1 / e n^{1/e} n1/e​,就可以运用一个O(log n)的算法求出这些根)而所谓的 O ( l o g   n ) O(log ~n) O(log n)​的算法是需要自己构造的,题目一般不会给出,构造一个只有m作为未知数的同余式,满足 m < n 1 / e m<n^{1/e} m<n1/e​条件即可计算出 m m m​​(计算一下得到 m < n 1 / e = T r u e m<n^{1/e}=True m<n1/e=True​)

试着构造关于 m m m的同余式

已知:

c 1 ≡ m p ( m o d   n ) c_1\equiv m^p (mod~n) c1mp(mod n)

c 2 ≡ m q ( m o d   n ) c_2\equiv m^q(mod~n) c2mq(mod n)

应用费马小定理: a p − 1 ≡ 1 ( m o d   p ) a^{p-1}\equiv 1(mod~p) ap11(mod p)

m p ≡ m ( m o d   p ) m^p\equiv m(mod~p) mpm(mod p)

m q ≡ m ( m o d   q ) m^q\equiv m(mod~q) mqm(mod q)

也即

m p = m + k 1 ∗ p m^p = m+k_1*p mp=m+k1p

m q = m + k 2 ∗ p m^q=m+k_2*p mq=m+k2p

所以

c 1 ≡ m p ≡ m + k 1 ∗ p ( m o d   n ) c_1\equiv m^p\equiv m+k_1*p(mod~n) c1mpm+k1p(mod n)

c 2 ≡ m q ≡ m + k 2 ∗ q ( m o d   n ) c_2\equiv m^q\equiv m+k_2*q(mod~n) c2mqm+k2q(mod n)

也即

c 1 = m + k 1 ∗ p + k 1 ′ ∗ p ∗ q c_1=m+k_1*p+k_1'*p*q c1=m+k1p+k1pq

c 2 = m + k 2 ∗ p + k 2 ′ ∗ p ∗ q c_2= m+k_2*p+k_2'*p*q c2=m+k2p+k2pq

实际上等价于

c 1 = m + k ∗ p c_1=m+k*p c1=m+kp

c 2 = m + k ′ ∗ q c_2=m+k'*q c2=m+kq

构造关于m的同余式,已知的模数是n,所以要尽量让构造出的m的等式是n的倍数(也就是模n等于0)当然也可以是余数不等于0的情况但是一定要已知余数是多少(这里似乎没有什么数学定理可以应用,大概率就是直接构造一个等式等于n的倍数即可)

c 1 ∗ c 2 = m 2 + ( k ∗ p + k ′ ∗ q ) ∗ m + k ∗ k ′ ∗ n c_1*c_2=m^2+(k*p+k'*q)*m+k*k'*n c1c2=m2+(kp+kq)m+kkn

m ∗ ( c 1 + c 2 ) = 2 m 2 + ( k ∗ p + k ′ ∗ q ) ∗ m m*(c_1+c_2)=2m^2+(k*p+k'*q)*m m(c1+c2)=2m2+(kp+kq)m

合并这两个等式

m 2 − m ∗ ( c 1 + c 2 ) + c 1 ∗ c 2 = k ∗ k ′ ∗ n ≡ 0 ( m o d   n ) m^2-m*(c_1+c_2)+c_1*c_2=k*k'*n\equiv 0(mod~n) m2m(c1+c2)+c1c2=kkn0(mod n)

系数已知;进行sage运算

代码实现:

import gmpy2
from Crypto.Util.number import *
from sympy import *
from sympy.polys.polyoptions import Flag
# 求hint
p = 107316975771284342108362954945096489708900302633734520943905283655283318535709
n = 6807492006219935335233722232024809784434293293172317282814978688931711423939629682224374870233587969960713638310068784415474535033780772766171320461281579
e1 = 2303413961 
c1 = 1754421169036191391717309256938035960912941109206872374826444526733030696056821731708193270151759843780894750696642659795452787547355043345348714129217723
e2 = 2622163991 
c2 = 1613454015951555289711148366977297613624544025937559371784736059448454437652633847111272619248126613500028992813732842041018588707201458398726700828844249

_,s,t = gmpy2.gcdext(e1,e2)
c = pow(c1,s,n)*pow(c2,t,n) % n
e = 256
m = nthroot_mod(c,e,p)
print(long_to_bytes(m))
# 错误想法
# fai_p = p - 1
# com = gmpy2.gcd(e,fai_p)
# print(com)
# d = gmpy2.invert(e//com,fai_p)
# m = pow(c,d,p)

# 求flag
n = 128205304743751985889679351195836799434324346996129753896234917982647254577214018524580290192396070591032007818847697193260130051396080104704981594190602854241936777324431673564677900773992273463534717009587530152480725448774018550562603894883079711995434332008363470321069097619786793617099517770260029108149
c1 = 96860654235275202217368130195089839608037558388884522737500611121271571335123981588807994043800468529002147570655597610639680977780779494880330669466389788497046710319213376228391138021976388925171307760030058456934898771589435836261317283743951614505136840364638706914424433566782044926111639955612412134198
c2 = 9566853166416448316408476072940703716510748416699965603380497338943730666656667456274146023583837768495637484138572090891246105018219222267465595710692705776272469703739932909158740030049375350999465338363044226512016686534246611049299981674236577960786526527933966681954486377462298197949323271904405241585

sum = c1 + c2
pro = c1*c2
# sage
# R.<m> = Zmod(n)[]
# f = m^2 - sum*m + pro
# flag = f.smallroots(2^400)[0] #括号内的是根的边界,我们所求的根也就是m,这里hint已经给出了m.bit_length()<400
flag = 4242839043019782000788118887372132807371568279472499477998758466224002905442227156537788110520335652385855
print(long_to_bytes(flag))

思路来源:BUU_NPUCTF2020]共 模 攻 击 - 灰信网(软件开发博客聚合) (freesion.com)

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

M3ng@L

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值