D^3CTF 2022

D^3CTF

赛题质量很高,题目都设计的很好呀,前三道是比较简单的,另外三道有点难,照着官方wp复现一部分

d3factor

from Crypto.Util.number import bytes_to_long, getPrime
from secret import msg
from sympy import nextprime
from gmpy2 import invert
from hashlib import md5

flag = 'd3ctf{'+md5(msg).hexdigest()+'}'
p = getPrime(256)
q = getPrime(256)
assert p > q
n = p * q
e = 0x10001
m = bytes_to_long(msg)
c = pow(m, e, n)

N = pow(p, 7) * q
phi = pow(p, 6) * (p - 1) * (q - 1)
d1 = getPrime(2000)
d2 = nextprime(d1 + getPrime(1000))
e1 = invert(d1, phi)
e2 = invert(d2, phi)

print(f'c = {c}')
print(f'N = {N}')
print(f'e1 = {e1}')
print(f'e2 = {e2}')
'''
c = 2420624631315473673388732074340410215657378096737020976722603529598864338532404224879219059105950005655100728361198499550862405660043591919681568611707967
N = 1476751427633071977599571983301151063258376731102955975364111147037204614220376883752032253407881568290520059515340434632858734689439268479399482315506043425541162646523388437842149125178447800616137044219916586942207838674001004007237861470176454543718752182312318068466051713087927370670177514666860822341380494154077020472814706123209865769048722380888175401791873273850281384147394075054950169002165357490796510950852631287689747360436384163758289159710264469722036320819123313773301072777844457895388797742631541101152819089150281489897683508400098693808473542212963868834485233858128220055727804326451310080791
e1 = 425735006018518321920113858371691046233291394270779139216531379266829453665704656868245884309574741300746121946724344532456337490492263690989727904837374279175606623404025598533405400677329916633307585813849635071097268989906426771864410852556381279117588496262787146588414873723983855041415476840445850171457530977221981125006107741100779529209163446405585696682186452013669643507275620439492021019544922913941472624874102604249376990616323884331293660116156782891935217575308895791623826306100692059131945495084654854521834016181452508329430102813663713333608459898915361745215871305547069325129687311358338082029
e2 = 1004512650658647383814190582513307789549094672255033373245432814519573537648997991452158231923692387604945039180687417026069655569594454408690445879849410118502279459189421806132654131287284719070037134752526923855821229397612868419416851456578505341237256609343187666849045678291935806441844686439591365338539029504178066823886051731466788474438373839803448380498800384597878814991008672054436093542513518012957106825842251155935855375353004898840663429274565622024673235081082222394015174831078190299524112112571718817712276118850981261489528540025810396786605197437842655180663611669918785635193552649262904644919
'''

d2比d1大1000bits的样子,与d1的比特数差的有点多,考虑构造关于差值的等式进行copper

消掉d1后得到式子\(e_1e_2x-(e_1-e_2)=0mod(phi)\)

注意到phi与N均含有p6=>p6>N3/4

取beta=0.75即可,epsilon的约束比较宽松

"""
c = 2420624631315473673388732074340410215657378096737020976722603529598864338532404224879219059105950005655100728361198499550862405660043591919681568611707967
N = 1476751427633071977599571983301151063258376731102955975364111147037204614220376883752032253407881568290520059515340434632858734689439268479399482315506043425541162646523388437842149125178447800616137044219916586942207838674001004007237861470176454543718752182312318068466051713087927370670177514666860822341380494154077020472814706123209865769048722380888175401791873273850281384147394075054950169002165357490796510950852631287689747360436384163758289159710264469722036320819123313773301072777844457895388797742631541101152819089150281489897683508400098693808473542212963868834485233858128220055727804326451310080791
e1 = 425735006018518321920113858371691046233291394270779139216531379266829453665704656868245884309574741300746121946724344532456337490492263690989727904837374279175606623404025598533405400677329916633307585813849635071097268989906426771864410852556381279117588496262787146588414873723983855041415476840445850171457530977221981125006107741100779529209163446405585696682186452013669643507275620439492021019544922913941472624874102604249376990616323884331293660116156782891935217575308895791623826306100692059131945495084654854521834016181452508329430102813663713333608459898915361745215871305547069325129687311358338082029
e2 = 1004512650658647383814190582513307789549094672255033373245432814519573537648997991452158231923692387604945039180687417026069655569594454408690445879849410118502279459189421806132654131287284719070037134752526923855821229397612868419416851456578505341237256609343187666849045678291935806441844686439591365338539029504178066823886051731466788474438373839803448380498800384597878814991008672054436093542513518012957106825842251155935855375353004898840663429274565622024673235081082222394015174831078190299524112112571718817712276118850981261489528540025810396786605197437842655180663611669918785635193552649262904644919
PR.<x>=PolynomialRing(Zmod(N))
f=e1*e2*x-(e1-e2)
f=f.monic()
root=f.small_roots(X=2^1020,beta=0.75,epsilon=0.05)
print(e1*e2*root[0]-(e1-e2))

#output: 5498330243880825560336478154736411141592210908996313792046872054395398976679658325464312879090781305712698211596905825314106279441934035902545571237383430582051583244045985067458074575709473242707792625147725353815630560698228239913024228898186759660641368985679517024637086608415503468609683417679307728323433958210505654874722780394972014173838885916015811709092514670099647558318976889851674968105042856608773879099153620896269003572797579241474129549520952511194990317515806784426147925237659681587436469337994396402152317182880013883191329924124799500677464595648928836140539357418053230423056611355264914728
"""

