BUUCTF 每日打卡 2021-8-9

引言

加入了Nep联合战队,又要忙起来了啊

[NCTF2019]easyRSA

加密代码如下:

from flag import flag

e = 0x1337
p = 199138677823743837339927520157607820029746574557746549094921488292877226509198315016018919385259781238148402833316033634968163276198999279327827901879426429664674358844084491830543271625147280950273934405879341438429171453002453838897458102128836690385604150324972907981960626767679153125735677417397078196059
q = 112213695905472142415221444515326532320352429478341683352811183503269676555434601229013679319423878238944956830244386653674413411658696751173844443394608246716053086226910581400528167848306119179879115809778793093611381764939789057524575349501163689452810148280625226541609383166347879832134495444706697124741
n = p * q

assert(flag.startswith('NCTF'))
m = int.from_bytes(flag.encode(), 'big')
assert(m.bit_length() > 1337)

c = pow(m, e, n)
print(c)
# 10562302690541901187975815594605242014385201583329309191736952454310803387032252007244962585846519762051885640856082157060593829013572592812958261432327975138581784360302599265408134332094134880789013207382277849503344042487389850373487656200657856862096900860792273206447552132458430989534820256156021128891296387414689693952047302604774923411425863612316726417214819110981605912408620996068520823370069362751149060142640529571400977787330956486849449005402750224992048562898004309319577192693315658275912449198365737965570035264841782399978307388920681068646219895287752359564029778568376881425070363592696751183359

