2023羊城杯 Crypto

Danger RSA

from Crypto.Util.number import *

m = bytes_to_long(flag)


def get_key(a, nbit):
    assert a >= 2
    while True:
        X = getRandomInteger(nbit // a)
        s = getRandomRange(pow(2, a ** 2 - a + 4), pow(2, a ** 2 - a + 5))
        p = X ** a + s
        if isPrime(p):
            return (p, s)


p, s = get_key(a, 1024)
q, t = get_key(a, 1024)

N = p * q
e = s * t
c = pow(m, e, N)
print("N =", N)
print("e =", e)
print("c =", c)
# N = 20289788565671012003324307131062103060859990244423187333725116068731043744218295859587498278382150779775620675092152011336913225797849717782573829179765649320271927359983554162082141908877255319715400550981462988869084618816967398571437725114356308935833701495015311197958172878812521403732038749414005661189594761246154666465178024563227666440066723650451362032162000998737626370987794816660694178305939474922064726534186386488052827919792122844587807300048430756990391177266977583227470089929347969731703368720788359127837289988944365786283419724178187242169399457608505627145016468888402441344333481249304670223
# e = 11079917583
# c = 13354219204055754230025847310134936965811370208880054443449019813095522768684299807719787421318648141224402269593016895821181312342830493800652737679627324687428327297369122017160142465940412477792023917546122283870042482432790385644640286392037986185997262289003477817675380787176650410819568815448960281666117602590863047680652856789877783422272330706693947399620261349458556870056095723068536573904350085124198592111773470010262148170379730937529246069218004969402885134027857991552224816835834207152308645148250837667184968030600819179396545349582556181916861808402629154688779221034610013350165801919342549766

自己不会做 看了看WP 学习了一些思路
先是利用e.bit_length()==34判断s,t的bit为17位 得到a的值为4
然后利用 (XY) ^ 4 ~ n 可以解出 XY的值
然后联立 n=... XY=... 用sage解个四次方程 得到X,Y的值 就能得到p,q
发现(e,phi)=21 有限域开根最终得到flag
这里还要学习一下利用itertools简化编程
写代码时出了点bug 以后再来补...


Easy_3L

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

m = bytes_to_long(flag)


def get_key():
    p = getPrime(1400)
    f = getRandomNBitInteger(1024)
    while True:
        q = getPrime(512)
        if gcd(f, q) != 1:
            continue
        else:
            break
    h = (invert(f, p) * q) % p
    return p, h


def encrypt1(m):
    a = getPrime(250)
    b = getRandomNBitInteger(240)
    n = getPrime(512)
    seed = m
    s = [0] * 6
    s[0] = seed
    for i in range(1, 6):
        s[i] = (s[i - 1] * a + b) % n
    return s


def encrypt2(msg, p, h):
    s = getRandomNBitInteger(512)
    c = (s * h + msg) % p
    return c


s = encrypt1(m)
print("S1 =", s[1])
print("S2 =", s[2])
print("S4 =", s[4])
print("S5 =", s[5])

p, h = get_key()
c = encrypt2(s[3], p, h)
print("p =", p)
print("h =", h)
print("c =", c)

p = 25886434964719448194352673440525701654705794467884891063997131230558866479588298264578120588832128279435501897537203249743883076992668855905005985050222145380285378634993563571078034923112985724204131887907198503097115380966366598622251191576354831935118147880783949022370177789175320661630501595157946150891275992785113199863734714343650596491139321990230671901990010723398037081693145723605154355325074739107535905777351
h = 2332673914418001018316159191702497430320194762477685969994411366563846498561222483921873160125818295447435796015251682805613716554577537183122368080760105458908517619529332931042168173262127728892648742025494771751133664547888267249802368767396121189473647263861691578834674578112521646941677994097088669110583465311980605508259404858000937372665500663077299603396786862387710064061811000146453852819607311367850587534711
c = 20329058681057003355767546524327270876901063126285410163862577312957425318547938475645814390088863577141554443432653658287774537679738768993301095388221262144278253212238975358868925761055407920504398004143126310247822585095611305912801250788531962681592054588938446210412897150782558115114462054815460318533279921722893020563472010279486838372516063331845966834180751724227249589463408168677246991839581459878242111459287
S1 = 28572152986082018877402362001567466234043851789360735202177142484311397443337910028526704343260845684960897697228636991096551426116049875141
S2 = 1267231041216362976881495706209012999926322160351147349200659893781191687605978675590209327810284956626443266982499935032073788984220619657447889609681888
S4 = 9739918644806242673966205531575183334306589742344399829232076845951304871478438938119813187502023845332528267974698273405630514228632721928260463654612997
S5 = 9755668823764800147393276745829186812540710004256163127825800861195296361046987938775181398489372822667854079119037446327498475937494635853074634666112736


首先通过格恢复S3
这是一个很经典的NTRU问题
只是有个点有疑问?这里造出来的格[[p,0],[h,1]]和后面规约出来的[q,f]其实大小差的并不大 而且接出来发现bit位数也对不上?
当然 解出来试一下发现能得flag
NTRU:


M = [[p,0],[h,1]]
M = matrix(M)
for i in M.LLL():
    q = abs(i[0])
    f = abs(i[1])
    if(int(f).bit_length()==1024):
        print(f'q= {q}\nf= {f}')
q= 143265706312185518707360965653484385997990911723976280223660311623608293086933108010191106789268178340653420902857329654860207182679342550588469606976658133500469022125616655674540322895098388733565812347250745
f= 2958625475884682403405014470761000210086580211925778089178918430815532447031463283614057163768060620823591903413541344968843101811848989638106999025589699093227724370590844533541264661014288260713331275996479822
# q= 8679032255315414870468109941104050878068604455215530087851124363550974247657821506664757785443771830171620813109655257936200563905213273573251632347739177090668314850815348942671723865738347884139081915448901123
# f= 1454842428684152404857969746042430553612790806980714985914044260129099237334833974185382919002392303110658316599832651986287543945336014319232039352131088276665839782293749006470734400265676548019701080303477701
S3 = (((c*f)%p)*modinv(f,q))%q

LCG:


# 先恢复n
t = []
for i in range(len(output)-1):
    t.append(output[i+1]-output[i])
T = []
for i in range(1,len(t)-1):
    T.append(t[i-1]*t[i+1]-t[i]*t[i])
kn = T[0]
for i in range(len(T)):
    kn = gcd(kn,T[i])
print(kn)
n = kn
# print(S3)
# 恢复a
a = (output[2]-output[1])*modinv(output[1]-output[0],n)%n

# 恢复b
b = (output[1]-a*output[0])%n
S0 = ((S1-b)*modinv(a,n))%n
print(n2s(int(S0)))
# DASCTF{NTRU_L0G_a6e_S1mpLe}

MCeorpkpleer

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


def pubkey(list, m, w):
    pubkey_list = []
    for i in range(len(e_bin)):
        pubkey_list.append(w * list[i] % m)
    return pubkey_list


def e_cry(e, pubkey):
    pubkey_list = pubkey
    encode = 0
    for i in range(len(e)):
        encode += pubkey_list[i] * int(e[i]) % m
    return encode


p = getPrime(1024)
q = getPrime(1024)
n = p * q
e = getPrime(64)
m = bytes_to_long(flag)
c = pow(m, e, n)

e_bin = (bin(e))[2:]
list = [pow(3, i) for i in range(len(e_bin))]
m = getPrime(len(bin(sum(list))) - 1)
w = getPrime(64)
pubkey = pubkey(list, m, w)
en_e = e_cry(e_bin, pubkey)

print('p = {}\n'
      'n = {}\n'
      'c = {}\n'
      'pubkey = {}\n'
      'en_e = {}'.format((p >> 435) << 435, n, c, pubkey, en_e))

'''
p = 139540788452365306201344680691061363403552933527922544113532931871057569249632300961012384092481349965600565669315386312075890938848151802133991344036696488204791984307057923179655351110456639347861739783538289295071556484465877192913103980697449775104351723521120185802327587352171892429135110880845830815744
n = 22687275367292715121023165106670108853938361902298846206862771935407158965874027802803638281495587478289987884478175402963651345721058971675312390474130344896656045501040131613951749912121302307319667377206302623735461295814304029815569792081676250351680394603150988291840152045153821466137945680377288968814340125983972875343193067740301088120701811835603840224481300390881804176310419837493233326574694092344562954466888826931087463507145512465506577802975542167456635224555763956520133324723112741833090389521889638959417580386320644108693480886579608925996338215190459826993010122431767343984393826487197759618771
c = 156879727064293983713540449709354153986555741467040286464656817265584766312996642691830194777204718013294370729900795379967954637233360644687807499775502507899321601376211142933572536311131955278039722631021587570212889988642265055045777870448827343999745781892044969377246509539272350727171791700388478710290244365826497917791913803035343900620641430005143841479362493138179077146820182826098057144121231954895739989984846588790277051812053349488382941698352320246217038444944941841831556417341663611407424355426767987304941762716818718024107781873815837487744195004393262412593608463400216124753724777502286239464
pubkey = [18143710780782459577, 54431132342347378731, 163293397027042136193, 489880191081126408579, 1469640573243379225737, 4408921719730137677211, 13226765159190413031633, 39680295477571239094899, 119040886432713717284697, 357122659298141151854091, 1071367977894423455562273, 3214103933683270366686819, 9642311801049811100060457, 28926935403149433300181371, 86780806209448299900544113, 260342418628344899701632339, 781027255885034699104897017, 2343081767655104097314691051, 7029245302965312291944073153, 21087735908895936875832219459, 63263207726687810627496658377, 189789623180063431882489975131, 569368869540190295647469925393, 1708106608620570886942409776179, 601827224419797931380408071500, 1805481673259393794141224214500, 893952418336266652976851386463, 2681857255008799958930554159389, 3523079163584485147344841221130, 1524252287869625983140881149316, 50264262166963219975822190911, 150792786500889659927466572733, 452378359502668979782399718199, 1357135078508006939347199154597, 4071405235524020818041597463791, 3169230503688232995231149877299, 462706308180869526799807117823, 1388118924542608580399421353469, 4164356773627825741198264060407, 3448085117999647764701149667147, 1299270151115113835209806487367, 3897810453345341505629419462101, 2648446157152195057994615872229, 3422845870014670444537026359650, 1223552407160181874717436564876, 3670657221480545624152309694628, 1966986461557807413563286569810, 1378466783231507511243038452393, 4135400349694522533729115357179, 3361215846199738142293703557463, 1038662335715384967987468158315, 3115987007146154903962404474945, 302975818554635252993570910761, 908927455663905758980712732283, 2726782366991717276942138196849, 3657854499533237101379593333510, 1928578295715881845245137486456, 1263242285705730806288591202331, 3789726857117192418865773606993, 2324195368467747797703678306905, 2450093503961328663664213663678, 2827787910442071261545819733997, 3960871129884299055190637944954, 2837628186769067706678271320788]
en_e = 31087054322877663244023458448558
'''

先copper恢复P 再解背包得到e RSA恢复明文

p0 = 139540788452365306201344680691061363403552933527922544113532931871057569249632300961012384092481349965600565669315386312075890938848151802133991344036696488204791984307057923179655351110456639347861739783538289295071556484465877192913103980697449775104351723521120185802327587352171892429135110880845830815744
n = 22687275367292715121023165106670108853938361902298846206862771935407158965874027802803638281495587478289987884478175402963651345721058971675312390474130344896656045501040131613951749912121302307319667377206302623735461295814304029815569792081676250351680394603150988291840152045153821466137945680377288968814340125983972875343193067740301088120701811835603840224481300390881804176310419837493233326574694092344562954466888826931087463507145512465506577802975542167456635224555763956520133324723112741833090389521889638959417580386320644108693480886579608925996338215190459826993010122431767343984393826487197759618771
c = 156879727064293983713540449709354153986555741467040286464656817265584766312996642691830194777204718013294370729900795379967954637233360644687807499775502507899321601376211142933572536311131955278039722631021587570212889988642265055045777870448827343999745781892044969377246509539272350727171791700388478710290244365826497917791913803035343900620641430005143841479362493138179077146820182826098057144121231954895739989984846588790277051812053349488382941698352320246217038444944941841831556417341663611407424355426767987304941762716818718024107781873815837487744195004393262412593608463400216124753724777502286239464
pubkey = [18143710780782459577, 54431132342347378731, 163293397027042136193, 489880191081126408579, 1469640573243379225737, 4408921719730137677211, 13226765159190413031633, 39680295477571239094899, 119040886432713717284697, 357122659298141151854091, 1071367977894423455562273, 3214103933683270366686819, 9642311801049811100060457, 28926935403149433300181371, 86780806209448299900544113, 260342418628344899701632339, 781027255885034699104897017, 2343081767655104097314691051, 7029245302965312291944073153, 21087735908895936875832219459, 63263207726687810627496658377, 189789623180063431882489975131, 569368869540190295647469925393, 1708106608620570886942409776179, 601827224419797931380408071500, 1805481673259393794141224214500, 893952418336266652976851386463, 2681857255008799958930554159389, 3523079163584485147344841221130, 1524252287869625983140881149316, 50264262166963219975822190911, 150792786500889659927466572733, 452378359502668979782399718199, 1357135078508006939347199154597, 4071405235524020818041597463791, 3169230503688232995231149877299, 462706308180869526799807117823, 1388118924542608580399421353469, 4164356773627825741198264060407, 3448085117999647764701149667147, 1299270151115113835209806487367, 3897810453345341505629419462101, 2648446157152195057994615872229, 3422845870014670444537026359650, 1223552407160181874717436564876, 3670657221480545624152309694628, 1966986461557807413563286569810, 1378466783231507511243038452393, 4135400349694522533729115357179, 3361215846199738142293703557463, 1038662335715384967987468158315, 3115987007146154903962404474945, 302975818554635252993570910761, 908927455663905758980712732283, 2726782366991717276942138196849, 3657854499533237101379593333510, 1928578295715881845245137486456, 1263242285705730806288591202331, 3789726857117192418865773606993, 2324195368467747797703678306905, 2450093503961328663664213663678, 2827787910442071261545819733997, 3960871129884299055190637944954, 2837628186769067706678271320788]
en_e = 31087054322877663244023458448558

# # Copper解p
# PR.<x> = PolynomialRing(Zmod(n))
# f = p0+x
# f = f.monic()
# roots = f.small_roots(X=2^450,beta=0.4)
# if roots:
#     print(f'p= {f(roots)}')

# # LLL解e
# p= 139540788452365306201344680691061363403552933527922544113532931871057569249632300961012384092481349965600565669315386312075890938848151802133991344036696488204791984307057923179677630589032444985150800881889090713797496239571291907818169058929859395965304623825442220206712660451198754072531986630133689525911
# q= 162585259972480477964240855936099163585362299488578311068842002571891718764319834825730036484383081273549236661473286892739224906812137330941622699836239606393084030874487072527724286268715004074797344316619876830720445250395986443767703356842297999006344406006724963545062388183647988548800359369190326996261
# l = len(pubkey)
# M = Matrix(ZZ,l+1,l+1)
# for i in range(l):
#     M[i,i] = 1
#     M[i,-1] = pubkey[i]
# M[-1,-1] = -en_e
# e = ''
# for i in M.LLL()[-21]:
#     e = e + str(i)
# print(e)
e = '1101110101111111101010101111101101001110100000010000100001010011'
e = int(e,2)
# e = 15960663600754919507
print(e)
p= 139540788452365306201344680691061363403552933527922544113532931871057569249632300961012384092481349965600565669315386312075890938848151802133991344036696488204791984307057923179677630589032444985150800881889090713797496239571291907818169058929859395965304623825442220206712660451198754072531986630133689525911
q= 162585259972480477964240855936099163585362299488578311068842002571891718764319834825730036484383081273549236661473286892739224906812137330941622699836239606393084030874487072527724286268715004074797344316619876830720445250395986443767703356842297999006344406006724963545062388183647988548800359369190326996261
from libnum import *
from primefac import *
from gmpy2 import gcd,iroot
print(gcd(e,(p-1)*(q-1))) # 1
d = modinv(e,(p-1)*(q-1))
m = pow(c,d,n)
print(n2s(int(m)))

esyRSA

from gmpy2 import invert
from md5 import md5
from secret import p, q

e = XXX
n = p*q
phi = (p-1)*(q-1)
d = invert(e, phi)
ans = gcd(e,phi)

print (n, e, d)
print ("Flag: DASCTF{%s}" %md5(str(p + q)).hexdigest())

"""
n = 8064259277274639864655809758868795854117113170423331934498023294296505063511386001711751916634810056911517464467899780578338013011453082479880809823762824723657495915284790349150975180933698827382368698861967973964030509129133021116919437755292590841218316278732797712538885232908975173746394816520256585937380642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373
d = 14218766449983537783699024084862960813708451888387858392014856544340557703876299258990323621963898510226357248200187173211121827541826897886277531706124228848229095880229718049075745233893843373402201077890407507625110061976931591596708901741146750809962128820611844426759462132623616118530705745098783140913
"""

factor分解n 发现很奇怪
image
说明n不对劲 这种一般是n重复 或者采用的其他进制
随便拖一截前缀发现后半部分有相同的 故应该是重复了两次
去掉后真实的n为80642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373

这时发现d和n的长度几乎相同 d~n 于是可以采用连分数展开获得k,e 进而获得phi 得到p+q

n = 80642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373
d = 14218766449983537783699024084862960813708451888387858392014856544340557703876299258990323621963898510226357248200187173211121827541826897886277531706124228848229095880229718049075745233893843373402201077890407507625110061976931591596708901741146750809962128820611844426759462132623616118530705745098783140913

# d/n ~ k/e

# num = d/n
# cf = continued_fraction(num)
# alist = cf.convergents()
# ans = []
# for i in alist:
#     a = str(i).split('/')
#     if(len(a)>1):
#         k, e = int(a[0]), int(a[1])
#         if((e*d-1)%k == 0):
#             phi = (e*d-1) // k
#             if(gcd(e,phi) == 1):
#                 ans.append(phi)
# print(f'phi= {ans}')
phis= [71093832249917688918495120424314804068542259441939291960074282721702788519381496294951618109819492551131786241000935866055609137709134489431387658530621144241145479401148590245378726169469216867011005389452037538125550309884657957983544508705733754049810644103059222133797310663118080592653528725493915704564, 85312598699901226702194144509177764882250711330327150352089139266043346223257795553941941731783391061358143489201123039266730965250961387317665190236745373089374575281378308294454471403363060240413206467342445045750660371861589549580253410446880504859772772923671066560556772795741696711184234470592698845477, 80573009883240047440961136480890111277681227367531197554750853751263160321965695800945167191128758224616024406467727314863023689403685754688906013001370630139964876654635068944762556325398445782612472774712309209875623684535945685714683776533164921256452063316800451751636952084867158005007332555559771131840, 80642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628229134608055954943799388235382259848429635810050660300419425586876320465642638414052458239112926888212224741397964972405489721142581182321171300117720993408, 80642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373]

from hashlib import md5
for phi in phis:
    p_q = n+1-phi
    print ("Flag: DASCTF{%s}" %md5(str(p_q).encode()).hexdigest())

得出5组答案后试一试就行了

signinCrypto

from random import *
from Crypto.Util.number import *
from Crypto.Cipher import DES3
from flag import flag
from key import key
from iv import iv
import os
import hashlib
import secrets

K1= key
hint1 = os.urandom(2) * 8 # b'\xfb\xc2'*8
xor =bytes_to_long(hint1)^bytes_to_long(K1)
print(xor) # 还原K1

def Rand():
    rseed = secrets.randbits(1024)
    List1 = []
    List2 = []
    seed(rseed)
    for i in range(624):
        rand16 = getrandbits(16)
        List1.append(rand16) 
    seed(rseed)
    for i in range(312):
        rand64 = getrandbits(64)
        List2.append(rand64)
    with open("task.txt", "w") as file:
        for rand16 in List1:
            file.write(hex(rand16)+ "\n")
        for rand64 in List2:
            file.write(hex((rand64 & 0xffff) | ((rand64 >> 32) & 0xffff) << 16) + "\n")
Rand()

K2 = long_to_bytes(getrandbits(64)) # K2可预测
K3 = flag[:8] # b'DASCTF{'+爆破一位(0~2**8)

KEY = K1 + K2 + K3

IV=iv

IV1=IV[:len(IV)//2]
IV2=IV[len(IV)//2:]

digest1 = hashlib.sha512(IV1).digest().hex()
digest2 = hashlib.sha512(IV2).digest().hex()

digest=digest1+digest2
hint2=(bytes_to_long(IV)<<32)^bytes_to_long(os.urandom(8))
print(hex(bytes_to_long((digest.encode()))))
print(hint2)


mode = DES3.MODE_CBC
des3 = DES3.new(KEY, mode, IV)

pad_len = 8 - len(flag) % 8
padding = bytes([pad_len]) * pad_len
flag += padding

cipher = des3.encrypt(flag)

ciphertext=cipher.hex()
print(ciphertext)

# 334648638865560142973669981316964458403
# 0x62343937373634656339396239663236643437363738396663393438316230353665353733303939613830616662663633326463626431643139323130616333363363326631363235313661656632636265396134336361623833636165373964343533666537663934646239396462323666316236396232303539336438336234393737363465633939623966323664343736373839666339343831623035366535373330393961383061666266363332646362643164313932313061633336336332663136323531366165663263626539613433636162383363616537396434353366653766393464623939646232366631623639623230353933643833
# 22078953819177294945130027344
# a6546bd93bced0a8533a5039545a54d1fee647007df106612ba643ffae850e201e711f6e193f15d2124ab23b250bd6e1

大概分析了下 由于没有数据 以后再来补
关键在于这个随机数的处理技巧
python每次生成的是32bit
16bit是从32bit的高16bit取出来的
64bit是生成两个32bit 从低位到高位拼接
题目给的(rand64 & 0xffff) | ((rand64 >> 32) & 0xffff) << 16)
相当于告诉64bit的高32bit的低16bit 低32bit的低16bit
这样与rand16的32bit的高16bit刚好互补 结合一下就能预测了

posted @ 2023-11-15 11:18  N0zoM1z0  阅读(93)  评论(0编辑  收藏  举报