题目描述:
task:
hint:
题目分析:
- 先看hint(提示)这一部分,标题已经提示了是共模攻击,看到有e1,e2,c1,c2,n也可以想到是共模攻击,之后得到c,继续往下做
- 此时有点不知如何下手,e = 256 =
并且
gcd(e // 4,p-1) = 4
gcd(e // 4 // 4,p-1) = 4
gcd(e // 4 // 4 // 4,p-1) = 4
啊这......(这怎么去做)
- 看到别人写的,用sympy库中的nthroot_mod(c,e,n)函数可以做出来 ,目前第一次用此函数,还没什么经验,也不好多分享什么,大家多摸索吧
- hint部分的解题代码
p = 107316975771284342108362954945096489708900302633734520943905283655283318535709
n = 6807492006219935335233722232024809784434293293172317282814978688931711423939629682224374870233587969960713638310068784415474535033780772766171320461281579
e1 = 2303413961
c1 = 1754421169036191391717309256938035960912941109206872374826444526733030696056821731708193270151759843780894750696642659795452787547355043345348714129217723
e2 = 2622163991
c2 = 1613454015951555289711148366977297613624544025937559371784736059448454437652633847111272619248126613500028992813732842041018588707201458398726700828844249
import gmpy2
from Crypto.Util.number import *
from sympy import *
s,s1,s2 = gmpy2.gcdext(e1,e2)
c = pow(c1,s1,n) * pow(c2,s2,n)%n
e = 256
m = nthroot_mod(c,e,p)
print(long_to_bytes(m))
# b'm.bit_length() < 400'
知道了m的比特位小于400位
- 接下来看task,显然,根据提示,可以尝试使用coppersmith定理
'''构造关于m的同余式,已知的模数是n,所以要尽量让构造出的m的等式是n的倍数(也就是模n等于0)当然也可以是余数不等于0的情况但是一定要已知余数是多少(这里似乎没有什么数学定理可以应用,大概率就是直接构造一个等式等于n的倍数即可)'''
- 代码如下:
# sage
from Crypto.Util.number import *
n = 128205304743751985889679351195836799434324346996129753896234917982647254577214018524580290192396070591032007818847697193260130051396080104704981594190602854241936777324431673564677900773992273463534717009587530152480725448774018550562603894883079711995434332008363470321069097619786793617099517770260029108149
c1 = 96860654235275202217368130195089839608037558388884522737500611121271571335123981588807994043800468529002147570655597610639680977780779494880330669466389788497046710319213376228391138021976388925171307760030058456934898771589435836261317283743951614505136840364638706914424433566782044926111639955612412134198
c2 = 9566853166416448316408476072940703716510748416699965603380497338943730666656667456274146023583837768495637484138572090891246105018219222267465595710692705776272469703739932909158740030049375350999465338363044226512016686534246611049299981674236577960786526527933966681954486377462298197949323271904405241585
sum = c1 + c2
mult = c1 * c2
PR.<x> = PolynomialRing(Zmod(n))
# R.<x> = PolynomialRing(Zmod(n),implementation = 'NTL')
# R.<x> = Zmod(n)[]
# 上面三个都行
f = x ^ 2 + mult - sum * x
flag = f.small_roots(X = 2 ^ 400)[0] # 2 ^ 400是根的上界
print(flag)
# print(long_to_bytes(flag)
flag = 4242839043019782000788118887372132807371568279472499477998758466224002905442227156537788110520335652385855
print(long_to_bytes(flag))
收获与体会:
- 以后遇到e还算小的可以尝试用sympy.nthroot_mod(),感觉这东西还挺🐂的,哈哈哈
m = nthroot_mod(c,256,p,all_roots=True) # 所有根,列表中
print (m)
for i in m:
print (i)
hint = long_to_bytes(i)
print (hint)
- 以上copper法值得收藏(求m,m位数已知,并且c1 = m^p mod n, c2 = m^q mod n)
以下三个可以互换使用,目前还没看到局限(可能是做题少了吧)
PR.<x> = PolynomialRing(Zmod(n))
R.<x> = PolynomialRing(Zmod(n),implementation = 'NTL')
R.<x> = Zmod(n)[]