p和q都给了,这不是白给题吗?
然后开开心心地去做了
结果发现解出来都是一堆乱码,我直接找wp(发现比赛的时候只有两个人解出来,看来不简单)
又是e和φ不互素的问题,但是之前[De1CTF2019]babyrsaEzRSA的解法都不适用
接着看wp,给了一种新的思路
将同余方程
m e ≡ c ( m o d   n ) m^e \equiv c \quad (mod\ n) mec(mod n)
化成
{ m e ≡ c ( m o d   p ) m e ≡ c ( m o d   q ) \begin{cases} m^e &\equiv c \quad (mod\ p)\\ m^e &\equiv c \quad (mod\ q) \end{cases} {memec(mod p)c(mod q)
然后在有限域 G F ( p ) GF(p) GF(p) G F ( q ) GF(q) GF(q)对两个方程分别开 e e e次方根,再作 C R T CRT CRT即可得到 m m m(妙啊)
关键是怎么再有限域中开任意次方根
出题人给了一个AMM算法:
在这里插入图片描述
这里对wp的代码进行了一些修改:

import random
import time

def cal_k(s, r):
    R.<x> = PolynomialRing(GF(r))
    f = x * s + 1
    k = int(f.roots()[0][0])
    print(k)
    return k

# About 3 seconds to run
def AMM(o, r, q):
    start = time.time()
    print('\n----------------------------------------------------------------------------------')
    print('Start to run Adleman-Manders-Miller Root Extraction Method')
    print('Try to find one {:#x}th root of {} modulo {}'.format(r, o, q))
    g = GF(q)
    o = g(o)
    p = g(random.randint(1, q))
    while p ^ ((q-1) // r) == 1:
        p = g(random.randint(1, q))
    print('[+] Find p:{}'.format(p))
    t = 0
    s = q - 1
    while s % r == 0:
        t += 1
        s = s // r
    print('[+] Find s:{}, t:{}'.format(s, t))
    k = cal_k(s, r)
    alp = (k * s + 1) // r
    print('[+] Find alp:{}'.format(alp))
    a = p ^ (r**(t-1) * s)
    b = o ^ (r*alp - 1)
    c = p ^ s
    h = 1
    for i in range(1, t):
        d = b ^ (r^(t-1-i))
        if d == 1:
            j = 0
        else:
            print('[+] Calculating DLP...')
            j = - dicreat_log(a, d)
            print('[+] Finish DLP...')
        b = b * (c^r)^j
        h = h * c^j
        c = c ^ r
    result = o^alp * h
    end = time.time()
    print("Finished in {} seconds.".format(end - start))
    print('Find one solution: {}'.format(result))
    return result

def findAllPRoot(p, e):
    print("Start to find all the Primitive {:#x}th root of 1 modulo {}.".format(e, p))
    start = time.time()
    proot = set()
    while len(proot) < e:
        proot.add(pow(random.randint(2, p-1), (p-1)//e, p))
    end = time.time()
    print("Finished in {} seconds.".format(end - start))
    return proot

def findAllSolutions(mp, proot, cp, p):
    print("Start to find all the {:#x}th root of {} modulo {}.".format(e, cp, p))
    start = time.time()
    all_mp = set()
    for root in proot:
        mp2 = mp * root % p
        assert(pow(mp2, e, p) == cp)
        all_mp.add(mp2)
    end = time.time()
    print("Finished in {} seconds.".format(end - start))
    return all_mp


c = 10562302690541901187975815594605242014385201583329309191736952454310803387032252007244962585846519762051885640856082157060593829013572592812958261432327975138581784360302599265408134332094134880789013207382277849503344042487389850373487656200657856862096900860792273206447552132458430989534820256156021128891296387414689693952047302604774923411425863612316726417214819110981605912408620996068520823370069362751149060142640529571400977787330956486849449005402750224992048562898004309319577192693315658275912449198365737965570035264841782399978307388920681068646219895287752359564029778568376881425070363592696751183359
p = 199138677823743837339927520157607820029746574557746549094921488292877226509198315016018919385259781238148402833316033634968163276198999279327827901879426429664674358844084491830543271625147280950273934405879341438429171453002453838897458102128836690385604150324972907981960626767679153125735677417397078196059
q = 112213695905472142415221444515326532320352429478341683352811183503269676555434601229013679319423878238944956830244386653674413411658696751173844443394608246716053086226910581400528167848306119179879115809778793093611381764939789057524575349501163689452810148280625226541609383166347879832134495444706697124741
e = 0x1337
cp = c % p
cq = c % q
mp = AMM(cp, e, p)
mq = AMM(cq, e, q)
p_proot = findAllPRoot(p, e)
q_proot = findAllPRoot(q, e)
mps = findAllSolutions(mp, p_proot, cp, p)
mqs = findAllSolutions(mq, q_proot, cq, q)
print(mps, mqs)

def check(m):
    h = m.hex()
    if len(h) & 1:
        return False
    if bytes.fromhex(h).startswith(b'NCTF'):
        print(bytes.fromhex(h))
        return True
    else:
        return False


# About 16 mins to run 0x1337^2 == 24196561 times CRT
start = time.time()
result = []
print('Start CRT...')
for mpp in mps:
    for mqq in mqs:
        solution = CRT_list([int(mpp), int(mqq)], [p, q])
        if check(solution):
            print(solution)
            result.append(bytes.fromhex(solution.hex()))
    print(time.time() - start)

end = time.time()
print("Finished in {} seconds.".format(end - start))
print("result:", result)

得到的结果如下:
在这里插入图片描述
抛开算法和代码本身的推导不谈(因为我完全是不懂哦),这种做法是否对其他e和φ不互素的情况适用呢?
经过试验后发现,如果要应用AMM算法,需要满足两个条件:
一、 r ∣ q − 1 r|q-1 rq1,二、 ∃ k ∈ Z , s . t .   r ∣ k s + 1 \exist k\in \mathbb{Z},s.t.\space r|ks+1 kZs.t. rks+1
需要满足条件一是因为必须使t>0,否则a = p ^ (r**(t-1) * s)会出错
而如果不满足条件二,那么最后会无解,或者如原代码写的:

k = 1
while (k * s + 1) % r != 0:
	k += 1

会一直循环直到内存溢出

出题人说灵感来自hackergame 2019的一道十次方根题,于是就去找了这道题
在本题中的y可以应用AMM算法,e=10
结果如下:
在这里插入图片描述
其实也可以直接开方计算,时间也差不多,结果相同:

y_roots = []
y = 116513882455567447431772208851676203256471727099349255694179213039239989833646726805040167642952589899809273716764673737423792812107737304956679717082391151505476360762847773608327055926832394948293052633869637754201186227370594688119795413400655007893009882742908697688490841023621108562593724732469462968731
z = 88688615046438957657148589794574470139777919686383514327296565433247300792803913489977671293854830459385807133302995575774658605472491904258624914486448276269854207404533062581134557448023142028865220726281791025833570337140263511960407206818858439353134327592503945131371190285416230131136007578355799517986306208039490339159501009668785839201465041101739825050371023956782364610889969860432267781626941824596468923354157981771773589236462813563647577651117020694251283103175874783965004467136515096081442018965974870665038880840823708377340101510978112755669470752689525778937276250835072011344062132449232775717960070624563850487919381138228636278647776184490240264110748648486121139328569423969642059474027527737521891542567351630545570488901368570734520954996585774666946913854038917494322793749823245652065062604226133920469926888309742466030087045251385865707151307850662127591419171619721200858496299127088429333831383287417361021420824398501423875648199373623572614151830871182111045650469239575676312393555191890749537174702485617397506191658938798937462708198240714491454507874141432982611857838173469612147092460359775924447976521509874765598726655964369735759375793871985156532139719500175158914354647101621378769238233
e = 10
R.<b> = PolynomialRing(GF(y^3))
g = b^e - z
for yr in g.roots():
    y_roots.append(yr[0])
print(y_roots)

(但是这道题在模y的情况下对z开10次方根没有用,需要模y^3开根,虽然理论上可行,但是很花时间)
在这里插入图片描述
这题的出题人也遇到了相同的问题
后来我找到了一篇题为浅谈高次剩余的求解的博客,其中有这样一段话:
在这里插入图片描述
给了对于e和φ不互素问题的一种可能的解法

结语

e和φ不互素问题还是一个有待研究的问题,如果以后碰到再做研究
希望继续坚持

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值