import gmpy2
from Crypto.Util.number import *
from hashlib import md5
t=5498330243880825560336478154736411141592210908996313792046872054395398976679658325464312879090781305712698211596905825314106279441934035902545571237383430582051583244045985067458074575709473242707792625147725353815630560698228239913024228898186759660641368985679517024637086608415503468609683417679307728323433958210505654874722780394972014173838885916015811709092514670099647558318976889851674968105042856608773879099153620896269003572797579241474129549520952511194990317515806784426147925237659681587436469337994396402152317182880013883191329924124799500677464595648928836140539357418053230423056611355264914728
c = 2420624631315473673388732074340410215657378096737020976722603529598864338532404224879219059105950005655100728361198499550862405660043591919681568611707967
N = 1476751427633071977599571983301151063258376731102955975364111147037204614220376883752032253407881568290520059515340434632858734689439268479399482315506043425541162646523388437842149125178447800616137044219916586942207838674001004007237861470176454543718752182312318068466051713087927370670177514666860822341380494154077020472814706123209865769048722380888175401791873273850281384147394075054950169002165357490796510950852631287689747360436384163758289159710264469722036320819123313773301072777844457895388797742631541101152819089150281489897683508400098693808473542212963868834485233858128220055727804326451310080791
e1 = 425735006018518321920113858371691046233291394270779139216531379266829453665704656868245884309574741300746121946724344532456337490492263690989727904837374279175606623404025598533405400677329916633307585813849635071097268989906426771864410852556381279117588496262787146588414873723983855041415476840445850171457530977221981125006107741100779529209163446405585696682186452013669643507275620439492021019544922913941472624874102604249376990616323884331293660116156782891935217575308895791623826306100692059131945495084654854521834016181452508329430102813663713333608459898915361745215871305547069325129687311358338082029
e2 = 1004512650658647383814190582513307789549094672255033373245432814519573537648997991452158231923692387604945039180687417026069655569594454408690445879849410118502279459189421806132654131287284719070037134752526923855821229397612868419416851456578505341237256609343187666849045678291935806441844686439591365338539029504178066823886051731466788474438373839803448380498800384597878814991008672054436093542513518012957106825842251155935855375353004898840663429274565622024673235081082222394015174831078190299524112112571718817712276118850981261489528540025810396786605197437842655180663611669918785635193552649262904644919
p=gmpy2.iroot(gmpy2.gcd(t,N),6)[0]
q=N//(p**7)
d=gmpy2.invert(0x10001,(p-1)*(q-1))
msg=long_to_bytes(pow(c,d,p*q))
flag = 'd3ctf{'+md5(msg).hexdigest()+'}'
print(flag)

d3qcg

from Crypto.Util.number import *
import random
from random import randint
from gmpy2 import *
from secret import flag
import hashlib
assert b'd3ctf' in flag
Bits = 512
UnKnownBits = 146

class QCG():
    def __init__(self,bit_length):
        p = getPrime(bit_length)
        a = randint(0,p)
        c = randint(0,p)
        self._key = {'a':a,'c':c,'p':p}
        self.secret = randint(0,p)
        self.high = []
    def Qnext(self,num):
        return ((self._key['a'])*num**2+self._key['c'])%self._key['p']
    
    def hint(self):
        num = self.secret
        for i in range(2):
            num = self.Qnext(num)
            self.high.append(num>>UnKnownBits)
    def get_key(self):
        return self._key
    def get_hint(self):
        return self.high

