DASCTF x CBCTF 2022_Crypto复现

DASCTF x CBCTF 2022_Crypto复现

  • easySignin
    • P r o b l e m Problem Problem
    • A n a l y s i s Analysis Analysis
    • S o l u t i o n Solution Solution
  • Little RSA
    • P r o b l e m Problem Problem
    • A n a l y s i s Analysis Analysis
    • S o l u t i o n Solution Solution
  • easyRSA
    • P r o b l e m Problem Problem
    • A n a l y s i s Analysis Analysis
    • S o l u t i o n Solution Solution
  • R e f e r e n c e Reference Reference

easySignin

keywords: 设置未知量并让未知量参与运算,构造同余式

P r o b l e m Problem Problem

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

p = getPrime(512)
d = getPrime(40)
m = libnum.s2n(flag)
a = randint(2,p)
b = randint(2,p)
c = randint(2,p)
g = d

for i in range(10):
    g = (c*d^2 + b*g + a) % p
    a = (a*b - c) % p
    b = (b*c - a) % p 
    c = (c*a - b) % p

t = (m+d)^2 %p

print('p=',p)
print('a=',a)
print('b=',b)
print('c=',c)
print('g=',g)
print('t=',t)

'''
p= 7591656713055743077369340861541583433090841738590989539280316533530045331013958613146671718809022799047779468311222607020894006899032327866283558110087799
a= 4392865163304254999527172406061971162689920565151840813033448791785156740502864894051809689255751412382468345217962713758808061870635744521996229554057672
b= 2119856022628544669301306700581535843188073099896481101405665476192582614655960576092254118367775147735092457551317887281026710342124525625026559538165667
c= 3370586754351688470908526079815435343732016329743637661764947106415792049906966624513736208696137655804912688128186282852926377345819134856707156640355705
g= 2221154642536617375933147254663757148609834736621720750750043572054496685087600339999953459509198087870095805651320901316659013390557077204194753685935362
t= 6426975621182152052236088849377616252912408340750729257254509090637526282051064469268808395760737262115678691330037039061905028548054911000486882481093832
'''

A n a l y s i s Analysis Analysis

flag通过t = (m+d)^2 %p加密,解出二次剩余并且减去d即可得到m

那么关于d的提示是

g = d
for i in range(10):
    g = (c*d^2 + b*g + a) % p
    a = (a*b - c) % p
    b = (b*c - a) % p 
    c = (c*a - b) % p

已知最后一轮循环的a, b, c, g,试求d

对于a,b,c来说,可以通过现有已知量推导出每个循环中a,b,c的值,我们会将其存储在a_ls, b_ls, c_ls列表中

而关于初始的g(即是d),我们可以通过将其设置为模p意义下的自变量x0,构造同余式来求解;设置未知量x0之后,我们可以再对其进行与题目一样的计算过程,``,x

x1 = x0
for i in range(10): 
	x1 = (c_ls[i] * x0^2 + b_ls[i] * x1 + a_ls[i]) % p

循环10轮后,构造式子f = x1 - known_g,相当于
x 1 − g k n o w n ≡ 0 ( m o d p ) x_1-g_{known} \equiv 0 \pmod p x1gknown0(modp)
求解该同余式即可得到x0

S o l u t i o n Solution Solution

# type:ignore
from Crypto.Util.number import *
import gmpy2

p= 7591656713055743077369340861541583433090841738590989539280316533530045331013958613146671718809022799047779468311222607020894006899032327866283558110087799
a= 4392865163304254999527172406061971162689920565151840813033448791785156740502864894051809689255751412382468345217962713758808061870635744521996229554057672
b= 2119856022628544669301306700581535843188073099896481101405665476192582614655960576092254118367775147735092457551317887281026710342124525625026559538165667
c= 3370586754351688470908526079815435343732016329743637661764947106415792049906966624513736208696137655804912688128186282852926377345819134856707156640355705
g= 2221154642536617375933147254663757148609834736621720750750043572054496685087600339999953459509198087870095805651320901316659013390557077204194753685935362
t= 6426975621182152052236088849377616252912408340750729257254509090637526282051064469268808395760737262115678691330037039061905028548054911000486882481093832

a_ls = []
b_ls = []
c_ls = []

for i in range(10):
    c = (c + b) * gmpy2.invert(a, p) % p
    b = (b + a) * gmpy2.invert(c, p) % p
    a = (a + c) * gmpy2.invert(b, p) % p
    c_ls.append(c)
    b_ls.append(b)
    a_ls.append(a)

