BUUCTF 每日打卡 2022-1-16

引言

填坑

[羊城杯 2020]Power

加密代码如下:

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

p = getPrime(512)
q = getPrime(512)
n = p**4*q

e = 0x10001
phi = gmpy2.lcm(p - 1, q - 1)
d = gmpy2.invert(e, phi)
dp = d % (p - 1)
m = bytes_to_long(flag)
c = pow(m, e, n)
print "dp = " + str(dp)
print "c = " + str(c)

y = 449703347709287328982446812318870158230369688625894307953604074502413258045265502496365998383562119915565080518077360839705004058211784369656486678307007348691991136610142919372779782779111507129101110674559235388392082113417306002050124215904803026894400155194275424834577942500150410440057660679460918645357376095613079720172148302097893734034788458122333816759162605888879531594217661921547293164281934920669935417080156833072528358511807757748554348615957977663784762124746554638152693469580761002437793837094101338408017407251986116589240523625340964025531357446706263871843489143068620501020284421781243879675292060268876353250854369189182926055204229002568224846436918153245720514450234433170717311083868591477186061896282790880850797471658321324127334704438430354844770131980049668516350774939625369909869906362174015628078258039638111064842324979997867746404806457329528690722757322373158670827203350590809390932986616805533168714686834174965211242863201076482127152571774960580915318022303418111346406295217571564155573765371519749325922145875128395909112254242027512400564855444101325427710643212690768272048881411988830011985059218048684311349415764441760364762942692722834850287985399559042457470942580456516395188637916303814055777357738894264037988945951468416861647204658893837753361851667573185920779272635885127149348845064478121843462789367112698673780005436144393573832498203659056909233757206537514290993810628872250841862059672570704733990716282248839
g = 2
x = 2019*p**2 + 2020*p**3 + 2021*p**4
c1 = pow(g, x, y)
print "c1 = " + str(c1)

# dp = 3272293505696712831419859641571956066667516012597886098021642320155056349966612629986261146617139998624603483170466852538289743936225789351270153550594329
# c = 22524257534087703614496632403022329621384173069680778965750290698059674588465640878754707363673789674111671270645152584118206145007310499274423606886261969807360070526126452646719628307689968971699215841867636770320159256301550908771135042912287955209485328267670825390080110910391913063177323585204392804538642393453388536211144485389902591029350060800993352969569703901717308330574394200996651534321547814313195218895547718815009876393987398738932001924661338796059973950012706427109598830049455186171345179840564502215531573714428772608739268313985559628612004439028014417408631851880698512023740903181116906766066951473942201698375224240271523568161242951730224901227589413731025281719101368668617497947995579443908773425555177346524678673641140157885033923288401884
# c1 = 290707924192892686920253390955676600323331633814839708838347288502692494699485764473635783441705302268064111648851157070038783719749721994682837294625334517914882191486257362565066745587415388291939979195637720350919055988532145531805200483161599965215275808797976727969023747299578173497083532351976473770041800769265319548352841139802163279116490053292316399038329210043455932786945180855178341998049756983301499491011851026499269682821602212971062877270127451987836730083380463825717889123804613394241190839837791281657872259492589868751745327696030438893865069941066073554427558697972551085353027574529823439588670263047287131740802375738439636789806332323994866753085014446479034974063195632514803340511247735647970572837053148490258113394359072976858781060349776921428492973183958437965966963122069107876143476772436757554253049619918403996315720023020827394900507088006299225934263699192253079026440287311664705744424959801981503191480257138833694306501816837037995549817186335377411638035575004595417788588264823861850877111374085336446477943372458378834664678094751978400910288151519902977326995118727880223621964441498323865158898463327323193833062919619201107279964663654606753750042791368210261574897455830722232022689695292080269205470491791950839486861811469879413313773338916781857981641910031441448964144000585506870170898052132929034349451945051362244755750988705018897859238859476967568556992146975789444151432386692872801263000639711599152191790766776280

看到dp,有点像dp泄露问题,但是发现n=p**4*q,而phi = gmpy2.lcm(p - 1, q - 1),而且也没有给公钥n,显然不能那么做
首先,需要根据下半部分代码求出p
运用sympy离散对数求出x

