0xGame2023 Crypto

密码部分的题出的挺好的 很多题目都可以起到很好的锻炼学习作用
比赛时很多没做出来 赛后尽可能都复现一下

Week1

Take My Bag

chall.py

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

def encrypt(m):
	m = str(bin(m))[2:][::-1]
	enc = 0
	for i in range(len(m)):
		enc += init[i] * int(m[i]) % n
	return enc

w = getPrime(64)
n = getPrime(512)
init = [w*pow(3, i) % n for i in range(512)]

c = encrypt(bytes_to_long(flag))

print(f'w={w}')
print(f'n={n}')
print(f'c={c}')

'''
w=16221818045491479713
n=9702074289348763131102174377899883904548584105641045150269763589431293826913348632496775173099776917930517270317586740686008539085898910110442820776001061
c=4795969289572314590787467990865205548430190921556722879891721107719262822789483863742356553249935437004378475661668768893462652103739250038700528111
'''

分析:
image

image
结合这两点(超递增 0/1)可以看出是一个背包密码
只用倒序判断即可还原flag的bit位
solution.py

from libnum import *
w=16221818045491479713
n=9702074289348763131102174377899883904548584105641045150269763589431293826913348632496775173099776917930517270317586740686008539085898910110442820776001061
c=4795969289572314590787467990865205548430190921556722879891721107719262822789483863742356553249935437004378475661668768893462652103739250038700528111
init = [w*pow(3, i) % n for i in range(512)]
flag = ''
for i in range(511,-1,-1):
    if(c>init[i]):
        c-=init[i]
        flag = '1'+flag
    else:
        flag = '0'+flag
print(flag[::-1])
print(n2s(int(flag[::-1],2)))

此外由于是背包密码 当然可以用格来做
要注意这里的求和是在modn的意义下的 所以格要加维
image

from libnum import *
w=16221818045491479713
n=9702074289348763131102174377899883904548584105641045150269763589431293826913348632496775173099776917930517270317586740686008539085898910110442820776001061
c=4795969289572314590787467990865205548430190921556722879891721107719262822789483863742356553249935437004378475661668768893462652103739250038700528111
init = [w*pow(3, i) % n for i in range(512)]

M = Matrix(ZZ,514,514)
for i in range(512):
    M[i,i] = 1
for i in range(512):
    M[i,512] = init[i]
M[-1,-1] = c
M[-2,-1] = -n
print(M.LLL())

只是我的电脑跑这个属实太慢。。。

密码,觅码,先有 * 再密

chall.py

from secret import flag #从中导入秘密的flag,这是我们要破解的信息
from Crypto.Util.number import bytes_to_long #从函数库导入一些编码函数
from base64 import b64encode