c_ls = c_ls[::-1]
b_ls = b_ls[::-1]
a_ls = a_ls[::-1]

P.<x0> = PolynomialRing(Zmod(p))
x1 = x0
for i in range(10):
    x1 = c_ls[i] * x0^2 + b_ls[i] * x1 + a_ls[i]
f = x1 - g
res = f.roots()
for i in res:
    if int(i[0]).bit_length() == 40:
        # print(i[0])
        d = int(i[0])
        break

m = sqrt(GF(p)(t)) - d
flag = long_to_bytes(m).decode()
print(flag)

Little RSA

keywords: 构造格子应用LLL算法

P r o b l e m Problem Problem

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

m = bytes_to_long(flag)
p = getPrime(512)
q = getPrime(512)
phi = (p-1)*(q-1)
e = 65537
n = p * q
c = pow(m, e, n)

s = getPrime(300)
N = getPrime(2048)
g = p * inverse(s,N)**2 % (N**2)
print(N)
print(g)
print(n)
print(c)

'''
19351301035801508116955552063316327463227928638319284082504070745230119792307421099534903837766317639913937954784857576991401214861067471772614753337821871108189780331081099041824669243928056765115068764246765680962348646383991303828426125303844394268682191775232611288039200316595279055408827296256289143602827525373267536643865729646353071637054367702218515803980122435811129935450486950137279824491461041391572264371799797200331838690523349105589985032730668315787318829244743317257793753147209875458127340875400367081865762286565978620979196410411241442894450955280237513249393612603560410291825805553536595543937
101172011079013273946711882340439823149055809449035744718659818796135714101721641190114954130041477714466321498903210220694435354795744225843314447645623337668697058127975104586375292636080114347294697007231487782548846095107329445479367324424672776003899748234353857872627585595343736452088156885081907758727085723312506489549364721644636251780350312413098132506051531311685636921117457469745637347738336829350634994271419554741425590636953154753970902976959308323838617091060754826727417688836026597614894745348808019654100196615719730109909578899299246848916182034705259206906552769087038179288139086772719994577168184701096922291610523676039127012518100023765548552210944426749474888311751069936144583375194023227887848704267587915237057432609663328145608194550736074250822416779448467084842127165553649513397606464059847361880649213934069715996589751778384513724306521043255299443480482640183740131563318058454711913397533436985618182923646192481486120942073719321372236539019107909910597047133371708017755744495134116771999521953654596632221519266339372439452558083199640035069852530373510758859460350025736629801086757717838159774542506755335660607766677992105601518694405113552321342152041808586187181800679845672788746273313
90106928919727272173474070618911951313216606598108495724382284361415375454490594410306345748069424740100772955015304592942129026096113424198209327375124576666577469761124470792842854884924199449996929134613382626394351988541980388358156143332979538058465890179760337315789398915560641465656968797050755849799
51609249982849856103564442566936515708380814106997783395400669324617748952940831076546581735494963467680719842859574144530848473300102236821201997786375946601413660428461473204032985053128283751860315027843200214217715401391736262811016964783589439740884991543059175666298728428567481043422497862838127903980
'''

A n a l y s i s Analysis Analysis

已知g = p * inverse(s,N)**2 % (N**2)flag应用RSA加密,突破点就是g的表达式中的p,如何求解p

又已知N,所以我们可以

g % N = p * inverse(s,N)**2 % (N**2) % N

就相当于构造了
g ≡ p ⋅ s − 2 ( m o d N ) g \equiv p\cdot s^{-2} \pmod N gps2(modN)
这样做的主要原因在于inverse(s,N),我们需要将整个同余式的模数从 N 2 N^2 N2换做 N N N才能方便转换同余式,紧接着
g ⋅ s 2 ≡ p ( m o d N ) ⇒ g ⋅ s 2 = p + k ⋅ N ⇒ s 2 ⋅ g − k ⋅ N = p g \cdot s^2\equiv p \pmod N \\ \Rightarrow g \cdot s^2 = p + k\cdot N \\ \Rightarrow s^2\cdot g - k\cdot N = p gs2p(modN)gs2=p+kNs2gkN=p
构造矩阵乘法式子
( s 2 ,   − k ) ( 1 g 0 N ) = ( s 2 ,   p ) (s^2,\ -k) \begin{pmatrix} 1\qquad g \\ 0 \qquad N \end{pmatrix} = (s^2,\ p) (s2, k)(1g0N)=(s2, p)
应用LLL算法后得到p,代入求RSA即可

