import gmpy2 from secret import flag from Crypto.Util.number import *
defgenerate(): p = getStrongPrime(2048) whileTrue: f = getRandomNBitInteger(1024) g = getStrongPrime(768) h = gmpy2.invert(f, p) * g % p return (p, f, g, h)
defencrypt(plaintext, p, h): m = bytes_to_long(plaintext) r = getRandomNBitInteger(1024) c = (r * h + m) % p return c
p, f, g, h = generate() c = encrypt(flag, p, h) print('h =', h) print('p =', p) print('c =', c) """ h = 15920807412952692847985174177588211960281948838307253586797239960508125481987882224605864406372742338485793530131031795389776531751200676051949170672004649326503467447518123006808297262753280286176914568491022298784897984879823370933511805201516939304165656461649805404345353075803763209810253831770288511818668398003443730898078080711296567200650962390927974385735100849320021423318726773493255693093044142610555698370275203822724528162516863483780170076614868308468049805668954554578089167666866242081591436319781031943877834260419842837279937368942586813623585114579680192182136454951076576180846308031147577895183 p = 29616445112694260274774681537287299269831042656521626513009034520717072986110554689452007791622053679125813101887358792411152206641110832730768759894034995329749945245036475665938165090997263055454214551943883405059392525425764609291470545536168035201657530029849113821500078015786845062143152799634844986753056256220285729693791666273618731684193516606613125066125143895019716948226556471128531174411802630235945882713680099627033330758906060609807833477234842026397619463093836747345939002210487194276855948870859245196439206070300222410002340377429280616491741559912351526804469748340235688215655559714767093336011 c = 24894154600738747801028572977171957374256712941786243361235711912410748252475712552938200529578615522555383736598357845901370674754857388874985225645650913059820754690696257510209172235875364336887131653254443697948965333434213242584604843844646774324930722413839123594241879178636469903372909302377061318833174246232722769872293078758804927418352848560803152544304608965368181815249876729133751310904899772060616419975025741262545479052454752165874425435226386604586446369944613258629120527951194286510228752204113015018002437399369034486123978271982779314575972603420464431960235222295086660836240988842127196837233 """
题解
根据大小关系化简
关注题目参数大小
$p: 2048 \space bit$
$f: 1024 \space bit$
$g: 768 \space bit$
$h = f^{-1}*g \mod p :2048 \space bit$
$r: 1024 \space bit$
$c = (r \cdot h + m)= (r \cdot f^{-1}*g + m) \mod p :2048 \space bit$
于是有: $$ c \cdot f = r \cdot g + m \cdot f \mod p $$ 让我们关注等式右侧,不难发现: $r \cdot g +m \cdot f$的大小肯定不会超过$p$(2048bit)
即,这不是同余式而是等式(记$c \cdot f \space \% \space p$的结果为$c’$): $$ c’= r \cdot g + m \cdot f $$ 若我们有了参数$f、g$,那么这题便可以绕过r求解m了,流程如下:
等式两边同时对g取余
$c’= m \cdot f \mod g$
等式两边同时乘f对g的逆
$c’ \cdot f^{-1}= m \mod g$
一般来说flag不会太大,模g有768bit比m大,如上运算便可以得到m的真值。
那么我们该如何求解f、g呢?
答案很显然了,格。
利用格求出未知量
与$f、g$同时有关系的只有如下这个式子: $$ \begin{aligned}h &= f^{-1}*g \mod p \\ h \cdot f &= g + kp \end{aligned} $$ “一个式子居然能求两个未知数吗?”,你想到。
「事实上,只要等式中参数大小足够巧妙,我们便能利用格来求解其中未知量」
先给出结论,对于如下矩阵M,对其使用LLL算法后,我们可以得到$f, g$ $$ M = \begin{bmatrix} 1 & h \\ 0 & p \end{bmatrix} $$ 那么,我们是如何写出这个矩阵的呢?
事实上,写出矩阵M的过程都是以这一句话为准则的,即:$v \cdot M = \vec w$
$v$:未知量矩阵
$M$:已知量矩阵
$\vec w$:要求量矩阵
对于本题,最容易确认的是$\vec w$, 因为我们需要求的量很明确,就是$f, g$。
所以,有: $$ \vec w = [f \space\space\space g] $$ 其次,格是通过等式来建立的,我们看向本题的关系式: $$ h \cdot f -kp= g $$ 其中,$f、k、g$为未知量,$f、g$为要求量
确定$v$,如下(一般来说,等式里能单独表示的要求量不放在未知量矩阵里,如本题中$g$): $$ v = [f \space\space\space -k ] $$ 最后,根据矩阵乘法确定$M$,如下: $$ M = \begin{bmatrix} 1 & h \\ 0 & p \end{bmatrix} $$ 总的看来,我们写出如下$v \cdot M = \vec w$ $$ \begin{bmatrix} f & -k \end{bmatrix} \begin{bmatrix} 1 & h \\ 0 & p \end{bmatrix} = \begin{bmatrix} f & g \end{bmatrix} $$ 值得一说,在确认已知量矩阵$M$时,依赖的等式有:
import libnum h = 15920807412952692847985174177588211960281948838307253586797239960508125481987882224605864406372742338485793530131031795389776531751200676051949170672004649326503467447518123006808297262753280286176914568491022298784897984879823370933511805201516939304165656461649805404345353075803763209810253831770288511818668398003443730898078080711296567200650962390927974385735100849320021423318726773493255693093044142610555698370275203822724528162516863483780170076614868308468049805668954554578089167666866242081591436319781031943877834260419842837279937368942586813623585114579680192182136454951076576180846308031147577895183 p = 29616445112694260274774681537287299269831042656521626513009034520717072986110554689452007791622053679125813101887358792411152206641110832730768759894034995329749945245036475665938165090997263055454214551943883405059392525425764609291470545536168035201657530029849113821500078015786845062143152799634844986753056256220285729693791666273618731684193516606613125066125143895019716948226556471128531174411802630235945882713680099627033330758906060609807833477234842026397619463093836747345939002210487194276855948870859245196439206070300222410002340377429280616491741559912351526804469748340235688215655559714767093336011 c = 24894154600738747801028572977171957374256712941786243361235711912410748252475712552938200529578615522555383736598357845901370674754857388874985225645650913059820754690696257510209172235875364336887131653254443697948965333434213242584604843844646774324930722413839123594241879178636469903372909302377061318833174246232722769872293078758804927418352848560803152544304608965368181815249876729133751310904899772060616419975025741262545479052454752165874425435226386604586446369944613258629120527951194286510228752204113015018002437399369034486123978271982779314575972603420464431960235222295086660836240988842127196837233
# 求解f, g Ge = matrix(ZZ, [[1, h], [0, p]]) f, g = Ge.LLL()[0] # SVP # 利用f, g求解m f = abs(f) g = abs(g) c_ = (c*f)%p m = c_*inverse_mod(f, g)%g print(libnum.n2s(int(m)))