Q1 = QCG(Bits)
print(Q1.get_key())
#{'a': 3591518680290719943596137190796366296374484536382380061852237064647969442581391967815457547858969187198898670115651116598727939742165753798804458359397101, 'c': 6996824752943994631802515921125382520044917095172009220000813718617441355767447428067985103926211738826304567400243131010272198095205381950589038817395833, 'p': 7386537185240346459857715381835501419533088465984777861268951891482072249822526223542514664598394978163933836402581547418821954407062640385756448408431347}
Q1.hint()
print(Q1.get_hint())
#[67523583999102391286646648674827012089888650576715333147417362919706349137337570430286202361838682309142789833, 70007105679729967877791601360700732661124470473944792680253826569739619391572400148455527621676313801799318422]
enc = bytes_to_long(hashlib.sha512(b'%d'%(secret)).digest())^bytes_to_long(flag)
print(enc)
# 6176615302812247165125832378994890837952704874849571780971393318502417187945089718911116370840334873574762045429920150244413817389304969294624001945527125

QCG即Quadratic congruence generator

注意到题目输出时会截断低146位,设截断位为x,y,根据递推构造函数多元copper即可

import itertools

def small_roots(f, bounds, m=1, d=None):
        if not d:
                d = f.degree()

        R = f.base_ring()
        N = R.cardinality()

        f /= f.coefficients().pop(0)
        f = f.change_ring(ZZ)

        G = Sequence([], f.parent())
        for i in range(m+1):
                base = N^(m-i) * f^i
                for shifts in itertools.product(range(d), repeat=f.nvariables()):
                        g = base * prod(map(power, f.variables(), shifts))
                        G.append(g)

        B, monomials = G.coefficient_matrix()
        monomials = vector(monomials)

        factors = [monomial(*bounds) for monomial in monomials]
        for i, factor in enumerate(factors):
                B.rescale_col(i, factor)

        B = B.dense_matrix().LLL()

        B = B.change_ring(QQ)
        for i, factor in enumerate(factors):
                B.rescale_col(i, 1/factor)

        H = Sequence([], f.parent().change_ring(QQ))
        for h in filter(None, B*monomials):
                H.append(h)
                I = H.ideal()
                if I.dimension() == -1:
                        H.pop()
                elif I.dimension() == 0:
                        roots = []
                        for root in I.variety(ring=ZZ):
                                root = tuple(R(root[var]) for var in f.variables())
                                roots.append(root)
                        return roots
        return []
        
a= 3591518680290719943596137190796366296374484536382380061852237064647969442581391967815457547858969187198898670115651116598727939742165753798804458359397101
c=6996824752943994631802515921125382520044917095172009220000813718617441355767447428067985103926211738826304567400243131010272198095205381950589038817395833
p=7386537185240346459857715381835501419533088465984777861268951891482072249822526223542514664598394978163933836402581547418821954407062640385756448408431347
h=[67523583999102391286646648674827012089888650576715333147417362919706349137337570430286202361838682309142789833, 70007105679729967877791601360700732661124470473944792680253826569739619391572400148455527621676313801799318422]
h[0]=h[0]<<146
h[1]=h[1]<<146
PR.<x,y>=PolynomialRing(Zmod(p))
f=a*(h[0]+x)^2+c-h[1]-y
bounds=(2^146,2^146)
print(small_roots(f,bounds,m=3,d=4))
#------
import gmpy2
a=3591518680290719943596137190796366296374484536382380061852237064647969442581391967815457547858969187198898670115651116598727939742165753798804458359397101
c= 6996824752943994631802515921125382520044917095172009220000813718617441355767447428067985103926211738826304567400243131010272198095205381950589038817395833
p=7386537185240346459857715381835501419533088465984777861268951891482072249822526223542514664598394978163933836402581547418821954407062640385756448408431347
h=[67523583999102391286646648674827012089888650576715333147417362919706349137337570430286202361838682309142789833, 70007105679729967877791601360700732661124470473944792680253826569739619391572400148455527621676313801799318422]
t=50712831100361370819145886978385347931029768
pad1=(h[0]<<146)+t
s2=(pad1-c)*gmpy2.invert(a,p)%p
print(s2)
#------
p=7386537185240346459857715381835501419533088465984777861268951891482072249822526223542514664598394978163933836402581547418821954407062640385756448408431347
ss=4508722024464242774844580634679202019739970390460001982611686314565408465605990967298630328780463883701424894922522261864494015405770113222925776958816402
PR.<x>=PolynomialRing(Zmod(p))
f=x^2-ss
print(f.roots())
#------
import hashlib
from Crypto.Util.number import *
enc=6176615302812247165125832378994890837952704874849571780971393318502417187945089718911116370840334873574762045429920150244413817389304969294624001945527125
s2=3345361405203462981041847914374453868599106060665812229784462734764742247048957655005612474587555839753748604882708741687926147536458567411789178129398205
flag =long_to_bytes(bytes_to_long(hashlib.sha512(b'%d'%(s2)).digest())^enc)
print(flag)