import sympy

y = 449703347709287328982446812318870158230369688625894307953604074502413258045265502496365998383562119915565080518077360839705004058211784369656486678307007348691991136610142919372779782779111507129101110674559235388392082113417306002050124215904803026894400155194275424834577942500150410440057660679460918645357376095613079720172148302097893734034788458122333816759162605888879531594217661921547293164281934920669935417080156833072528358511807757748554348615957977663784762124746554638152693469580761002437793837094101338408017407251986116589240523625340964025531357446706263871843489143068620501020284421781243879675292060268876353250854369189182926055204229002568224846436918153245720514450234433170717311083868591477186061896282790880850797471658321324127334704438430354844770131980049668516350774939625369909869906362174015628078258039638111064842324979997867746404806457329528690722757322373158670827203350590809390932986616805533168714686834174965211242863201076482127152571774960580915318022303418111346406295217571564155573765371519749325922145875128395909112254242027512400564855444101325427710643212690768272048881411988830011985059218048684311349415764441760364762942692722834850287985399559042457470942580456516395188637916303814055777357738894264037988945951468416861647204658893837753361851667573185920779272635885127149348845064478121843462789367112698673780005436144393573832498203659056909233757206537514290993810628872250841862059672570704733990716282248839
c1 = 290707924192892686920253390955676600323331633814839708838347288502692494699485764473635783441705302268064111648851157070038783719749721994682837294625334517914882191486257362565066745587415388291939979195637720350919055988532145531805200483161599965215275808797976727969023747299578173497083532351976473770041800769265319548352841139802163279116490053292316399038329210043455932786945180855178341998049756983301499491011851026499269682821602212971062877270127451987836730083380463825717889123804613394241190839837791281657872259492589868751745327696030438893865069941066073554427558697972551085353027574529823439588670263047287131740802375738439636789806332323994866753085014446479034974063195632514803340511247735647970572837053148490258113394359072976858781060349776921428492973183958437965966963122069107876143476772436757554253049619918403996315720023020827394900507088006299225934263699192253079026440287311664705744424959801981503191480257138833694306501816837037995549817186335377411638035575004595417788588264823861850877111374085336446477943372458378834664678094751978400910288151519902977326995118727880223621964441498323865158898463327323193833062919619201107279964663654606753750042791368210261574897455830722232022689695292080269205470491791950839486861811469879413313773338916781857981641910031441448964144000585506870170898052132929034349451945051362244755750988705018897859238859476967568556992146975789444151432386692872801263000639711599152191790766776280
x = sympy.discrete_log(y, c1, 2)
print(x)

可能要等几分钟,结果为:

x = 5535722692962580764045545539105119140941061679289569420988353884209653851308860058948669740693107863231179565602072744542122031789184119031739723962825082929025825322421201364211726001366490949760887367407718763255964735567971493859197583624076478457865073449246835949075135223468616834636386958924709024763349115622062848212445867198457630368236782421195503713107838541903829979118327675371550868768159024260793541264335548489228744367609071659968450303895118817379316060805148754136917043160175570565717388336822960389664337656603584425629662613786203920234401824957121860225422901340950436355650311392398098947210940

然后求出p,sage代码如下:

y = 449703347709287328982446812318870158230369688625894307953604074502413258045265502496365998383562119915565080518077360839705004058211784369656486678307007348691991136610142919372779782779111507129101110674559235388392082113417306002050124215904803026894400155194275424834577942500150410440057660679460918645357376095613079720172148302097893734034788458122333816759162605888879531594217661921547293164281934920669935417080156833072528358511807757748554348615957977663784762124746554638152693469580761002437793837094101338408017407251986116589240523625340964025531357446706263871843489143068620501020284421781243879675292060268876353250854369189182926055204229002568224846436918153245720514450234433170717311083868591477186061896282790880850797471658321324127334704438430354844770131980049668516350774939625369909869906362174015628078258039638111064842324979997867746404806457329528690722757322373158670827203350590809390932986616805533168714686834174965211242863201076482127152571774960580915318022303418111346406295217571564155573765371519749325922145875128395909112254242027512400564855444101325427710643212690768272048881411988830011985059218048684311349415764441760364762942692722834850287985399559042457470942580456516395188637916303814055777357738894264037988945951468416861647204658893837753361851667573185920779272635885127149348845064478121843462789367112698673780005436144393573832498203659056909233757206537514290993810628872250841862059672570704733990716282248839
num = 5535722692962580764045545539105119140941061679289569420988353884209653851308860058948669740693107863231179565602072744542122031789184119031739723962825082929025825322421201364211726001366490949760887367407718763255964735567971493859197583624076478457865073449246835949075135223468616834636386958924709024763349115622062848212445867198457630368236782421195503713107838541903829979118327675371550868768159024260793541264335548489228744367609071659968450303895118817379316060805148754136917043160175570565717388336822960389664337656603584425629662613786203920234401824957121860225422901340950436355650311392398098947210940
R.<x> = PolynomialRing(GF(y))
f = 2019*x**2+2020*x**3+2021*x**4-num
f.roots()

结果为较小的根:
在这里插入图片描述
看了看大佬的博客,找到了类似的内容:在这里插入图片描述
但是我不知道b是什么,于是就去找了wp

解法一

根据wp,因为 c ≡ m e   m o d   n c\equiv m^e\space mod \space n cme mod n d p ≡ d   m o d   p − 1 d_p\equiv d\space mod \space p-1 dpd mod p1
所以
c d p ≡ m e d p   m o d   n c^{d_p} \equiv m^{ed_p} \space mod \space n cdpmedp mod n
进而
c d p   m o d   p ≡ m e d p   m o d   p c^{d_p} \space mod \space p \equiv m^{ed_p} \space mod \space p cdp mod pmedp mod p
又因为 e d ≡ 1   m o d   l c m ( p − 1 , q − 1 ) ed \equiv 1 \space mod \space lcm(p-1, q-1) ed1 mod lcm(p1,q1),所以
e d p ≡ e d   m o d   ( p − 1 ) ≡ 1   m o d   ( p − 1 ) ed_p\equiv ed \space mod \space (p-1) \equiv 1 \space mod \space (p-1) edped mod (p1)1 mod (p1)
从而 ∃ k ∈ Z \exists k\in \mathbb{Z} kZ s . t . s.t. s.t.
c d p   m o d   p ≡ m 1 + k ( p − 1 )   m o d   p c^{d_p} \space mod \space p \equiv m^{1+k(p-1)} \space mod \space p cdp mod pm1+k(p1) mod p
又由费马小定理, m p − 1 ≡ 1   m o d   p m^{p-1}\equiv 1 \space mod \space p mp11 mod p,所以
m ≡ c d p   m o d   p m\equiv c^{d_p} \space mod \space p mcdp mod p
解密代码如下:

from Crypto.Util.number import *

x = 5535722692962580764045545539105119140941061679289569420988353884209653851308860058948669740693107863231179565602072744542122031789184119031739723962825082929025825322421201364211726001366490949760887367407718763255964735567971493859197583624076478457865073449246835949075135223468616834636386958924709024763349115622062848212445867198457630368236782421195503713107838541903829979118327675371550868768159024260793541264335548489228744367609071659968450303895118817379316060805148754136917043160175570565717388336822960389664337656603584425629662613786203920234401824957121860225422901340950436355650311392398098947210940
p = 7234391427703598327916723159145232922047935397302241978344500497098972068808591685717500902909442183573763273395725479516998210374727754578133587007330339
dp = 3272293505696712831419859641571956066667516012597886098021642320155056349966612629986261146617139998624603483170466852538289743936225789351270153550594329
c = 22524257534087703614496632403022329621384173069680778965750290698059674588465640878754707363673789674111671270645152584118206145007310499274423606886261969807360070526126452646719628307689968971699215841867636770320159256301550908771135042912287955209485328267670825390080110910391913063177323585204392804538642393453388536211144485389902591029350060800993352969569703901717308330574394200996651534321547814313195218895547718815009876393987398738932001924661338796059973950012706427109598830049455186171345179840564502215531573714428772608739268313985559628612004439028014417408631851880698512023740903181116906766066951473942201698375224240271523568161242951730224901227589413731025281719101368668617497947995579443908773425555177346524678673641140157885033923288401884
print(long_to_bytes(pow(c, dp, p)))