flag = flag.encode()
lent = len(flag)
flag = [flag[i*(lent//4):(i+1)*(lent//4)] for i in range(4)]

c1 = bytes_to_long(flag[0])
c2 = ''.join([str(bin(i))[2:] for i in flag[1]])
c3 = b64encode(flag[2])
c4 = flag[3].hex()

print(f'c1?= {pow(c1,5)}\nc2 = {c2}\nc3 = {c3}\nc4 = {c4}')

'''
c1?= 2607076237872456265701394408859286660368327415582106508683648834772020887801353062171214554351749058553609022833985773083200356284531601339221590756213276590896143894954053902973407638214851164171968630602313844022016135428560081844499356672695981757804756591891049233334352061975924028218309004551
c2 = 10010000100001101110100010100111101000111110010010111010100001101110010010111111101000011110011010000001101011111110011010011000101011111110010110100110100000101110010010111101100101011110011110111100
c3 = b'lueggeeahO+8jOmCo+S5iOW8gOWni+aIkQ=='
c4 = e4bbace79a8443727970746fe68c91e68898e590a72121217d
'''
#全是乱码,那咋办嘛?

主要是要注意flag不一定全是英文数字 还有可能会出现中文
所以这题得到b''后decode一下即可

0xGame{ \xe6\x81\xad\xe5\x96\x9c\xe4\xbd\xa0,\xe5\xb7\xb2\xe7\xbb\x8f\xe7\x90\x86\xe8\xa7\xa3\xe4\xba\x86\xe4\xbf\xa1\xe6\x81\xaf\xe6\x98\xaf\xe5\xa6\x82\xe4\xbd\x95\xe7\xbc\x96\xe7\xa0\x81\xe7\x9a\x84\xef\xbc\x8c\xe9\x82\xa3\xe4\xb9\x88\xe5\xbc\x80\xe5\xa7\x8b\xe6\x88\x91\xe4\xbb\xac\xe7\x9a\x84Crypto\xe6\x8c\x91\xe6\x88\x98\xe5\x90\xa7!!!}

0xGame{ 恭喜你,已经理解了信息是如何编码的,那么开始我们的Crypto挑战吧!!!}

What's CBC?

chall.py

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

def bytes_xor(a,b):
	a,b=bytes_to_long(a),bytes_to_long(b)
	return long_to_bytes(a^b)

def pad(text):
	if len(text)%8:
		return text
	else:
		pad = 8-(len(text)%8)
		text += pad.to_bytes(1,'big')*pad
		return text

def Encrypt_CBC(text,iv,key):
	result = b''
	text = pad(text)
	block=[text[_*8:(_+1)*8] for _ in range(len(text)//8)]
	for i in block:
		tmp = bytes_xor(iv,i)
		iv = encrypt(tmp,key)
		result += iv
	return result

def encrypt(text,key):
	result = b''
	for i in text:
		result += ((i^key)).to_bytes(1,'big')
	return result

iv = b'11111111'
enc = (Encrypt_CBC(flag,iv,key))
print(f'enc = {enc}')

#enc = b"\x8e\xc6\xf9\xdf\xd3\xdb\xc5\x8e8q\x10f>7.5\x81\xcc\xae\x8d\x82\x8f\x92\xd9o'D6h8.d\xd6\x9a\xfc\xdb\xd3\xd1\x97\x96Q\x1d{\\TV\x10\x11"

块密码
key的值可以通过枚举爆出来
然后逆着加密的思路回去就可以还原出明文
solution.py

from Crypto.Util.number import *
def bytes_xor(a,b):
	a,b=bytes_to_long(a),bytes_to_long(b)
	return long_to_bytes(a^b)

def encrypt(text,key):
	result = b''
	for i in text:
		result += ((i^key)).to_bytes(1,'big')
	return result

def decrypt(enc,iv,key):
    pt = b''
    block=[enc[_*8:(_+1)*8] for _ in range(len(enc)//8)]
    for i in block:
        # tmp = bytes_xor(iv,i)
        # iv = encrypt(tmp,key)
        # pt += iv
        tmp = encrypt(i,key)
        pt += bytes_xor(tmp,iv)
        iv = i
    return pt

iv = b'11111111'
enc = b"\x8e\xc6\xf9\xdf\xd3\xdb\xc5\x8e8q\x10f>7.5\x81\xcc\xae\x8d\x82\x8f\x92\xd9o'D6h8.d\xd6\x9a\xfc\xdb\xd3\xd1\x97\x96Q\x1d{\\TV\x10\x11"
for key in range(0xff):
    flag = decrypt(enc,iv,key)
    if b'0xGame' in flag:
        print(flag)

猜谜

chall.py

from secret import flag,key

def enc(text):
	code = 'AP3IXYxn4DmwqOlT0Q/JbKFecN8isvE6gWrto+yf7M5d2pjBuk1Hh9aCRZGUVzLS'
	text = ''.join([str(bin(i))[2:].zfill(8) for i in text])
	length = len(text)
	pad = b''
	if length%3 == 1:
		text += '00'
		pad = b'=='
	elif length%3 == 2:
		text += '0'
		pad = b'='
	result = [code[int(text[3*i:3*(i+1)],2)] for i in range(0,len(text)//3)]
	return ''.join(result).encode()+pad

def encrypt(flag):
	result = b''
	for i in range(len(flag)):
		result += (key[i%7]^(flag[i]+i)).to_bytes(1,'big') # 由开头为'0xGame{' 刚好7位可以确定key
	return result


c = enc(encrypt(flag))
print(f'c = {c}')

'''
c = b'IPxYIYPYXPAn3nXX3IXA3YIAPn3xAYnYnPIIPAYYIA3nxxInXAYnIPAIxnXYYYIXIIPAXn3XYXIYAA3AXnx='
'''

注意细节!
对密文进行code中的Index得到的是3bit的 而后面加密是8bit一组
所以要再转换一道
先逆外层enc:利用code中index找到对应项位置 再8bit一组取
再逆内层encrypt: 利用已知flag前7位'0xGame{'还原key
solution.py

enc = 'IPxYIYPYXPAn3nXX3IXA3YIAPn3xAYnYnPIIPAYYIA3nxxInXAYnIPAIxnXYYYIXIIPAXn3XYXIYAA3AXnx'
code = 'AP3IXYxn4DmwqOlT0Q/JbKFecN8isvE6gWrto+yf7M5d2pjBuk1Hh9aCRZGUVzLS'
flag = ''
for c in enc:
    print(code.index(c))
    flag += str(bin(code.index(c))[2:].zfill(3))
# print(flag)
block = [flag[8*i:8*(i+1)] for i in range(len(flag) // 8)]
print(block)
flag = [int(x,2) for x in block]
key = []
known = b'0xGame{'
for i in range(7):
    key.append((flag[i])^((known[i])+i))
print(key)
print(flag)
pt = ''
for i in range(len(flag)):
    pt += chr(((flag[i])^(key[i%7]))-i)
print(pt)

Week2

CRT

chall.py

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

m = bytes_to_long(flag)
e = 260792700
q,p,q_,p_ = [getPrime(512) for _ in range(4)]
gift = [q+p,q_+p_]
n,n_ = q*p,q_*p_
mq_ = pow(m,4,q_)
mp_ = pow(m,4,p_)
c = pow(m,e,n)

print(f'mygift={gift}\nmq_={mq_}\nmp_={mp_}\nn={n}\nn_={n_}\nc={c}')
'''
mygift=[15925416640901708561793293991573474917595642805739825596593339102414328214313430010166125066639132916608736569443045051644173933089503934675628814467277922, 18342424676996843423829480445042578097182127446865571536445030052846412665700132683433441858073625594933132038175200824257774638419166516796318527302903098]
mq_=6229615098788722664392369146712291169948485951371133086154028832805750551655072946170332335458186479565263371985534601035559229403357396564568667218817197
mp_=7514598449361191486799480225087938913945061715845128006069296876457814528347371315493644046029376830166983645570092100320566196227210502897068206073043718
n=63329068473206068067147844002844348796575899624395867391964805451897110448983910133293450006821779608031734813916287079551030950968978400757306879502402868643716591624454744334316879241573399993026873598478532467624301968439714860262264449471888606538913071413634346381428901358109273203087030763779091664797
n_=84078907800136966150486965612788894868587998005459927216462899940718213455112139441858657865215211843183780436155474431592540465189966648565764225210091190218976417210291521208716206733270743675534820816685370480170120230334766919110311980614082807421812749491464201740954627794429460268010183163151688591417
c=12623780002384219022772693100787925315981488689172490837413686188416255911213044332780064192900824150269364486747430892667624289724721692959334462348218416297309304391635919115701692314532111050955120844126517392040880404049818026059951326039894605004852370344012563287210613795011783419126458214779488303552
'''

韦达定理可以对应的解出p,q,p_,q_
注意p_,q_要枚举下对应关系
发现gcd(e,(p-1) * (q-1)) == 4
所以不能直接求d
于是构造4组关于m ^ 4的同余式 用中国剩余定理解出m_4 (mod n * n_) 的值 iroot开4次方即可
其实这里有个小问题 不确定是否需要nthrootmod 但这个跑有限域开方可能比较慢 这里n * n_达到了2048bit 应该直接开能开出m来 有空再跑跑sage看看模意义下要多久
solution.py

from Crypto.Util.number import *
from primefac import *
from sympy import *
from gmpy2 import *
from sympy.ntheory.modular import crt

mygift=[15925416640901708561793293991573474917595642805739825596593339102414328214313430010166125066639132916608736569443045051644173933089503934675628814467277922, 18342424676996843423829480445042578097182127446865571536445030052846412665700132683433441858073625594933132038175200824257774638419166516796318527302903098]
mq_=6229615098788722664392369146712291169948485951371133086154028832805750551655072946170332335458186479565263371985534601035559229403357396564568667218817197
mp_=7514598449361191486799480225087938913945061715845128006069296876457814528347371315493644046029376830166983645570092100320566196227210502897068206073043718
n=63329068473206068067147844002844348796575899624395867391964805451897110448983910133293450006821779608031734813916287079551030950968978400757306879502402868643716591624454744334316879241573399993026873598478532467624301968439714860262264449471888606538913071413634346381428901358109273203087030763779091664797
n_=84078907800136966150486965612788894868587998005459927216462899940718213455112139441858657865215211843183780436155474431592540465189966648565764225210091190218976417210291521208716206733270743675534820816685370480170120230334766919110311980614082807421812749491464201740954627794429460268010183163151688591417
ct=12623780002384219022772693100787925315981488689172490837413686188416255911213044332780064192900824150269364486747430892667624289724721692959334462348218416297309304391635919115701692314532111050955120844126517392040880404049818026059951326039894605004852370344012563287210613795011783419126458214779488303552
e = 260792700

a, b, c = 1,-mygift[0],n
p = (-b+iroot(b*b-4*a*c,2)[0])//(2*a)
q = n//p

a, b, c = 1,-mygift[1],n_
q_ = (-b+iroot(b*b-4*a*c,2)[0])//(2*a)
p_ = n_//q_
d = modinv(e//4,(p-1))
mp = pow(ct,d,p)
d = modinv(e//4,(q-1))
mq = pow(ct,d,q)

# print(gcd(e,(p-1)*(q-1))) # 4
N = [p,q,p_,q_]
C = [mp,mq,mp_,mq_]
m_4 = crt(N,C)[0]
print(p,q,p_,q_)
print(mp,mq,mp_,mq_,m_4)
print(long_to_bytes(iroot(m_4,4)[0]))

中间的那个人

chall.py

from secret import flag
from Crypto.Util.number import *
from Crypto.Cipher import AES
from hashlib import sha256
from random import *

p = getPrime(128)
g = 2
A = getrandbits(32)
B = getrandbits(32)

Alice = pow(g,A,p)
Bob = pow(g,B,p)
key = pow(Alice,B,p)
key = sha256(long_to_bytes(key)).digest()

iv = b"0xGame0xGameGAME"
aes = AES.new(key, AES.MODE_CBC, iv)
enc = aes.encrypt(flag)
print(f'g={g}\np={p}')  #we tell
print(f'Bob={Bob}')     #Bob tell
print(f'Alice={Alice}') #Alice tell

print(f'enc={enc}')#Here is they secret

'''
g=2
p=250858685680234165065801734515633434653
Bob=33067794433420687511728239091450927373
Alice=235866450680721760403251513646370485539
enc=b's\x04\xbc\x8bT6\x846\xd9\xd6\x83 y\xaah\xde@\xc9\x17\xdc\x04v\x18\xef\xcf\xef\xc5\xfd|\x0e\xca\n\xbd#\x94{\x8e[.\xe8\xe1GU\xfa?\xda\x11w'
'''

分析:
p-1光滑 故可以直接求离散对数解出B

from Crypto.Util.number import *
from Crypto.Cipher import AES
from hashlib import sha256
from primefac import *
from sympy import *
from gmpy2 import *

g=2
p=250858685680234165065801734515633434653
Bob=33067794433420687511728239091450927373
Alice=235866450680721760403251513646370485539
enc=b's\x04\xbc\x8bT6\x846\xd9\xd6\x83 y\xaah\xde@\xc9\x17\xdc\x04v\x18\xef\xcf\xef\xc5\xfd|\x0e\xca\n\xbd#\x94{\x8e[.\xe8\xe1GU\xfa?\xda\x11w'
iv = b"0xGame0xGameGAME"
# B = discrete_log(mod(Bob,p),mod(g,p))
# print(B)
# assert pow(g,B,p) == Bob
B = 1620639479
key = pow(Alice,B,p)
key = sha256(long_to_bytes(key)).digest()
aes = AES.new(key, AES.MODE_CBC, iv)
print(aes.decrypt(enc).decode())

EzLFSR

chall.py

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

assert flag == b'0xGame{'+secret+b'}'

def make_mask(m):
    tmp = str(bin(bytes_to_long(m)))[2:].zfill(128)
    return tmp

def string2bits(s):
    return [int(b) for b in s]

def bits2string(bs):
    s = [str(b) for b in bs]
    return ''.join(s)

def lfsr(state, mask):
    assert(len(state) == 128)
    assert(len(mask)  == 128)

    output = 0
    for i in range(128):
        output = output ^ (state[i] & mask[i])

    return output

if __name__ == '__main__':
    initState = [0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0]
    secret = make_mask(secret)
    mask = string2bits(secret)

    for b in secret: assert(b == '0' or b == '1')
    assert(len(secret) == 128)

    for i in range(256):
        state = initState[i:]
        output = lfsr(state, mask)
        initState += [output]

    outputState = bits2string(initState[128:])
    print('outputState =', outputState)

'''
outputState = 1101111111011101100001000011111101001000111000110100010011110111010011100110100100111001101010110110101110000011110101000110010010000011111111001111000110111001100111101110010100100001101001111110001010000100111101011011100010000000100000100000100111010110
'''

学到了一个很好的思路:
^ 可以当作模2意义下的加法 & 可以当作模2意义下的乘法
image

用sage解一个矩阵方程即可

from libnum import *
S = [0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0]
R = '1101111111011101100001000011111101001000111000110100010011110111010011100110100100111001101010110110101110000011110101000110010010000011111111001111000110111001100111101110010100100001101001111110001010000100111101011011100010000000100000100000100111010110'
R = [x for x in R]
S = S + R
A = []
for i in range(128):
    A.append(S[i:i+128])
A = Matrix(Zmod(2),A)
B = vector(Zmod(2),R[:128])
X = A.inverse()*B
print(X)
flag = ''
for x in X:
    flag = str(x)+flag
# print(flag)
print(n2s(int(flag,2)))
print(n2s(int(flag[::-1],2)))

注意是在mod2的意义下解
image

Week3

EzMatrix

chall.py

from Crypto.Util.number import getPrime
from random import randint
from secert import secert,flag
from hashlib import md5
def n2b(n):return md5(str(n).encode()).hexdigest()

assert secert < pow(2,64)
assert flag == '0xGame{'+n2b(secert)+'}'

def Martix2list(Martix):
    result = []
    Martix = list(Martix)
    for i in Martix:
        result.append(list(i))
    return result

A=[[12143520799533590286, 1517884368, 12143520745929978443, 796545089340, 12143514553710344843, 28963398496032, 12143436449354407235, 158437186324560, 12143329129091084963, 144214939188320, 12143459416553205779, 11289521392968],[12143520799533124067, 1552775781, 12143520745442171123, 796372987410, 12143514596803995443, 28617862048776, 12143437786643111987, 155426784993480, 12143333265382547123, 140792203111560, 12143460985399172467, 10983300063372],[12143520799533026603, 1545759072, 12143520746151921286, 781222462020, 12143514741528175043, 27856210942560, 12143440210529480891, 150563969013744, 12143339455702534403, 135941365971840, 12143463119774571623, 10579745342712],[4857408319806885466, 2428704161425648657, 12143520747462241175, 758851601758, 12143514933292307603, 7286139389566980165, 9714738936567334300, 144947557513044, 12143346444338047691, 130561054163540, 4857352974113333366, 2428714303424782417],[12143520799533339320, 1476842796, 12143520749060275613, 733281428880, 12143515144091549812, 25896324662208, 12143446129977471347, 139126289668080, 12143353609086952433, 125093278125816, 12143467808884068695, 9705993135696],[3469577371288079926, 5204366058378782250, 12143520750775862343, 706665985740, 12143515359139397843, 24876891455539, 12143449149385190675, 5204499435641729607, 1734628523990131469, 119757210113970, 12143470097256549947, 9282407958928],[10986995009101166671, 1734788687033207505, 12143520752514668698, 680173911560, 12143515570582515443, 23883386182656, 12143452072344092516, 10408859957710764174, 8673790006740000925, 4047954924507284041, 12143472277719610437, 8879790035168],[12143520799534210329, 8095680534365818753, 12143520754224346525, 6071761054204856029, 12143515774342357443, 22931775530664, 12143454859049102627, 122586336122081, 12143373761302849103, 109840689548590, 8095634066844843878, 8500892291801],[2428704159899526175, 7286112481016467893, 12143520755876491019, 629765964828, 12143515968446948123, 9714838668887734012, 4857345013259425502, 117630592711632, 12143379764863568374, 105318302849760, 2428659620509049335, 7286120625945355053],[7286112479717322389, 7286112480971640825, 12143520757456628435, 606320684970, 12143516152115449139, 4857429497934652454, 4857347490735050126, 112978994964264, 12143385390297217523, 101086824360217, 7286069740980100293, 7286120294834973633],[7727695054246476847, 1202487728, 12143520758958480293, 584144077140, 12143516325240923843, 20377952745696, 12143462294760579275, 108622249048560, 12143390651947217363, 97133513961120, 12143479741445599772, 8831658996900830432],[12143520799535388887, 1161628182, 12143520760380594623, 563225247585, 12143516488091679443, 19626876325056, 12143464472820678035, 104545135017180, 12143395570399006523, 93441517429260, 12143481309754543787, 7218375794633]]# 12*12
p = 12143520799543738643
A = Matrix(GF(p),A)
enc = A**secert

def Martix2list(Martix):
    result = []
    Martix = list(Martix)
    for i in Martix:
        result.append(list(i))
    return result

with open('enc.txt','w') as f:
    f.write(str(Martix2list(enc)))

分析:
这种矩阵幂次的一般都跟相似对角化有关
将 A相似对角化为对角矩阵
image
这样 P和B可以通过A得到
P和C组合后得到一个新的对角阵C' 满足 C' = B ^ m
由对角矩阵的幂次直接就是主对角线上每个元素的幂次
取B中的元和C'中对应的元 满足一个幂次关系 这样discrete_log求解离散对数即可
solution.py

from hashlib import *
A=[[12143520799533590286, 1517884368, 12143520745929978443, 796545089340, 12143514553710344843, 28963398496032, 12143436449354407235, 158437186324560, 12143329129091084963, 144214939188320, 12143459416553205779, 11289521392968],[12143520799533124067, 1552775781, 12143520745442171123, 796372987410, 12143514596803995443, 28617862048776, 12143437786643111987, 155426784993480, 12143333265382547123, 140792203111560, 12143460985399172467, 10983300063372],[12143520799533026603, 1545759072, 12143520746151921286, 781222462020, 12143514741528175043, 27856210942560, 12143440210529480891, 150563969013744, 12143339455702534403, 135941365971840, 12143463119774571623, 10579745342712],[4857408319806885466, 2428704161425648657, 12143520747462241175, 758851601758, 12143514933292307603, 7286139389566980165, 9714738936567334300, 144947557513044, 12143346444338047691, 130561054163540, 4857352974113333366, 2428714303424782417],[12143520799533339320, 1476842796, 12143520749060275613, 733281428880, 12143515144091549812, 25896324662208, 12143446129977471347, 139126289668080, 12143353609086952433, 125093278125816, 12143467808884068695, 9705993135696],[3469577371288079926, 5204366058378782250, 12143520750775862343, 706665985740, 12143515359139397843, 24876891455539, 12143449149385190675, 5204499435641729607, 1734628523990131469, 119757210113970, 12143470097256549947, 9282407958928],[10986995009101166671, 1734788687033207505, 12143520752514668698, 680173911560, 12143515570582515443, 23883386182656, 12143452072344092516, 10408859957710764174, 8673790006740000925, 4047954924507284041, 12143472277719610437, 8879790035168],[12143520799534210329, 8095680534365818753, 12143520754224346525, 6071761054204856029, 12143515774342357443, 22931775530664, 12143454859049102627, 122586336122081, 12143373761302849103, 109840689548590, 8095634066844843878, 8500892291801],[2428704159899526175, 7286112481016467893, 12143520755876491019, 629765964828, 12143515968446948123, 9714838668887734012, 4857345013259425502, 117630592711632, 12143379764863568374, 105318302849760, 2428659620509049335, 7286120625945355053],[7286112479717322389, 7286112480971640825, 12143520757456628435, 606320684970, 12143516152115449139, 4857429497934652454, 4857347490735050126, 112978994964264, 12143385390297217523, 101086824360217, 7286069740980100293, 7286120294834973633],[7727695054246476847, 1202487728, 12143520758958480293, 584144077140, 12143516325240923843, 20377952745696, 12143462294760579275, 108622249048560, 12143390651947217363, 97133513961120, 12143479741445599772, 8831658996900830432],[12143520799535388887, 1161628182, 12143520760380594623, 563225247585, 12143516488091679443, 19626876325056, 12143464472820678035, 104545135017180, 12143395570399006523, 93441517429260, 12143481309754543787, 7218375794633]]# 12*12
p = 12143520799543738643
C = [[11285847990515095003, 7585413350741918021, 11658254512436412666, 477577914899276103, 2941386515764607825, 11283325421744133699, 4096971712575507616, 8118672870538606033, 2377937081025778041, 6576171711896495163, 6152554374963853172, 5022013484610428974], [8354008012616001452, 7787447107046065118, 9504997911333967278, 1082773427768571094, 6015520658629219637, 11244285744740006951, 4493944053220750368, 3504246247470690014, 1738582001618280397, 2330057776906622572, 3043456814665571080, 2981613454022714952], [2508674373714509177, 3544963739532775937, 7952732753025175616, 11161786730565526285, 3397123486689639675, 6454135592624912854, 6613201018024296927, 9748485344986779929, 1819761609989340766, 1259944825407465767, 1596049024644778041, 7769939905324967788], [4200851163596876950, 11960539098651202761, 3303721151143544462, 2532304102428121556, 11083895221097319129, 1171933471304558017, 1549099593543874478, 6088238862927163233, 6459553630361959801, 947358195425767572, 2090533922210134578, 9023030120605201052], [2271102089902208138, 1614812525306266829, 1546249462332047661, 3168333397191737100, 7678980468150522028, 3128939172985153696, 1146041044751755224, 11870173227065140617, 8351303466095252790, 694704483676649448, 7944218023016968278, 583421745603756386], [10309472503110333289, 1100598261990718822, 10235859400888405310, 910925705831020921, 10771855884237562064, 9970830255165655653, 11678899608458971536, 4368822164222204233, 3104861419162339779, 4540709628196554222, 7851809145727500968, 12086896840826708824], [10973051751637593366, 5039073157846327641, 4855314857834773443, 4416954195828423951, 8243966437000815560, 8250554263390748131, 8093181066366682440, 1145520354143718292, 294729013023637045, 10115389386419597159, 2767140395261835843, 6724257139233017485], [6878768250003631244, 10834164422364241529, 6946589221005878489, 539734218479521833, 2691724062063066048, 3989403041446358401, 815244541494093987, 11168528286389981272, 2021358468726921955, 1123433019094267521, 524639025046508882, 5720273332497702547], [6688451244183880831, 10892730373179989558, 6987453292894341174, 5572212176769878684, 11332149024403380575, 3944612864568504791, 6768594304071589280, 10526434024562201079, 10241323610053039912, 1120473558410865753, 306153635148226248, 3606666063074222104], [7556871914690327290, 11353594909211427742, 747771112781361153, 1245068803956910299, 2831489557155431404, 1800035620948876551, 1050411779595241927, 5665981688041778089, 2028968510484240787, 4386552235402890530, 10334391443650474796, 3883841302951550608], [4485787817401669404, 184501191500952934, 3690661645276970957, 6263309802498749034, 6484490370652685031, 9743108369653588026, 3045941510087387269, 5870433915209047275, 4679598273992216016, 11839352681285251516, 4957980185504231911, 7925596893607015470], [1000449712878466719, 7022601702937838844, 1095849907482791166, 11989051568709522226, 6768031250066783733, 185945517026191241, 4280928696740160411, 5633542561098902406, 10176177574499086410, 5782837249861240943, 7406530879613861823, 1971858224839520916]]

A = Matrix(GF(p),A)
C = Matrix(GF(p),C)
B,P = A.diagonalization()

print(B,P)
C = P.inverse()*C*P
a = B[0][0]
c = C[0][0]
m = discrete_log(mod(c,p),mod(a,p))
def n2b(n):return md5(str(n).encode()).hexdigest()
print(n2b(m))

这里sage里的A.diagonalization()会将P和对角化的矩阵都返回
注意这里是在mod p 的意义下求离散对数

LLL-FirstBlood

chall.py

from random import randrange
from Crypto.Util.number import getPrime,bytes_to_long
from secret import flag
assert len(flag) % 4 == 0

length = len(flag)//4
m = [bytes_to_long(flag[i*length:(i+1)*length]) for i in range(4)]
p = getPrime(int(128))

def MakeMask(n,p):
    upper = identity_matrix(n)
    low = identity_matrix(n)
    for i in range(n-1):
        for j in range(i+1, n):    
            upper[i, j] = randrange(1, p)
            low[j, i] = randrange(1, p)
    result = upper * low
    assert det(result) == 1
    return result

def Matrix2List(x):return [list(i) for i in x]

noise = [[randrange(1, p) for i in range(4)] for _ in range(4)]
noise[0] = m
M = matrix(noise)
A = MakeMask(4,p)
C = A*M

print(f'p={p}')
print(f'C={Matrix2List(C)}')

题目名字提示的很清楚了
光做题的话直接(也只能)对C求个LLL
得到
image
'-'去掉即为m1,m2,m3,m4
solution.py

p=198880159035681668071031460916089145469
C=[[1528140902799730745476264672501768332416990282355490479242339131918301176698899635154781328839496210200676497333428, 2081687444435007467807250373278513114045272585243815458840083487459795021302180077490134099644993120009567147202772, 3080873409460299046339495750746632185307246572817534784703936044874106809413620470006445984962733721029566440253675, 3491734341995174183626991907292607070252197520631412767989879432598743851171175369180080355977574296558734415823458], [2359409535809048127331244699867147546817134802610067329431135227991488324148374065940238308147500809599395748756798, 3191196199160821446351036460385791985682645040446022512790815348810555748825420237291839170774872264097466183208742, 4665346530155386457242345394284286198347336281451530670818113876767736288089400119492317775648206643242839430899283, 5369350746042850276067380638571565496087948799720968959426256192923852197959381101839484196445995828389461004495917], [1641407111066265429602929560264443103285908072677065498760570514577412905392260182334706635555256537745902283191251, 2190536173399177167068153351271988931232272884028569669242062395087922275021628334797729266560930040116807133977244, 3127556759140845426132305699421707182108351516931881411928719802847628408656887897596425133523782526561471050447359, 3707239956529200159380870618471703921011276020439315706352183576289925263316580408968092016782483770373121972835410], [9883814543195849013523934427451407019514807606993414569626142656857168165339, 13190422499129347541373922929251088892868361241120937213742340947017395215646, 18832738552342488056498211782604832513006649329982003661701684946590064734701, 22323329751908690611034666068697427811613727429398087082295754189068333861152]]
# Ge = Matrix(C)
# print(Ge.LLL())
from libnum import *
m = [228892343979120176686388,473218447137085890782052,260770537947126049367394,270233647859726974858109]
flag = b''
for x in m:
    flag += n2s(int(x))
print(flag)

但是为什么这道题可以用LLL格基规约出来呢?
我的理解(严格证明暂且不会)是:
将AM=C写成 M = A^-1 x C
C作为格基 大概手算一下A 发现很多数是在p ^ 4, p ^ 3,p ^ 2这种量级的
p为128bit 所以系数矩阵中的值都很大 而M中的noise都是p的量级 所以大致符合短向量这一条件 因此可以对C格基规约

LLL-SecondBlood

chall.py

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

m = bytes_to_long(flag)
q = getPrime(512)
assert m.bit_length() == 318

def encrypt(m):
	mask,noise = getPrime(511),getPrime(50)
	mask_.append(mask)
	noise_.append(noise)
	c = (mask*m + noise)%q
	return c

noise_,mask_  =[[] for _ in range(2)]
c_ = [encrypt(m) for i in range(4)]

print(f'q = {q}\nmask = {mask_}\nc_ = {c_}')

'''
q = 9342426601783650861020119568565656404715236059903009041977149778244153930435908024696666887269890479558473622355346816236972767736577737332173213722012253
mask = [6237128445236992920577225644858662677575951126467888858782461334057970069468925833844231116647406833999142659751374620280213290736114576089069396331226747, 6368031389213953889417545256750169233725975229197446803885029159767701479445576860704561593200907482372690851152126782391126462547524526631934408981070841, 5106473460982791188578285397420642137630347289252852045044021197988607082777231839839730169682158507822078412449827976663385282021916120837408192506341443, 6318090842950331228033349517542810123596316850353637421587264886413877142612686177796023049304908696413386218992511112752788640732410845589679820003047667]
c_ = [3823539664720029027586933152478492780438595004453489251844133830947165342839393878831914879334660250621422877333022321117120398528430519794109624186204492, 1721659645750224819953244995460589691120672649732560768435214608167861246790136217219349234604724148039910656573436663379375048145045443527267790379816425, 668633520079344839648950502380059311916108468801009386138810324259146523323704014491547148973835774917331333581475920804677395949854411894556705238578896, 497860586379981076499130281851986010889356253371192266267220334713415782402939318483926418213877341511996918189750595755372560345085899109305344338944066]
'''

等式很好推 但是这里造格子还是很需要功底的
这里大概找了一个模板图
image
(感觉思路就是使得尽可能稀疏且能够以主对角线简单分块)
构造格
image

# q = 9342426601783650861020119568565656404715236059903009041977149778244153930435908024696666887269890479558473622355346816236972767736577737332173213722012253
# a = [6237128445236992920577225644858662677575951126467888858782461334057970069468925833844231116647406833999142659751374620280213290736114576089069396331226747, 6368031389213953889417545256750169233725975229197446803885029159767701479445576860704561593200907482372690851152126782391126462547524526631934408981070841, 5106473460982791188578285397420642137630347289252852045044021197988607082777231839839730169682158507822078412449827976663385282021916120837408192506341443, 6318090842950331228033349517542810123596316850353637421587264886413877142612686177796023049304908696413386218992511112752788640732410845589679820003047667]
# c_ = [3823539664720029027586933152478492780438595004453489251844133830947165342839393878831914879334660250621422877333022321117120398528430519794109624186204492, 1721659645750224819953244995460589691120672649732560768435214608167861246790136217219349234604724148039910656573436663379375048145045443527267790379816425, 668633520079344839648950502380059311916108468801009386138810324259146523323704014491547148973835774917331333581475920804677395949854411894556705238578896, 497860586379981076499130281851986010889356253371192266267220334713415782402939318483926418213877341511996918189750595755372560345085899109305344338944066]

# Ge = [
#         [q,0,0,0,0,0],
#         [0,q,0,0,0,0],
#         [0,0,q,0,0,0],
#         [0,0,0,q,0,0],
#         [-a[0],-a[1],-a[2],-a[3],1,0],
#         [c_[0],c_[1],c_[2],c_[3],0,2**318]
#     ]
# Ge = Matrix(Ge)
# print(Ge.LLL())
from libnum import *
flag = 404417766109752774365993311026206252937822359426120081323087457724287886115277329019989616964477
print(n2s(int(flag)))

Week4

NormalECC

from Crypto.Util.number import getPrime
from Crypto.Cipher import AES
from random import getrandbits
from secret import flag,M
from hashlib import md5

def MD5(m):return md5(str(m).encode()).hexdigest()

p = 11093300438765357787693823122068501933326829181518693650897090781749379503427651954028543076247583697669597230934286751428880673539155279232304301123931419
a = getPrime(int(512))
b = getPrime(int(512))
assert p>a
assert p>b
E = EllipticCurve(GF(p),[a,b])
G = E.random_point()
k = getPrime(int(512))
K = k*G
r = getrandbits(64)
M = E(M)

C1 = M + r*K
C2 = r*G

assert '0xGame{'+MD5( M.xy()[0] )+'}' == flag

print(f'p={p}\na={a}\nb={b}')
print(f'G={G.xy()}')
print(f'K={K.xy()}')
print(f'C1={C1.xy()}')
print(f'C2={C2.xy()}')
'''
p=11093300438765357787693823122068501933326829181518693650897090781749379503427651954028543076247583697669597230934286751428880673539155279232304301123931419
a=7150069360142473220874778371025253986400531606173784255855621272842352949822722345927984117158003009207785424116052251585892319431674211713978446093533949
b=8963713118505064052475299691180792684131316295319527298757291586802733177771327455119311985236802185776962863601191772056992397979199759282886953573897623
G=(4070512847946293053993474472718195445326650730220767223671483350865356914474371813956296088808339388116138119830978356761203350661975684819340687599188773, 7919267117945460629179349735575165185291048599591225961407006624231142667171694867758723087028969163792156367031144131919207578182780960301059191834343484)
K=(3429071535068496391288385908059514112858019444898682888326563488381066866765760330150826456161675891783443971423132174003430225228636705672269386133448242, 10156980123178962109303543933598555000559941757051056925651640103802811004794287116521872896690665760105638977618361662092227807698111279640177447796532347)
C1=(4139336890213227868613795086096336512836348527349045673681270821212710038308856344020383776363498787598928112315425033118240925101586130966715819924212989, 8496671787567254905958613320810855596994019625894595967770545586397682431545287861458500877647243710691962626334781301359445519608668358210417703062746989)
C2=(2151204832133866138854176239337864259798539350706680161553247616590123485482950549170787112029461554837485268534053338274459614702685163614673775491725035, 612484077350471488714018386040340578068868389564012902083181785403536097453280569723896780143638704225018931513080350876551883282131207177391746460216488)
'''

曲线的阶和p相等 smartattack即可

from sage.all import *

p=11093300438765357787693823122068501933326829181518693650897090781749379503427651954028543076247583697669597230934286751428880673539155279232304301123931419
a=7150069360142473220874778371025253986400531606173784255855621272842352949822722345927984117158003009207785424116052251585892319431674211713978446093533949
b=8963713118505064052475299691180792684131316295319527298757291586802733177771327455119311985236802185776962863601191772056992397979199759282886953573897623
E = EllipticCurve(GF(p), [a, b])
G=E(4070512847946293053993474472718195445326650730220767223671483350865356914474371813956296088808339388116138119830978356761203350661975684819340687599188773, 7919267117945460629179349735575165185291048599591225961407006624231142667171694867758723087028969163792156367031144131919207578182780960301059191834343484)
K=E(3429071535068496391288385908059514112858019444898682888326563488381066866765760330150826456161675891783443971423132174003430225228636705672269386133448242, 10156980123178962109303543933598555000559941757051056925651640103802811004794287116521872896690665760105638977618361662092227807698111279640177447796532347)
C1=E(4139336890213227868613795086096336512836348527349045673681270821212710038308856344020383776363498787598928112315425033118240925101586130966715819924212989, 8496671787567254905958613320810855596994019625894595967770545586397682431545287861458500877647243710691962626334781301359445519608668358210417703062746989)
C2=E(2151204832133866138854176239337864259798539350706680161553247616590123485482950549170787112029461554837485268534053338274459614702685163614673775491725035, 612484077350471488714018386040340578068868389564012902083181785403536097453280569723896780143638704225018931513080350876551883282131207177391746460216488)


E = EllipticCurve(GF(p), [a, b])
def SmartAttack(P,Q,p):
    E = P.curve()
    Eqp = EllipticCurve(Qp(p, 2), [ ZZ(t) + randint(0,p)*p for t in E.a_invariants() ])

    P_Qps = Eqp.lift_x(ZZ(P.xy()[0]), all=True)
    for P_Qp in P_Qps:
        if GF(p)(P_Qp.xy()[1]) == P.xy()[1]:
            break

    Q_Qps = Eqp.lift_x(ZZ(Q.xy()[0]), all=True)
    for Q_Qp in Q_Qps:
        if GF(p)(Q_Qp.xy()[1]) == Q.xy()[1]:
            break

    p_times_P = p*P_Qp
    p_times_Q = p*Q_Qp

    x_P,y_P = p_times_P.xy()
    x_Q,y_Q = p_times_Q.xy()

    phi_P = -(x_P/y_P)
    phi_Q = -(x_Q/y_Q)
    k = phi_Q/phi_P
    return ZZ(k)

r = SmartAttack(G,C2,p)
print(r)
r = 45840949424430882760955413723991162273980870535626561751713539365334957869729637484824862183800010513468339210713990392892179589524907920006728894081809713349698517652251375968486559316600026071366900520275441319289649772170835798945444943411843128104479490593518558647899827469892207316254350208648026704938
M = C1-r*K
from hashlib import md5

def MD5(m):return md5(str(m).encode()).hexdigest()
print('0xGame{'+MD5( M.xy()[0] )+'}')

DangerLeak

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

m = bytes_to_long(flag)
p = getPrime(1024)
q = getPrime(1024)
n = p * q
phi = (p - 1) * (q - 1)
while True:
    M = getrandbits(954)
    d0 = getrandbits(70)
    d1 = getrandbits(60)
    d = M * d1 + d0
    e = inverse(d, (p - 1) * (q - 1))
    if GCD(d,phi) == 1:
    	break


c = pow(m,e,n)
print(f'n = {n}')
print(f'e = {e}', )
print(f'c = {c}')
print(f'leak={M}')

'''
n = 20890649807098098590988367504589884104169882461137822700915421138825243082401073285651688396365119177048314378342335630003758801918471770067256781032441408755600222443136442802834673033726750262792591713729454359321085776245901507024843351032181392621160709321235730377105858928038429561563451212831555362084799868396816620900530821649927143675042508754145300235707164480595867159183020730488244523890377494200551982732673420463610420046405496222143863293721127847196315699011480407859245602878759192763358027712666490436877309958694930300881154144262012786388678170041827603485103596258722151867033618346180314221757
e = 18495624691004329345494739768139119654869294781001439503228375675656780205533832088551925603457913375965236666248560110824522816405784593622489392063569693980307711273262046178522155150057918004670062638133229511441378857067441808814663979656329118576174389773223672078570346056569568769586136333878585184495900769610485682523713035338815180355226296627023856218662677851691200400870086661825318662718172322697239597148304400050201201957491047654347222946693457784950694119128957010938708457194638164370689969395914866589468077447411160531995194740413950928085824985317114393591961698215667749937880023984967171867149
c = 7268748311489430996649583334296342239120976535969890151640528281264037345919563247744198340847622671332165540273927079037288463501586895675652397791211130033797562320858177249657627485568147343368981852295435358970875375601525013288259717232106253656041724174637307915021524904526849025976062174351360431089505898256673035060020871892556020429754849084448428394307414301376699983203262072041951835713075509402291301281337658567437075609144913905526625759374465018684092236818174282777215336979886495053619105951835282087487201593981164477120073864259644978940192351781270609702595767362731320959397657161384681459323
leak=136607909840146555806361156873618892240715868885574369629522914036807393164542930308166609104735002945881388216362007941213298888307579692272865700211608126496105057113506756857793463197250909161173116422723246662094695586716106972298428164926993995948528941241037242367190042120886133717
'''

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