比赛的时候还了解了一下二次生成器的一些攻击(paper提供的是一种更强的对于QCG的攻击方式)

paper

照着paper的方向自己实现了一下CVP,只能说数据还是差了一点,paper采用的SVP,后面一部分实在看不下去了,仅作参考吧,以后有时间再来看看

d3bug

from Crypto.Util.number import *
from secret import flag
assert flag.startswith("D3CTF{")
assert flag.endswith("}")
message = bytes_to_long(flag[6:-1])
assert message < 2**64
mask = 0b1010010000001000000010001001010010100100000010000000100010010100

def lfsr_MyCode(R,mask):
    output = (R << 1) & 0xffffffffffffffff
    i = (R ^ mask) & 0xffffffffffffffff
    lastbit = 0
    while i != 0:
        lastbit ^= (i & 1)
        i = i>>1
    output ^= lastbit
    return (output,lastbit)

def lfsr_CopiedfromInternet(R,mask):
    output = (R << 1) & 0xffffffffffffffff
    i = (R & mask) & 0xffffffffffffffff
    lastbit = 0
    while i != 0:
        lastbit ^= (i & 1)
        i = i>>1
    output ^= lastbit
    return (output,lastbit)

f=open("standardResult","w")
R=message
for i in range(35):
    (R, out) = lfsr_CopiedfromInternet(R,mask)
    f.write(str(out))
f.close()

f=open("myResult","w")
R=message
for i in range(35):
    (R, out) = lfsr_MyCode(R,mask)
    f.write(str(out))
f.close()

#Why are the results always different?!!
#Can you help me debug my code? QAQ

首先推lfsr_MyCode的规律,可以看作是在模2下各位相加再加上mask的各位相加,由于mask有偶数个1故无需考虑

观察MyCode的输出流,即状态为偶数个1时输出0,奇数个1时输出1,刚开始状态为偶数个1,则输出0

在状态向左平移的过程中,若去掉0,下一次输出仍为0,若为1下一次输出则为1,由此可知MyCode的第2~35位输出是seed的前34位

我们又已知标准lfsr的前35位输出,对已知的共69位lfsr的比特位还原,在尝试的过程中我尽可能地拟合seed的前34位数据后面的数据用已知标准输出填充,得到的结构用两种lfsr输出,看是否一致即可

mask='1010010000001000000010001001010010100100000010000000100010010100'
sign1='0100110001000110001101010101001001'
sign2='01111101111010111000010010111001101'
v=[]
A=Matrix.zero(64)
for i in range(63):
    A[i,i+1]=1
for i in range(64):
    A[63,i]=int(mask[i])
    v.append(int(mask[i]))
A=Matrix(GF(2),A)
v=vector(GF(2),v)
T=Matrix.zero(64)
for i in range(34):
    T[i,i]=1
for i in range(30):
    temp=v*A^i
    T[i+34]=temp
T=Matrix(GF(2),T)
vv=[]
for i in range(34):
    vv.append(int(sign1[i]))
for i in range(30):
    vv.append(int(sign2[i]))
vv=vector(GF(2),vv)
s=T^(-1)*vv
s=list(s)
for i in range(len(s)):
    print(s[i],end='')

equivalent

from collections import namedtuple
from Crypto.Util import number
from Crypto.Random import random


PublicKey = namedtuple('PublicKey', ['a'])
SecretKey = namedtuple('SecretKey', ['s', 'e', 'p'])