结果为:
在这里插入图片描述

解法二

解出来之后,又去研究了大佬的博客(解法一的推导实在想不到),发现类似的问题其实有专门的分类,叫塔卡基体系(Takagi’s Scheme),是一种多指数RSA加密的变种(a variant of multi-power RSA)
它使用的公钥模数 N = p b − 1 q , b ≥ 3 N=p^{b-1}q, b\geq 3 N=pb1q,b3,且私钥 d d d和公钥 e e e满足 e d ≡ 1 λ ′ ( N ) , λ ′ ( N ) = l c m ( p − 1 , q − 1 ) ed\equiv 1 \lambda '(N), \lambda '(N)=lcm(p-1, q-1) ed1λ(N),λ(N)=lcm(p1,q1),不同于常规RSA的 λ ( N ) = φ ( N ) \lambda(N)=\varphi(N) λ(N)=φ(N),所以 m e d ≢ m   m o d   N m^{ed}\not\equiv m\space mod \space N medm mod N
因此,就需要先部分解出 m p b − 1 ≡ m   m o d   p b − 1 m_{p^{b-1}}\equiv m\space mod \space p^{b-1} mpb1m mod pb1 m q ≡ m   m o d   q m_q\equiv m\space mod \space q mqm mod q,然后用中国剩余定理解出 m   m o d   N m\space mod \space N m mod N
但要解出 m p b − 1 m_{p^{b-1}} mpb1,就需要先做一些额外工作,特别地,需要用到亨泽尔引理(Hensel lifting)

亨泽尔引理(Hensel lifting)