S o l u t i o n Solution Solution

# type:ignore

from Crypto.Util.number import *
import gmpy2


N = 19351301035801508116955552063316327463227928638319284082504070745230119792307421099534903837766317639913937954784857576991401214861067471772614753337821871108189780331081099041824669243928056765115068764246765680962348646383991303828426125303844394268682191775232611288039200316595279055408827296256289143602827525373267536643865729646353071637054367702218515803980122435811129935450486950137279824491461041391572264371799797200331838690523349105589985032730668315787318829244743317257793753147209875458127340875400367081865762286565978620979196410411241442894450955280237513249393612603560410291825805553536595543937
g = 101172011079013273946711882340439823149055809449035744718659818796135714101721641190114954130041477714466321498903210220694435354795744225843314447645623337668697058127975104586375292636080114347294697007231487782548846095107329445479367324424672776003899748234353857872627585595343736452088156885081907758727085723312506489549364721644636251780350312413098132506051531311685636921117457469745637347738336829350634994271419554741425590636953154753970902976959308323838617091060754826727417688836026597614894745348808019654100196615719730109909578899299246848916182034705259206906552769087038179288139086772719994577168184701096922291610523676039127012518100023765548552210944426749474888311751069936144583375194023227887848704267587915237057432609663328145608194550736074250822416779448467084842127165553649513397606464059847361880649213934069715996589751778384513724306521043255299443480482640183740131563318058454711913397533436985618182923646192481486120942073719321372236539019107909910597047133371708017755744495134116771999521953654596632221519266339372439452558083199640035069852530373510758859460350025736629801086757717838159774542506755335660607766677992105601518694405113552321342152041808586187181800679845672788746273313
n = 90106928919727272173474070618911951313216606598108495724382284361415375454490594410306345748069424740100772955015304592942129026096113424198209327375124576666577469761124470792842854884924199449996929134613382626394351988541980388358156143332979538058465890179760337315789398915560641465656968797050755849799
c = 51609249982849856103564442566936515708380814106997783395400669324617748952940831076546581735494963467680719842859574144530848473300102236821201997786375946601413660428461473204032985053128283751860315027843200214217715401391736262811016964783589439740884991543059175666298728428567481043422497862838127903980
e = 0x10001

g = g % N
M = Matrix(2, 2, [1, g, 0, N])
res = M.LLL()[0]
p = abs(res[1]) # 对结果取绝对值一劳永逸
assert n % p == 0
q = n // p
phi = (p - 1) * (q - 1)
d = gmpy2.invert(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))

easyRSA

keywords: 应用连分数误差估计的维纳攻击

P r o b l e m Problem Problem

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

bitlen = 512
p = getPrime(bitlen)
q = getPrime(bitlen)
r = getPrime(bitlen)

assert p != q and q != r and p != r

n = p*q*r
phi = (p-1)*(q-1)*(r-1)

while 1:
    d = getPrime(256)
    try:
        e = int(gmpy2.invert(d,phi))
    except:
        continue
    if gmpy2.gcd(e,phi) == 1 :
        break

assert flag.startswith(b'CBCTF{')
m = bytes_to_long(flag)
c = pow(m,e,n)
print('c =',c)
print('e =',e)
print('n =',n)

'''
c = 262857004135341325365954795119195630698138090729973647118817900621693212191529885499646534515610526918027363734446577563494752228693708806585707918542489830672358210151020370518277425565514835701391091303404848540885538503732425887366285924392127448359616405690101810030200914619945580943356783421516140571033192987307744023953015589089516394737132984255621681367783910322351237287242642322145388520883300325056201966188529192590458358240120864932085960411656176
e = 543692319895782434793586873362429927694979810701836714789970907812484502410531778466160541800747280593649956771388714635910591027174563094783670038038010184716677689452322851994224499684261265932205144517234930255520680863639225944193081925826378155392210125821339725503707170148367775432197885080200905199759978521133059068268880934032358791127722994561887633750878103807550657534488433148655178897962564751738161286704558463757099712005140968975623690058829135
n = 836627566032090527121140632018409744681773229395209292887236112065366141357802504651617810307617423900626216577416313395633967979093729729146808472187283672097414226162248255028374822667730942095319401316780150886857701380015637144123656111055773881542557503200322153966380830297951374202391216434278247679934469711771381749572937777892991364186158273504206025260342916835148914378411684678800808038832601224951586507845486535271925600310647409016210737881912119
'''

