NepCTF Crypto 中学数学

NepCTF Crypto 中学数学

# 原题如下
from gmpy2 import *
from Crypto.Util.number import *
from secret import flag
p=getPrime(1024)
q=next_prime(p+(p>>500))
e=0x10001
n=p*q
c=pow(bytes_to_long(flag),e,n)
print("n=",n)
print("c=",c)

'''
n= 13776679754786305830793674359562910178503525293501875259698297791987196248336062506951151345232816992904634767521007443634017633687862289928715870204388479258679577315915061740028494078672493226329115247979108035669870651598111762906959057540508657823948600824548819666985698501483261504641066030188603032714383272686110228221709062681957025702835354151145335986966796484545336983392388743498515384930244837403932600464428196236533563039992819408281355416477094656741439388971695931526610641826910750926961557362454734732247864647404836037293509009829775634926600458845832805085222154851310850740227722601054242115507
c= 6253975396639688013947622483271226838902346034187241970785550830715516801386404802832796746428068354515287579293520381463797045055114065533348514688044281004266071342722261719304097175009672596062130939189624163728328429608123325223000160428261082507446604698345173189268359115612698883860396660563679801383563588818099088505120717238037463747828729693649297904035253985982099474025883550074375828799938384533606092448272306356003096283602697757642323962299153853559914553690456801745940925602411053578841756504799815771173679267389055390097241148454899265156705442028845650177138185876173539754631720573266723359186
'''
# 导库
from libnum import invmod,n2s
from gmpy2 import iroot,mpz
from sympy import symbols,solve,expand,isprime,nextprime,prevprime,sqrt
from libnum import len_in_bits
from tqdm import tqdm
import sympy
#expand 用来展开函数
# 添加变量
n = 13776679754786305830793674359562910178503525293501875259698297791987196248336062506951151345232816992904634767521007443634017633687862289928715870204388479258679577315915061740028494078672493226329115247979108035669870651598111762906959057540508657823948600824548819666985698501483261504641066030188603032714383272686110228221709062681957025702835354151145335986966796484545336983392388743498515384930244837403932600464428196236533563039992819408281355416477094656741439388971695931526610641826910750926961557362454734732247864647404836037293509009829775634926600458845832805085222154851310850740227722601054242115507
c = 6253975396639688013947622483271226838902346034187241970785550830715516801386404802832796746428068354515287579293520381463797045055114065533348514688044281004266071342722261719304097175009672596062130939189624163728328429608123325223000160428261082507446604698345173189268359115612698883860396660563679801383563588818099088505120717238037463747828729693649297904035253985982099474025883550074375828799938384533606092448272306356003096283602697757642323962299153853559914553690456801745940925602411053578841756504799815771173679267389055390097241148454899265156705442028845650177138185876173539754631720573266723359186
e = 0x10001

先去找各个量之间的关系
p = p p + p b p = p_p + p_b p=pp+pb

q = p + p p + r p p p = p / / 2 500 p b = p m o d    2 500 n = p × ( p p × 2 500 + p b + p p + r p ) = ( p p × 2 500 + p b ) × ( p p × 2 500 + p p + p b + r p ) q = p + p_p + r_p \newline p_p = p // 2^{500}\newline p_b = p \mod 2^{500} \newline n = p \times ( p_p \times 2^{500} + p_b+p_p + r_p) \newline =(p_p \times 2^{500} + p_b) \times ( p_p \times 2^{500} +p_p + p_b + r_p) \newline q=p+pp+rppp=p//2500pb=pmod2500n=p×(pp×2500+pb+pp+rp)=(pp×2500+pb)×(pp×2500+pp+pb+rp)

主要是本人完全不想暴力破解

那就只能提出攻击思路

依旧假定 p = p p + p b p = p_p + p_b p=pp+pb

p p p_p pp限定为p的二进制高位, p b p_b pb限定为p的二进制低位

所以各个变量之间的关系为:

p p = p / / 2 500 p b = p m o d    2 500 q = p p ∗ 2 500 p b + r p p_p = p // 2^{500} \newline p_b = p \mod 2^{500} \newline q = p_p * 2^{500} p_b + r_p pp=p//2500pb=pmod2500q=pp2500pb+rp

由上述思路中的推导可得出
n = ( p p × 2 500 + p b ) × ( p p × 2 500 + p p + p b + r p ) (1) n = (p_p \times 2^{500} + p_b) \times ( p_p \times 2^{500} +p_p + p_b + r_p) \tag{1} n=(pp×2500+pb)×(pp×2500+pp+pb+rp)(1)