def keygen(sbit, N):
    s_ = [random.getrandbits(sbit) | 1 for _ in range(N)]

    pbit = sum(s_).bit_length() + 1
    p = number.getPrime(pbit)
    while not (sum(s_) < p < 2*sum(s_)):
        p = number.getPrime(pbit)
    e = random.randint(p//2, p-1)

    a_ = [e*s_i % p for s_i in s_]

    assert 2**N > max(a_)

    pk = PublicKey(a_)
    sk = SecretKey(s_, e, p)

    return (pk, sk)


def enc(m, pk):
    assert 0 <= m < 2
    n = len(pk.a)
    r_ = [random.getrandbits(1) for _ in range(n-1)]
    r_n = (m - sum(r_)) % 2
    r_.append(r_n)
    c = sum(a_i*r_i for a_i, r_i in zip(pk.a, r_))
    return c


def dec(c, sk):
    e_inv = number.inverse(sk.e, sk.p)
    m = (e_inv * c % sk.p) % 2
    return m


def encrypt(msg, pk):
    bits = bin(number.bytes_to_long(msg))[2:]
    cip = [enc(m, pk) for m in map(int, bits)]
    return cip


def decrypt(cip, sk):
    bits = [dec(c, sk) for c in cip]
    msg = number.long_to_bytes(int(''.join(map(str, bits)), 2))
    return msg


if __name__ == "__main__":
    from secret import FLAG

    pk, sk = keygen(sbit=80, N=100)

    msg = FLAG.removeprefix(b"d3ctf{").removesuffix(b"}")
    cip = encrypt(msg, pk)

    assert msg == decrypt(cip, sk)

    with open("data.txt", 'w') as f:
        f.write(f"pk = {pk}\n")
        f.write(f"cip = {cip}\n")

一开始就一直在做这个,开始以为就是个简单的背包变形,发现LLL和BKZ都没法解决问题的时候我就觉得估计又是哪篇paper的attack了

paper

属实看着有点懵,又重新看了一下knapsack才知道我之前了解的直接LLL的攻击只能对低密度背包使用

Knapsack系统的密度为\(d=\frac{n}{log_2(max\{a_i\})}\)(ai为公钥)

paper提供的应该是对一种高密度背包的攻击

格学的还是不太行,有些地方看不太明白

只能先放着了,下次一定复现😢

leak_dsa

from hashlib import sha256
from secret import flag
from Crypto.Util.number import *
from random import *
import os
from binascii import *
def gen_key(qbit , pbit):
    q = getPrime(qbit)
    while 1:
        p = getrandbits(pbit-qbit)*q + 1
        if isPrime(p):
            break
    while 1:
        h = randint(1 , p)
        g = pow(h , (p-1)//q , p)
        if g != 1:
            break
    d = randint(1 , q-1)
    y = pow(g,d,p)
    pubkey = (p ,q , g ,y)
    prikey = (p ,q ,g ,y , d)
    return pubkey , prikey

def sign(prikey , m):
    p,q,g,y,d = prikey
    k = randint(1 , q-1)
    r = pow(g , k , p) % q
    s = inverse(k , q) * (int(sha256(m).hexdigest(),16)+ d * r) % q
    return (r , s) , k
def verify(pubkey , m , r ,s ):
    p,q,g,y = pubkey
    w = inverse(s , q)
    u1 = int(sha256(m).hexdigest(),16) * w % q
    u2 = r * w % q
    if r == pow(g , u1 , p)*pow(y , u2,p)% q:
        return 1
    return 0
N = 70
pubkey , prikey = gen_key(256 , 2048)
f = open('./cipher.txt' , 'w')
f.write(str(pubkey) + '\n')
for i in range(N):
    m = os.urandom(10)
    signature , gift = sign(prikey , m)
    mask = getrandbits(256)
    f.write(hexlify(m).decode() + ',' + str(signature) +',' +str(mask & gift) +','+ str(mask) + '\n')

assert flag[:6] == b'd3ctf{' and flag[-1:] == b'}'
assert flag[6:-1] == sha256(str(prikey[-1]).encode()).hexdigest()

先了解一下HNP问题

大概就是解一系列具有模糊变量的一元一次模方程组

即Aix+Bi=kimod(N)

其中我们不知道具体的ki但是我们知道ki的比特数

不妨设比特数为K

构造格

\(L=\left[\begin{matrix}N&\\&N\\&&N\\&&&N\\...\\&&&&&N\\A_1&A_2&A_3&A_4&...&A_t&K/N\\B_1&B_2&B_3&B_4&...&B_t&&K\end{matrix}\right]\)

可知向量(k1 k2 ... kt \(\frac{Kx}{N}\) K)在格L上

可以证明的是当ki不大且获取数据组t较大时我们可以使用LLL找到该向量,从而解出x

回到该问题,由于题目并没有给出我们k的比特数,但是给出了多组签名,并且给了k的随机掩码位的值,根据wp我们要做的是将此问题划归到解HNP上

一开始看wp看着是真头疼,后来问了一下出题人就勉勉强强能够想明白了,这里记录一下大致思路

首先我们得到了k&mask的信息,也就是k的部分bits,那我们如何利用这个信息划归到hnp呢

设k=k&mask+∑ki2ti(ki是mask中的两个1之间的位置bits)

构造格

\(L=\left[\begin{matrix}q\\&q\\&&q\\...\\&&&&q\\2^{t_0}&2^{t_1}&2^{t_2}&...&2^{t_s}\end{matrix}\right]\)

通过对L使用LLL算法求得一个最短向量v

即gL[-1]mod(q)=v,把g求出来

规约的时候可以和wp一样在两边配一个平衡矩阵

于是我们对\(∑k_i2^{ti}\)乘以g可以使得其尽可能的小,通过实验可以发现大约在251bits,这样就可以使用hnp进行问题的解决了

=>\(k=k\&mask+∑k_i2^{ti}=s^{-1}h+s^{-1}rx\)

=>\(∑k_i2^{ti}=s^{-1}h+s^{-1}rx-k\&mask\)

=>\(g(s^{-1}h+s^{-1}rx-k\&mask)=g∑k_i2^{ti}\)~251bits

于是\(A=gs^{-1}r;B=g(s^{-1}h-k\&mask)\)

Ax+B=V(modq)其中V大约为251bits

利用所给数据求出多组A,B最后解个HNP问题即可

代码实现由于还有些细节没整明白就先咕咕咕了

这个是shallow的github上的代码shallow

d3share

#!sage
import random
from hashlib import sha256
from Crypto.Util.number import *

class KeyPredistribution:
    # a key predistribution scheme in 《A Random Perturbation-Based Scheme for Pairwise Key Establishment in Sensor Networks》
    def __init__(self ,p , t ,r , N):
        self.p = p
        self.t = t
        self.r = r
        self.N = N
        self.F = self.random_symmetric_polynomial()
        self.random_perturbation_polynomials()
    def random_symmetric_polynomial(self):
        P = PolynomialRing(GF(self.p) , "x,y")
        x , y = P.gens()
        F = 0
        for i in range(self.t+1):
            for j in range(self.t+1):
                r = GF(self.p).random_element()
                F += r * x^i * y^j +r * y^i * x^j 
        return F
    def random_perturbation_polynomials(self):
        P = PolynomialRing(GF(self.p) , 'y')
        g = P.random_element(degree = self.t , total = self.t+1)
        h = P.random_element(degree = self.t , total = self.t+1)
        S = []
        while len(S) < self.N:
            e = GF(self.p).random_element()
            if e not in S:
                if g(e) < self.r and h(e) < self.r:
                    S.append(e)
                
        self.g = g
        self.h = h
        self.S = S
    def get_node(self, index):
        if index > len(self.S):
            print("index out of range")
            return 0
        xi = self.S[index]
        _ , y = self.F.parent().gens()
        f = self.F(xi , y)
        r = random.randint(0 , 1)
        f += r*self.g + (1-r)*self.h
        pubkey = xi
        prikey = f
        return (pubkey , prikey)

def share_secret(a_prikey , b_pubkey , r):
    f = a_prikey
    xj = b_pubkey
    share = f(xj) >> (int(log(r , 2))+1)
    return share, sha256(share)
p = 2**48 - 59
r = 2**38
t = 40
n = 43
KP = KeyPredistribution(p , t ,r , n)
hint = KP.F(0,0)
# hint = 35327434352315
f = open('./data.txt' , 'w')
for i in range(n):
    node = KP.get_node(i)
    f.write(str(node) + '\n')
f.close()
flag = 'd3ctf{' + sha256(b''.join([long_to_bytes(int(i)) for i in KP.F.coefficients()])).hexdigest() + '}'
print(flag)

似乎是实现一个新的加密体制,不想再看paper了,留给以后复现吧🏃


wait for update

posted @ 2022-03-13 13:35  hash_hash  阅读(1136)  评论(0)    收藏  举报