A n a l y s i s Analysis Analysis

RSA加密的e很大,经典的维纳攻击应用场景

但是直接应用平常的维纳攻击跑不出来,转而挖连分数定理的细节

维纳攻击应用的连分数也并不是一定能找到与原始数据相同的收敛分数,这里的题目的 e , N , k , d e,N,k,d e,N,k,d可能在维纳攻击的应用条件上不完全满足
e N − k d = 1 d ⋅ φ ( N ) < 1 2 ⋅ d 2 \frac{e}{N} - \frac{k}{d} = \frac{1}{d\cdot \varphi(N)} <\frac{1}{2\cdot d^2} Nedk=dφ(N)1<2d21
连分数中存在一个误差估计( 连分数 - OI Wiki (oi-wiki.org))

实数 x x x可以写作
x = [ a 0 , a 1 , ⋯   , a k , r k + 1 ] x=[a_0,a_1,\cdots,a_k,r_{k+1}] x=[a0,a1,,ak,rk+1]
最后一项渐进分数是 x x x本身,根据渐进分数的递推式,我们有
x = r k + 1 p k + p k − 1 r k + 1 q k + q k − 1 x = \frac{r_{k+1}p_k+p_{k-1}}{r_{k+1}q_k + q_{k-1}} x=rk+1qk+qk1rk+1pk+pk1
参照该等式,我们在应用维纳攻击的时候对每个连分数部分进行爆破 r r r,查看是否满足最后的判断条件(具体爆破范围不清楚

S o l u t i o n Solution Solution

from Crypto.Util.number import *
from multiprocessing import Pool
import os
import gmpy2

def get_d(i):
    global q_k_1
    global q_k
    k = i.numerator()
    q_k = i.denominator()
    # print("Now is: %d" % q_k)
    # print("%s is run" %os.getpid())
    for r in range(20):
        d = r * q_k + q_k_1
        if pow(pow(2, e, n), d, n) != 2:
            continue
        else:
            # print(r)
            # print(q1)
            # print(q0)
            return d
    q_k_1 = q_k

if __name__ == "__main__": 
    e = 543692319895782434793586873362429927694979810701836714789970907812484502410531778466160541800747280593649956771388714635910591027174563094783670038038010184716677689452322851994224499684261265932205144517234930255520680863639225944193081925826378155392210125821339725503707170148367775432197885080200905199759978521133059068268880934032358791127722994561887633750878103807550657534488433148655178897962564751738161286704558463757099712005140968975623690058829135
    n = 836627566032090527121140632018409744681773229395209292887236112065366141357802504651617810307617423900626216577416313395633967979093729729146808472187283672097414226162248255028374822667730942095319401316780150886857701380015637144123656111055773881542557503200322153966380830297951374202391216434278247679934469711771381749572937777892991364186158273504206025260342916835148914378411684678800808038832601224951586507845486535271925600310647409016210737881912119
    c = 262857004135341325365954795119195630698138090729973647118817900621693212191529885499646534515610526918027363734446577563494752228693708806585707918542489830672358210151020370518277425565514835701391091303404848540885538503732425887366285924392127448359616405690101810030200914619945580943356783421516140571033192987307744023953015589089516394737132984255621681367783910322351237287242642322145388520883300325056201966188529192590458358240120864932085960411656176
    q_k_1 = 1
    conv = continued_fraction(Integer(e)/Integer(n)).convergents()

    pool = Pool()  # 这里用的进程池缩短总的运算时间
    res = pool.map(get_d , conv)
    pool.close()
    pool.terminate()
    for i in res:
        if i != None:
            d = i
    m = pow(c, d, n)
    print(long_to_bytes(m).decode())

关于官方wp使用的d = r * q_k + s * q_k_1,确实这样爆破更保险一些;关于连分数误差估计能应用在维纳攻击中也只是猜测,没有进行验证

R e f e r e n c e Reference Reference

DASCTF X CBCTF 2022| 九月挑战赛官方Write Up | CTF导航 (ctfiot.com)

你可能感兴趣的:(CTF比赛复现,Crypto,python)