n = p p 2 × ( 2 500 + p b p p ) × ( 2 500 + 1 + p b p p + r p p p ) = p b 2 ( p p p b × 2 500 + 1 ) × ( p p p b × ( 2 500 + 1 ) + 1 + r p p b ) n = p_p^2 \times (2^{500} + \dfrac{p_b}{p_p})\times (2^{500} + 1 + \dfrac{p_b}{p_p} +\dfrac{r_p}{p_p}) \newline = p_b^2 (\dfrac{p_p}{p_b} \times 2^{500} + 1) \times (\dfrac{p_p}{p_b} \times (2^{500}+ 1) + 1 + \dfrac{r_p}{p_b}) n=pp2×(2500+pppb)×(2500+1+pppb+pprp)=pb2(pbpp×2500+1)×(pbpp×(2500+1)+1+pbrp)

进而
∵ p p × 2 500 ≫ p b 且 p p × 2 500 ≫ r p ∴ n ≈ p p × 2 500 × ( p p × 2 500 + p p ) (2) \because p_p \times 2^{500} \gg p_b 且 p_p \times 2^{500} \gg r_p \newline \therefore n \approx p_p \times 2^{500} \times (p_p \times 2^{500} + p_p) \tag{2} pp×2500pbpp×2500rpnpp×2500×(pp×2500+pp)(2)

# 获取n的估计值和实际值之间的差值
p_p,p_b,r_p,x = symbols("p_p p_b r_p 2^{500}")
f1 = (p_p * x + p_b) * (p_p * x + p_b + p_p + r_p) # 公式1
f2 = (p_p *x + p_p) * p_p *x # 公式2
expand(f1-f2)

结果:
2 ∗ 2 500 ∗ p b ∗ p p + 2 500 ∗ p p ∗ r p + p b ∗ ∗ 2 + p b ∗ p p + p b ∗ r p 2*2^{500}*p_b*p_p + 2^{500}*p_p*r_p + p_b**2 + p_b*p_p + p_b*r_p 22500pbpp+2500pprp+pb2+pbpp+pbrp

可以得出约数和实际值之间的差值为
( 2 501 + 1 ) p p p b + 2 500 p b ∗ r p + p b 2 + p b r p (2^{501} + 1)p_p p_b + 2^{500}p_b*r_p + p_b^2 +p_b r_p (2501+1)pppb+2500pbrp+pb2+pbrp

可以获得 p p p_p pp的约数值:

p p = n ( 2 500 + p b p p ) × ( 2 500 + 1 + p b p p + r p p p ) < n 2 500 × ( 2 500 + 1 ) p_p = \sqrt{\dfrac{n}{(2^{500} + \dfrac{p_b}{p_p})\times (2^{500} + 1 + \dfrac{p_b}{p_p} +\dfrac{r_p}{p_p})}}\newline < \sqrt{\dfrac{n} {2^{500} \times (2^{500} + 1)}} pp=(2500+pppb)×(2500+1+pppb+pprp)n <2500×(2500+1)n
又:
p b p p < 1   且   2 500 ≫ p b p p \dfrac{p_b}{p_p} < 1 ~~且~~ 2^{500} \gg \dfrac{p_b}{p_p} pppb<1    2500pppb

