window.onload=function(){ /*页面加载完成之后生成博客目录*/ BlogDirectory.createBlogDirectory("cnblogs_post_body","h2","h3",20); }

[湖湘杯 2021]signin

题目分数:321

题目评分:4.5

题目标签: CryptoRSA连分数

附件内容:

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

m1 = bytes_to_long(flag[:len(flag) // 2])
m2 = bytes_to_long(flag[len(flag) // 2:])

def gen(pbits, qbits):
    p1, q1 = getPrime(pbits), getPrime(qbits)
    n1 = p1**4*q1
    q2 = getPrime(qbits)
    bound = p1 // (8*q1*q2) + 1
    p2 = random.randrange(p1, p1 + bound)
    while not isPrime(p2):
        p2 = random.randrange(p1, p1 + bound)
    n2 = p2**4*q2
    return (n1, n2), (p1, q1), (p2, q2)

e = 0x10001
pbits = int(360)
qbits = int(128)
pk, sk1, sk2 = gen(pbits, qbits)
c1 = pow(m1, e, pk[0])
c2 = pow(m2, e, pk[1])
print(f'pk = {pk}')
print(f'c1, c2 = {c1, c2}')

"""
pk = (1150398070565459492080597718626032792435556703413923483458704675295997646493249759818468321328556510074044954676615760446708253531839417036997811506222349194302791943489195718713797322878586379546657275419261647635859989280700191441312691274285176619391539387875252135478424580680264554294179123254566796890998243909286508189826458854346825493157697201495100628216832191035903848391447704849808577310612723700318670466035077202673373956324725108350230357879374234418393233, 1242678737076048096780023147702514112272319497423818488193557934695583793070332178723043194823444815153743889740338870676093799728875725651036060313223096288606947708155579060628807516053981975820338028456770109640111153719903207363617099371353910243497871090334898522942934052035102902892149792570965804205461900841595290667647854346905445201396273291648968142608158533514391348407631818144116768794595226974831093526512117505486679153727123796834305088741279455621586989)
c1, c2 = (361624030197288323178211941746074961985876772079713896964822566468795093475887773853629454653096485450671233584616088768705417987527877166166213574572987732852155320225332020636386698169212072312758052524652761304795529199864805108000796457423822443871436659548626629448170698048984709740274043050729249408577243328282313593461300703078854044587993248807613713896590402657788194264718603549894361488507629356532718775278399264279359256975688280723740017979438505001819438, 33322989148902718763644384246610630825314206644879155585369541624158380990667828419255828083639294898100922608833810585530801931417726134558845725168047585271855248605561256531342703212030641555260907310067120102069499927711242804407691706542428236208695153618955781372741765233319988193384708525251620506966304554054884590718068210659709406626033891748214407992041364462525367373648910810036622684929049996166651416565651803952838857960054689875755131784246099270581394)
"""

解题:

参考勒让德定理

关于连分数逼近问题离不开的就是勒让德定理:

假设x∈R+,那么在x的连分数逼近展开中,如果有∣x−bc∣<12c2,其中gcd(b,c)==1,那么可以认为bc是x的连分数展开中其中一项的值。假设xR+,那么在x的连分数逼近展开中,如果有xcb<2c21,其中gcd(b,c)==1,那么可以认为cbx的连分数展开中其中一项的值。

经过推导可以得到

N1N2的连分数展开是对q1q2的一个逼近N2N1的连分数展开是对q2q1的一个逼近

解题脚本:

from Crypto.Util.number import *
import gmpy2
def continuedFra(x,y):
    cf = []
    while y != 0:
        cf.append(x // y)
        x,y = y,x % y
    return cf

def exp(x,y):
    cf = continuedFra(x,y)
    fz = [cf[0],cf[0] * cf[1] + 1]
    fm = [1,cf[1]]
    for i in range(2,len(cf)):
        z = fz[i - 1] * cf[i] + fz[i - 2]
        m = fm[i - 1] * cf[i] + fm[i - 2]
        fz.append(z)
        fm.append(m)
    return fz,fm

def get(x,y):
    tmp1,tmp2 = exp(x,y)
    for i in range(2,len(tmp1)):
        _x,_y = tmp1[i],tmp2[i]
        if x % _x == 0 and y % _y == 0 and x != _x and y != _y:
            return _x,_y
e = 0x10001
n1 = 1150398070565459492080597718626032792435556703413923483458704675295997646493249759818468321328556510074044954676615760446708253531839417036997811506222349194302791943489195718713797322878586379546657275419261647635859989280700191441312691274285176619391539387875252135478424580680264554294179123254566796890998243909286508189826458854346825493157697201495100628216832191035903848391447704849808577310612723700318670466035077202673373956324725108350230357879374234418393233
n2 = 1242678737076048096780023147702514112272319497423818488193557934695583793070332178723043194823444815153743889740338870676093799728875725651036060313223096288606947708155579060628807516053981975820338028456770109640111153719903207363617099371353910243497871090334898522942934052035102902892149792570965804205461900841595290667647854346905445201396273291648968142608158533514391348407631818144116768794595226974831093526512117505486679153727123796834305088741279455621586989
c1 = 361624030197288323178211941746074961985876772079713896964822566468795093475887773853629454653096485450671233584616088768705417987527877166166213574572987732852155320225332020636386698169212072312758052524652761304795529199864805108000796457423822443871436659548626629448170698048984709740274043050729249408577243328282313593461300703078854044587993248807613713896590402657788194264718603549894361488507629356532718775278399264279359256975688280723740017979438505001819438
c2 = 33322989148902718763644384246610630825314206644879155585369541624158380990667828419255828083639294898100922608833810585530801931417726134558845725168047585271855248605561256531342703212030641555260907310067120102069499927711242804407691706542428236208695153618955781372741765233319988193384708525251620506966304554054884590718068210659709406626033891748214407992041364462525367373648910810036622684929049996166651416565651803952838857960054689875755131784246099270581394
q1,q2 = get(n1,n2)
p1 = gmpy2.iroot(n1 //q1,4)[0]
p2 = gmpy2.iroot(n2 //q2,4)[0]
def atttack(p,q,c,e):
    n = p ** 4 * q
    phi = p ** 3 * (p - 1) * (q - 1)
    d = gmpy2.invert(e,phi)
    m = pow(c,d,n)
    flag = long_to_bytes(m)
    return flag
print(atttack(p1,q1,c1,e) + atttack(p2,q2,c2,e))
flag{8ef333ac-21a7-11ec-80f1-00155d83f114}

 

posted @ 2023-04-14 20:47  Kicky_Mu  阅读(45)  评论(0编辑  收藏  举报