f ( x ) {\displaystyle f(x)} f(x)为整系数多项式, k k k为不少于2的整数, p p p为质数。若整数 r r r是下面同余式的根:
f ( r ) ≡ 0   m o d   p k − 1 f(r)\equiv 0\space mod \space p^{k-1} f(r)0 mod pk1
对于
f ( r + t p k − 1 ) ≡ 0   m o d   p k ⋯ ( ∗ ) {\displaystyle f(r+tp^{k-1})\equiv 0\space mod \space {p^{k}}}\cdots(*) f(r+tpk1)0 mod pk()
由泰勒公式,
f ( r + t p k − 1 ) = f ( r ) + t p k − 1 f ′ ( r ) + 1 2 t 2 p 2 ( k − 1 ) f ′ ′ ( r ) + 1 6 t 3 p 3 ( k − 1 ) f ′ ′ ′ ( r ) + ⋯ {\displaystyle f(r+tp^{k-1})=f(r)+tp^{k-1}f'(r)+{\frac {1}{2}}t^{2}p^{2(k-1)}f''(r)+{\frac {1}{6}}t^{3}p^{3(k-1)}f'''(r)+\cdots} f(r+tpk1)=f(r)+tpk1f(r)+21t2p2(k1)f(r)+61t3p3(k1)f(r)+
从第三项开始,都必能被 p k {\displaystyle p^{k}} pk整除。因此,
f ( r + t p k − 1 ) ≡ f ( r ) + t p k − 1 f ′ ( r )   m o d   p k {\displaystyle f(r+tp^{k-1})\equiv f(r)+tp^{k-1}f'(r)\space mod \space {p^{k}}} f(r+tpk1)f(r)+tpk1f(r) mod pk
所以有以下三种情况:
f ′ ( r ) ≢ 0   m o d   p {\displaystyle f'(r)\not \equiv 0\space mod \space p} f(r)0 mod p,则存在唯一的整数 0 ≤ t ≤ p − 1 {\displaystyle 0\leq t\leq p-1} 0tp1使得 ( ∗ ) (*) ()成立。 t f ′ ( r ) ≡ − ( f ( r ) / p k − 1 )   m o d   p {\displaystyle tf'(r)\equiv -(f(r)/p^{k-1})\space mod \space p} tf(r)(f(r)/pk1) mod p
f ′ ( r ) ≡ 0   m o d   p {\displaystyle f'(r)\equiv 0\space mod \space p} f(r)0 mod p f ( r ) ≡ 0   m o d   p k {\displaystyle f(r)\equiv 0\space mod \space {p^{k}}} f(r)0 mod pk,则 ( ∗ ) (*) ()对任意整数t成立。
f ′ ( r ) ≡ 0   m o d   p {\displaystyle f'(r)\equiv 0\space mod \space p} f(r)0 mod p f ( r ) ≢ 0   m o d   p k {\displaystyle f(r)\not \equiv 0\space mod \space {p^{k}}} f(r)0 mod pk,则 ( ∗ ) (*) ()无整数解。
亨泽尔引理是数学中模算术的一个结论。亨泽尔引理说明,如果一个模p(p是给定的质数)的多项式方程有一个单根,则可以通过这个根求出该方程在模p的更高次方时的根。在完备交换环(包括p进数)中,亨泽尔引理被看作是类似于牛顿法的渐进求根方法

算法的正确性

具体可以参考原论文(T. Takagi. A fast RSA-type public-key primitive modulo pkq using Hensel lifting. IEICE Transactions, 87-A(1):94–101, 2004.),可以在百度文库免费看到
原文中的算法描述与上述略有不同:
在这里插入图片描述
注意上述算法(Algorithm10.1)仅为解出部分明文(the partial decryption m p b − 1 m_p^{b−1} mpb1),原文给出的算法可以解出全部明文 m m m
这里做简单的描述(原文中的解出部分明文(the partial decryption m p b − 1 m_p^{b−1} mpb1))
c p = c   m o d   p k , m p = m   m o d   p k c_p=c\space mod \space p^k, m_p=m\space mod \space p^k cp=c mod pk,mp=m mod pk,那么 c p ≡ m p e   m o d   p k c_p\equiv m_p^e\space mod \space p^k cpmpe mod pk,再对 m p m_p mp做p进制展开:
m p ≡ K 0 + p K 1 + p 2 K 2 + ⋯ + p k − 1 K k − 1   m o d   p k m_p\equiv K_0+pK_1+p^2K_2+\cdots +p^{k-1}K_{k-1}\space mod \space p^k mpK0+pK1+p2K2++pk1Kk1 mod pk
其中 K 0 , K 1 , ⋯   , K k − 1 ∈ Z K_0,K_1,\cdots ,K_{k-1}\in \mathbb{Z} K0,K1,,Kk1Z
再定义函数 f i ( x 0 , x 1 , ⋯   , x i ) = ( x 0 + p x 1 + ⋯ + p i x i ) e , i = 0 , 1 , ⋯   , k − 1 f_i(x_0,x_1,\cdots ,x_i)=(x_0+px_1+\cdots +p^ix_i)^e,i=0,1,\cdots,k-1 fi(x0,x1,,xi)=(x0+px1++pixi)e,i=0,1,,k1,则 m p ≡ f k − 1 ( x 0 , x 1 , ⋯   , x k − 1 )   m o d   p k ≡ ( x 0 + p x 1 + ⋯ + p k − 1 x k − 1 ) e   m o d   p k m_p\equiv f_{k-1}(x_0,x_1,\cdots ,x_{k-1})\space mod \space p^k\equiv (x_0+px_1+\cdots +p^{k-1}x_{k-1})^e\space mod \space p^k mpfk1(x0,x1,,xk1) mod pk(x0+px1++pk1xk1)e mod pk
A i − 1 = x 0 + p x 1 + ⋯ + p i − 1 x i − 1 , i = 0 , 1 , ⋯   , k − 1 A_{i-1}=x_0+px_1+\cdots +p^{i-1}x_{i-1},i=0,1,\cdots ,k-1 Ai1=x0+px1++pi1xi1,i=0,1,,k1,于是有如下递推关系:
f i ( x 0 , x 1 , ⋯   , x i ) ≡ A i − 1 e + p i e A i − 1 e − 1 x i   m o d   p i + 1 ≡ ( x 0 + p x 1 + ⋯ + p i − 1 x i − 1 ) e + p i e ( x 0 + p x 1 + ⋯ + p i − 1 x i − 1 ) e − 1 x i   m o d   p i + 1 \begin{aligned} &f_i(x_0,x_1,\cdots ,x_i)\equiv A_{i-1}^{e}+p^i eA_{i-1}^{e-1}x_i \space mod \space p^{i+1}\\ &\equiv (x_0+px_1+\cdots +p^{i-1}x_{i-1})^e+p^i e(x_0+px_1+\cdots +p^{i-1}x_{i-1})^{e-1}x_i \space mod \space p^{i+1} \end{aligned} fi(x0,x1,,xi)Ai1e+pieAi1e1xi mod pi+1(x0+px1++pi1xi1)e+pie(x0+px1++pi1xi1)e1xi mod pi+1
由此可以计算出 K 1 , ⋯   , K k − 1 K_1,\cdots,K_{k-1} K1,,Kk1
A 0 = K 0 , f 0 ( K 0 ) = A 0 e   m o d   p 2 A_0=K_0,f_0(K_0)=A_0^e\space mod \space p^2 A0=K0,f0(K0)=A0e mod p2,当 i = 1 i=1 i=1时,
c ≡ f 0 ( K 0 ) + p ( e A 0 e − 1   m o d   p ) x 1   m o d   p 2 c\equiv f_0(K_0)+p(eA_0^{e-1}\space mod \space p)x_1\space mod \space p^2 cf0(K0)+p(eA0e1 mod p)x1 mod p2
亨泽尔引理(Hensel lifting)
K 1 ≡ c − f 0 ( K 0 )   m o d   p 2 p ( e A 0 e − 1   m o d   p ) − 1   m o d   p K_1\equiv \frac{c-f_0(K_0)\space mod \space p^2}{p} (eA_0^{e-1}\space mod \space p)^{-1}\space mod \space p K1pcf0(K0) mod p2(eA0e1 mod p)1 mod p
以此类推,就可以求出 m p m_p mp
再由 m q = c d q   m o d   p m_q=c^{d_q}\space mod \space p mq=cdq mod p
运用中国剩余定理就可以求出完整的 m m m

对于本题

回到本题,事实上我们只要求出 m q m_q mq即可,因为 m m m实际上非常小(这也是为什么解法一只需解出 m ≡ c d p   m o d   p m\equiv c^{d_p} \space mod \space p mcdp mod p可行, m m m p p p还小,那么必然小于 p 4 p^4 p4
按照算法:
在这里插入图片描述
解密代码如下:

from Crypto.Util.number import *

p = 7234391427703598327916723159145232922047935397302241978344500497098972068808591685717500902909442183573763273395725479516998210374727754578133587007330339
dp = 3272293505696712831419859641571956066667516012597886098021642320155056349966612629986261146617139998624603483170466852538289743936225789351270153550594329
c = 22524257534087703614496632403022329621384173069680778965750290698059674588465640878754707363673789674111671270645152584118206145007310499274423606886261969807360070526126452646719628307689968971699215841867636770320159256301550908771135042912287955209485328267670825390080110910391913063177323585204392804538642393453388536211144485389902591029350060800993352969569703901717308330574394200996651534321547814313195218895547718815009876393987398738932001924661338796059973950012706427109598830049455186171345179840564502215531573714428772608739268313985559628612004439028014417408631851880698512023740903181116906766066951473942201698375224240271523568161242951730224901227589413731025281719101368668617497947995579443908773425555177346524678673641140157885033923288401884
b = 5
e = 0x10001
mp1 = pow(c, dp, p)
mp = pow(c, dp - 1, p)
for i in range(1, b - 2):
    x = pow(c - pow(mp1, e), 1, p**(i + 1))
    y = pow(x * mp * (inverse(e, p)), 1, p**(i + 1))
    mp1 = mp1 + y
print(long_to_bytes(int(mp1)))

结果相同

结语

事实上,本题m的长度仅有303位,如果设m = getRandomNBitInteger(1535),那么大概率只解出部分m是不可行的
但本题也没有途径解出q,自然也就无法用完整的方法解出m,这也算是本题的一个漏洞吧

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值