x = 2**500
p_p = iroot(n//(x*(x+1)),2)
print(p_p[1])
p_p = p_p[0]
len_in_bits(int(p_p))

结果:
False
524

又因为

r p < < 2 500 r p < < p p r p < < p b r_p << 2^{500} \newline r_p << p_p \newline r_p << p_b rp<<2500rp<<pprp<<pb

尝试一下直接通过sympy去解 p b p_b pb

f3 = expand((p_p * x + p_b) * (p_p * x + p_b + p_p)-n)
f3

p_b**2 + 234748203441784029605546264019191369100140950983625918815401006819928268816279580149554018134364886555532239981448371569070598810627134525454891930342184712817335310569143171813222577456112704848761831308440868071153405524235368849056644946196368716289199694239365232060808865357432154718589228138165711690821*p_b - 703362945434949849890553721873017655818657316188302193305475760097394857649515948982232605142691305639015585953293320113584158480328765270581753362695266860592023045730966260181936220787089975556348484899405793581206871595977356194998849224322946624047337775358138025400819109814625333580530664301081326982901355820298472610756669157271295556944965475554867324277625148935098188608104161784470884588938365078701842810573312723187385605384484689392631922855859

solve(f3,p_b)

[-234748203441784029605546264019191369100140950983625918815401006819928268816279580149554018134364886555532239981448371569070598810627134525454891930342184712817335310569143171813222577456112704848761831308440868071153405524235368849056644946196368716289199694239365232060808865357432154718589228138165711690821/2 - sqrt(55106719019145223323174697438251640714014101174007501038793191167948784993344250027804605380931267971618539070084029774536070534751449159714863480817553917034718309263660246960113976314689972905316460991916432142679482606392447051627836230162034631295794403298195278667942794005933046018564264120754413416584932981935034803889524298584609782951501301375500494534517892077086243009131852203311560855435185734790926535854535437991207016883575070706249502276952233613010767060018264164343500357847655143410044889669028131029568083796768574220069089891051160210348299889117287472843780613781878334575978164641282387077477)/2,
-234748203441784029605546264019191369100140950983625918815401006819928268816279580149554018134364886555532239981448371569070598810627134525454891930342184712817335310569143171813222577456112704848761831308440868071153405524235368849056644946196368716289199694239365232060808865357432154718589228138165711690821/2 + sqrt(55106719019145223323174697438251640714014101174007501038793191167948784993344250027804605380931267971618539070084029774536070534751449159714863480817553917034718309263660246960113976314689972905316460991916432142679482606392447051627836230162034631295794403298195278667942794005933046018564264120754413416584932981935034803889524298584609782951501301375500494534517892077086243009131852203311560855435185734790926535854535437991207016883575070706249502276952233613010767060018264164343500357847655143410044889669028131029568083796768574220069089891051160210348299889117287472843780613781878334575978164641282387077477)/2]

可以获得一个关于 p b p_b pb的二元一次方程组

# 直接解方程获得他的正根
a = -234748203441784029605546264019191369100140950983625918815401006819928268816279580149554018134364886555532239981448371569070598810627134525454891930342184712817335310569143171813222577456112704848761831308440868071153405524235368849056644946196368716289199694239365232060808865357432154718589228138165711690821
b =55106719019145223323174697438251640714014101174007501038793191167948784993344250027804605380931267971618539070084029774536070534751449159714863480817553917034718309263660246960113976314689972905316460991916432142679482606392447051627836230162034631295794403298195278667942794005933046018564264120754413416584932981935034803889524298584609782951501301375500494534517892077086243009131852203311560855435185734790926535854535437991207016883575070706249502276952233613010767060018264164343500357847655143410044889669028131029568083796768574220069089891051160210348299889117287472843780613781878334575978164641282387077477
p_b = (a + iroot(b,2)[0])//2
p = p_p * 2**500 + p_b
p = int(p)

解出的 p b p_b pb是个约数,需要判断和实际值之间的关系

p b p_b pb求解实际值时的一元二次方程应该为:

( p p × 2 500 + p b ) × ( p p × 2 500 + p p + p b + r p ) − n = 0 (3) (p_p \times 2^{500} + p_b) \times ( p_p \times 2^{500} +p_p + p_b + r_p) - n = 0 \tag{3} (pp×2500+pb)×(pp×2500+pp+pb+rp)n=0(3)

p b p_b pb求解约数值时的一元二次方程却为:

( p p × 2 500 + p b ) × ( p p × 2 500 + p p + p b ) − n = 0 (4) (p_p \times 2^{500} + p_b) \times ( p_p \times 2^{500} +p_p + p_b) - n = 0 \tag{4} (pp×2500+pb)×(pp×2500+pp+pb)n=0(4)

两个方程之间的差值为: 2 500 ∗ p p r p + p b r p 2^{500}*p_pr_p+p_br_p 2500pprp+pbrp

只能说可以确定地是,约数值和实际值之间十分接近

p = p_p * 2**500 + p_b
flag = False
pp = p
for _ in range(10):
    if n%pp==0:
        print(str(_)+"  prev")
        flag = True
        break
    pp = prevprime(pp)

if flag == False:
    pp = p
    for _ in range(10):
        if n%pp==0:
            print(str(_)+"  next")
            flag = True
            break
        pp = nextprime(pp)

2 prev

n已经成功分解了,那就愉快地开搞吧

p = pp
q = n//p
phi = (p-1) * (q-1)
d = invmod(e,phi)
m = pow(c,d,n)
flag = n2s(int(m))
print(flag)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值