hgame2025-Crypto小记

发现积压在文件夹有一段时间了。整理一下发出来。

suprimeRSA

task.py

from Crypto.Util.number import *
import random
from sympy import prime
FLAG=b'hgame{xxxxxxxxxxxxxxxxxx}'
e=0x10001
def primorial(num):
print(num)
result = 1
for i in range(1, num + 1):
result *= prime(i)
return result
M=primorial(random.choice([39,71,126]))
def gen_key():
while True:
k = getPrime(random.randint(20,40))
a = getPrime(random.randint(20,60))
p = k * M + pow(e, a, M)
if isPrime(p):
return p
p,q=gen_key(),gen_key()
n=p*q
m=bytes_to_long(FLAG)
enc=pow(m,e,n)
print(n.bit_length())
print(f'{n=}')
print(f'{enc=}') """
n=787190064146025392337631797277972559696758830083248285626115725258876808514690830730702705056550628756290183000265129340257928314614351263713241
enc=365164788284364079752299551355267634718233656769290285760796137651769990253028664857272749598268110892426683253579840758552222893644373690398408
"""

其实是CVE-2017-15361

介绍这个攻击的友联:ROCA攻击——CVE-2017-15361 | crumbling's secret room

GKCTF2020_Crypto_复现_仿射密码在线解密器-CSDN博客之前就出现过,网上有exp

exp



from sage.all import *
from tqdm import tqdm

def solve(M, n, a, m):
# I need to import it in the function otherwise multiprocessing doesn't find it in its context
from sage_functions import coppersmith_howgrave_univariate

base = int(65537)
# the known part of p: 65537^a * M^-1 (mod N)
known = int(pow(base, a, M) * inverse_mod(M, n))
# Create the polynom f(x)
F = PolynomialRing(Zmod(n), implementation='NTL', names=('x',))
(x,) = F._first_ngens(1)
pol = x + known
beta = 0.1
t = m+1
# Upper bound for the small root x0
XX = floor(2 * n**0.5 / M)
# Find a small root (x0 = k) using Coppersmith's algorithm
roots = coppersmith_howgrave_univariate(pol, n, beta, m, t, XX)
# There will be no roots for an incorrect guess of a.
for k in roots:
# reconstruct p from the recovered k
p = int(k*M + pow(base, a, M))
if n%p == 0:
return p, n//p

def roca(n):

keySize = n.bit_length()

if keySize <= 960:
M_prime = 0x1b3e6c9433a7735fa5fc479ffe4027e13bea
m = 5

elif 992 <= keySize <= 1952:
M_prime = 0x24683144f41188c2b1d6a217f81f12888e4e6513c43f3f60e72af8bd9728807483425d1e
m = 4
print("Have you several days/months to spend on this ?")

elif 1984 <= keySize <= 3936:
M_prime = 0x16928dc3e47b44daf289a60e80e1fc6bd7648d7ef60d1890f3e0a9455efe0abdb7a748131413cebd2e36a76a355c1b664be462e115ac330f9c13344f8f3d1034a02c23396e6
m = 7
print("You'll change computer before this scripts ends...")

elif 3968 <= keySize <= 4096:
print("Just no.")
return None

else:
print("Invalid key size: {}".format(keySize))
return None

a3 = Zmod(M_prime)(n).log(65537)
order = Zmod(M_prime)(65537).multiplicative_order()
inf = a3 // 2
sup = (a3 + order) // 2

# Search 10 000 values at a time, using multiprocess
# too big chunks is slower, too small chunks also
chunk_size = 10000
for inf_a in tqdm(range(inf, sup, chunk_size)):
# create an array with the parameter for the solve function
inputs = [((M_prime, n, a, m), {}) for a in range(inf_a, inf_a+chunk_size)]
# the sage builtin multiprocessing stuff
from sage.parallel.multiprocessing_sage import parallel_iter
from multiprocessing import cpu_count

for k, val in parallel_iter(cpu_count(), solve, inputs):
if val:
p = val[0]
q = val[1]
print("found factorization:\np={}\nq={}".format(p, q))
return val ​
from sage.all_cmdline import *

def coppersmith_howgrave_univariate(pol, modulus, beta, mm, tt, XX):
"""
Taken from https://github.com/mimoo/RSA-and-LLL-attacks/blob/master/coppersmith.sage
Coppersmith revisited by Howgrave-Graham

finds a solution if:
* b|modulus, b >= modulus^beta , 0 < beta <= 1
* |x| < XX
More tunable than sage's builtin coppersmith method, pol.small_roots()
"""
#
# init
#
dd = pol.degree()
nn = dd * mm + tt

#
# checks
#
if not 0 < beta <= 1:
raise ValueError("beta should belongs in [0, 1]")

if not pol.is_monic():
raise ArithmeticError("Polynomial must be monic.")

#
# calculate bounds and display them
#
"""
* we want to find g(x) such that ||g(xX)|| <= b^m / sqrt(n)

* we know LLL will give us a short vector v such that:
||v|| <= 2^((n - 1)/4) * det(L)^(1/n)

* we will use that vector as a coefficient vector for our g(x)

* so we want to satisfy:
2^((n - 1)/4) * det(L)^(1/n) < N^(beta*m) / sqrt(n)

so we can obtain ||v|| < N^(beta*m) / sqrt(n) <= b^m / sqrt(n)
(it's important to use N because we might not know b)
"""
#
# Coppersmith revisited algo for univariate
#

# change ring of pol and x
polZ = pol.change_ring(ZZ)
x = polZ.parent().gen()

# compute polynomials
gg = []
for ii in range(mm):
for jj in range(dd):
gg.append((x * XX) ** jj * modulus ** (mm - ii) * polZ(x * XX) ** ii)
for ii in range(tt):
gg.append((x * XX) ** ii * polZ(x * XX) ** mm)

# construct lattice B
BB = Matrix(ZZ, nn)

for ii in range(nn):
for jj in range(ii + 1):
BB[ii, jj] = gg[ii][jj]

BB = BB.LLL()

# transform shortest vector in polynomial
new_pol = 0
for ii in range(nn):
new_pol += x ** ii * BB[0, ii] / XX ** ii # factor polynomial
potential_roots = new_pol.roots() # test roots
roots = []
for root in potential_roots:
if root[0].is_integer():
result = polZ(ZZ(root[0]))
if gcd(modulus, result) >= modulus ** beta:
roots.append(ZZ(root[0]))
return roots

if __name__ == "__main__":
n = 787190064146025392337631797277972559696758830083248285626115725258876808514690830730702705056550628756290183000265129340257928314614351263713241
print("Starting factorization...")
#p,q = roca(n)
p=954455861490902893457047257515590051179337979243488068132318878264162627
q=824752716083066619280674937934149242011126804999047155998788143116757683
enc=365164788284364079752299551355267634718233656769290285760796137651769990253028664857272749598268110892426683253579840758552222893644373690398408
phi=(p-1)*(q-1)
e = 65537
d = gmpy2.invert(e,phi)
m = pow(enc,d,n)
print(libnum.n2s(int(m))) ​
Starting factorization...
b'hgame{ROCA_ROCK_and_ROll!}'

Sieve

#sage
from Crypto.Util.number import bytes_to_long
from sympy import nextprime FLAG = b'hgame{xxxxxxxxxxxxxxxxxxxxxx}'
m = bytes_to_long(FLAG) def trick(k):
if k > 1:
mul = prod(range(1,k))
if k - mul % k - 1 == 0:
return euler_phi(k) + trick(k-1) + 1
else:
return euler_phi(k) + trick(k-1)
else:
return 1 e = 65537
p = q = nextprime(trick(e^2//6)<<128)
n = p * q
enc = pow(m,e,n)
print(f'{enc=}')
#enc=2449294097474714136530140099784592732766444481665278038069484466665506153967851063209402336025065476172617376546

它本质上是求前n项素数和还有前n项欧拉函数和

前n项素数可以用sagemath内置函数prime_pi()函数。至于求欧拉函数我调教deepseek不出来,抄一下官方WP的。

e = 65537
limit = e**2 // 6
e = 65537
x=prime_pi(e^2//6)
#print(x)
#37030583
def sieve_of_eratosthenes(limit):
is_prime = [True] * (limit + 1)
p = 2
while p * p <= limit:
if is_prime[p]:
for i in range(p*p, limit+1, p):
is_prime[i] = False
p += 1
primes = [p for p in range(2, limit+1) if is_prime[p]]
return primes def compute_phi_and_prefix_sum(n):
primes = sieve_of_eratosthenes(n)
phi = list(range(n + 1)) # phi[0]=0, phi[1]=1,...phi[i]=i
for p in primes:
if p < 2:
continue
for multiple in range(p, n+1, p):
phi[multiple] -= phi[multiple] // p
# 计算前缀和
pre_s = [0] * (n + 1)
current_sum = 0
for i in range(n + 1):
current_sum += phi[i]
pre_s[i] = current_sum
return phi, pre_s class EulerSumSolver:
def __init__(self, m=10**6):
self.m = m
self.phi, self.pre_s = compute_phi_and_prefix_sum(m) # 调用新函数
self.cache = {} def S(self, n):
if n <= self.m:
return self.pre_s[n]
if n in self.cache:
return self.cache[n]
res = n * (n + 1) // 2
v = int(n**0.5)
sum1 = 0
for i in range(2, v + 1):
sum1 += self.S(n // i)
u = n // (v + 1)
sum2 = 0
for k in range(1, u + 1):
sum2 += self.S(k) * (n // k - n // (k + 1))
res -= (sum1 + sum2)
self.cache[n] = res
return res solver = EulerSumSolver(m=10**6)
print(solver.S(65537**2 // 6)) # 注意修正变量名拼写slover->solver
#155763335410704472

根据公式

\[\phi(n) = n \prod_{i} \left(1 - \frac{1}{p_i}\right)
\]

所以我们每次只需要\(\phi(multiple) =\phi(multiple) -\frac{\phi(multiple)}{p}\)

然后我们累加欧拉函数值,得到前缀和。

接着它的递归公式是

\[\begin{equation}
S(n) = \frac{n(n+1)}{2} - \sum_{i=2}^{v} S\left(\left\lfloor \frac{n}{i} \right\rfloor\right) - \sum_{k=1}^{u} S(k) \left(\left\lfloor \frac{n}{k}\right\rfloor - \left\lfloor \frac{n}{k+1}\right\rfloor\right)
\end{equation}
\]

HGame CTF 2025 week1 wp这个师傅的版本简单些

ezBag

task.py

from Crypto.Util.number import *
import random
from Crypto.Cipher import AES
import hashlib
from Crypto.Util.Padding import pad
from secrets import flag list = []
bag = []
p=random.getrandbits(64)
assert len(bin(p)[2:])==64
for i in range(4):
t = p
a=[getPrime(32) for _ in range(64)]
b=0
for i in a:
temp=t%2
b+=temp*i
t=t>>1
list.append(a)
bag.append(b)
print(f'list={list}')
print(f'bag={bag}') key = hashlib.sha256(str(p).encode()).digest()
cipher = AES.new(key, AES.MODE_ECB)
flag = pad(flag,16)
ciphertext = cipher.encrypt(flag)
print(f"ciphertext={ciphertext}")

背包密码问题,但是套常规脚本不彳亍。

\[\begin{pmatrix}
2 & 0 & \dots & 0 & a[0][63] & a[1][63] & a[2][63] & a[3][63] \\
0 & 2 & \dots & 0 & a[0][62] & a[1][62] & a[2][62] & a[3][62] \\
\vdots & \vdots & \ddots & \vdots & \vdots & \vdots & \vdots & \vdots \\
0 & 0 & \dots & 2 & a[0][0] & a[1][0] & a[2][0] & a[3][0] \\
1 & 1 & \dots & 1 & b[0] & b[1] & b[2] & b[3]
\end{pmatrix}
\]
import hashlib
from Crypto.Util.number import *
from Crypto.Cipher import AES
list=[[2826962231, 3385780583, 3492076631, 3387360133, 2955228863, 2289302839, 2243420737, 4129435549, 4249730059, 3553886213, 3506411549, 3658342997, 3701237861, 4279828309, 2791229339, 4234587439, 3870221273, 2989000187, 2638446521, 3589355327, 3480013811, 3581260537, 2347978027, 3160283047, 2416622491, 2349924443, 3505689469, 2641360481, 3832581799, 2977968451, 4014818999, 3989322037, 4129732829, 2339590901, 2342044303, 3001936603, 2280479471, 3957883273, 3883572877, 3337404269, 2665725899, 3705443933, 2588458577, 4003429009, 2251498177, 2781146657, 2654566039, 2426941147, 2266273523, 3210546259, 4225393481, 2304357101, 2707182253, 2552285221, 2337482071, 3096745679, 2391352387, 2437693507, 3004289807, 3857153537, 3278380013, 3953239151, 3486836107, 4053147071], [2241199309, 3658417261, 3032816659, 3069112363, 4279647403, 3244237531, 2683855087, 2980525657, 3519354793, 3290544091, 2939387147, 3669562427, 2985644621, 2961261073, 2403815549, 3737348917, 2672190887, 2363609431, 3342906361, 3298900981, 3874372373, 4287595129, 2154181787, 3475235893, 2223142793, 2871366073, 3443274743, 3162062369, 2260958543, 3814269959, 2429223151, 3363270901, 2623150861, 2424081661, 2533866931, 4087230569, 2937330469, 3846105271, 3805499729, 4188683131, 2804029297, 2707569353, 4099160981, 3491097719, 3917272979, 2888646377, 3277908071, 2892072971, 2817846821, 2453222423, 3023690689, 3533440091, 3737441353, 3941979749, 2903000761, 3845768239, 2986446259, 3630291517, 3494430073, 2199813137, 2199875113, 3794307871, 2249222681, 2797072793], [4263404657, 3176466407, 3364259291, 4201329877, 3092993861, 2771210963, 3662055773, 3124386037, 2719229677, 3049601453, 2441740487, 3404893109, 3327463897, 3742132553, 2833749769, 2661740833, 3676735241, 2612560213, 3863890813, 3792138377, 3317100499, 2967600989, 2256580343, 2471417173, 2855972923, 2335151887, 3942865523, 2521523309, 3183574087, 2956241693, 2969535607, 2867142053, 2792698229, 3058509043, 3359416111, 3375802039, 2859136043, 3453019013, 3817650721, 2357302273, 3522135839, 2997389687, 3344465713, 2223415097, 2327459153, 3383532121, 3960285331, 3287780827, 4227379109, 3679756219, 2501304959, 4184540251, 3918238627, 3253307467, 3543627671, 3975361669, 3910013423, 3283337633, 2796578957, 2724872291, 2876476727, 4095420767, 3011805113, 2620098961], [2844773681, 3852689429, 4187117513, 3608448149, 2782221329, 4100198897, 3705084667, 2753126641, 3477472717, 3202664393, 3422548799, 3078632299, 3685474021, 3707208223, 2626532549, 3444664807, 4207188437, 3422586733, 2573008943, 2992551343, 3465105079, 4260210347, 3108329821, 3488033819, 4092543859, 4184505881, 3742701763, 3957436129, 4275123371, 3307261673, 2871806527, 3307283633, 2813167853, 2319911773, 3454612333, 4199830417, 3309047869, 2506520867, 3260706133, 2969837513, 4056392609, 3819612583, 3520501211, 2949984967, 4234928149, 2690359687, 3052841873, 4196264491, 3493099081, 3774594497, 4283835373, 2753384371, 2215041107, 4054564757, 4074850229, 2936529709, 2399732833, 3078232933, 2922467927, 3832061581, 3871240591, 3526620683, 2304071411, 3679560821]]
bag=[123342809734, 118191282440, 119799979406, 128273451872]
ciphertext=b'\x1d6\xcc}\x07\xfa7G\xbd\x01\xf0P4^Q"\x85\x9f\xac\x98\x8f#\xb2\x12\xf4+\x05`\x80\x1a\xfa !\x9b\xa5\xc7g\xa8b\x89\x93\x1e\xedz\xd2M;\xa2'
L=matrix(ZZ,65,68)
for i in range(64):
L[i,i]=2
L[i,-1]=list[3][-i-1]
L[i,-2]=list[2][-i-1]
L[i,-3]=list[1][-i-1]
L[i,-4]=list[0][-i-1]
L[-1,:]=1
L[-1,-1]=bag[3]
L[-1,-2]=bag[2]
L[-1,-3]=bag[1]
L[-1,-4]=bag[0]
x=L.BKZ()
print(x[0])
p=''
for i in x[0][:64]:
if i==x[0][0]:
p+='1'
else:
p+='0'
p=int(p,2)
key = hashlib.sha256(str(p).encode()).digest()
cipher = AES.new(key, AES.MODE_ECB)
flag = cipher.decrypt(ciphertext)
print(flag)

这个格为什么这样构造的,有没有师傅懂原理。不过从表面上看,list和bag都是二维数组,应该可以猜测是这样构造的吧。

Intergalactic Bound

task.py

from Crypto.Util.number import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from random import randint
import hashlib
from secrets import flag def add_THCurve(P, Q):
if P == (0, 0):
return Q
if Q == (0, 0):
return P
x1, y1 = P
x2, y2 = Q
x3 = (x1 - y1 ** 2 * x2 * y2) * pow(a * x1 * y1 * x2 ** 2 - y2, -1, p) % p
y3 = (y1 * y2 ** 2 - a * x1 ** 2 * x2) * pow(a * x1 * y1 * x2 ** 2 - y2, -1, p) % p
return x3, y3 def mul_THCurve(n, P):
R = (0, 0)
while n > 0:
if n % 2 == 1:
R = add_THCurve(R, P)
P = add_THCurve(P, P)
n = n // 2
return R p = getPrime(96)
a = randint(1, p)
G = (randint(1,p), randint(1,p))
d = (a*G[0]^3+G[1]^3+1)%p*inverse(G[0]*G[1],p)%p
x = randint(1, p)
Q = mul_THCurve(x, G)
print(f"p = {p}")
print(f"G = {G}")
print(f"Q = {Q}") key = hashlib.sha256(str(x).encode()).digest()
cipher = AES.new(key, AES.MODE_ECB)
flag = pad(flag,16)
ciphertext = cipher.encrypt(flag)
print(f"ciphertext={ciphertext}") """
p = 55099055368053948610276786301
G = (19663446762962927633037926740, 35074412430915656071777015320)
Q = (26805137673536635825884330180, 26376833112609309475951186883)
ciphertext=b"k\xe8\xbe\x94\x9e\xfc\xe2\x9e\x97\xe5\xf3\x04'\x8f\xb2\x01T\x06\x88\x04\xeb3Jl\xdd Pk$\x00:\xf5"
"""

一眼非常眼熟,因为刚好在研究curve相关问题。这其实是羊城杯2024的两道curve题目结合改编而来。

附上链接:https://blog.csdn.net/XiongSiqi_blog/article/details/141638136

我采用上面博客的方法,没有使用扭曲曲线惯用方法——映射到Weierstrass

本题就是先用两个点算出a和d。然后后面使用Pohlig_Hellman方法的时候,套用的博客脚本要修改一下,就是它这个prime最后一位有没有去掉的问题,羊城杯那题中,它是去掉的:

    primes = [factors[i] ^ exponents[i] for i in range(len(factors))][:-1]

但是这题不用去掉,具体原因我还要探究一下。我是偶然间把它去了发现才可以解

exp

from Crypto.Util.number import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import hashlib
ciphertext=b"k\xe8\xbe\x94\x9e\xfc\xe2\x9e\x97\xe5\xf3\x04'\x8f\xb2\x01T\x06\x88\x04\xeb3Jl\xdd Pk$\x00:\xf5"
a=39081810733380615260725035189
p = 55099055368053948610276786301
P = (19663446762962927633037926740, 35074412430915656071777015320)
Q = (26805137673536635825884330180, 26376833112609309475951186883)
d = (a * P[0] ** 3 + P[1] ** 3 + 1) * inverse(P[0] * P[1], p) % p # construct ECC to get a solution of 2X^3+Y^3+Z^3=dXYZ
R.<x,y,z> = Zmod(p)[]
cubic = a* x^3 + y^3 + z^3 - d*x*y*z
E = EllipticCurve_from_cubic(cubic,morphism=True)
P = E(P)
Q = E(Q)
P_ord = P.order() def Pohlig_Hellman(n,P,Q):
factors, exponents = zip(*factor(n))
primes = [factors[i] ^ exponents[i] for i in range(len(factors))]
print(primes)
dlogs = []
for fac in primes:
t = int(int(P.order()) // int(fac))
dlog = discrete_log(t*Q,t*P,operation="+")
dlogs += [dlog]
print("factor: "+str(fac)+", Discrete Log: "+str(dlog)) #calculates discrete logarithm for each prime order
num2 = crt(dlogs,primes)
return num2 num2 = Pohlig_Hellman(P_ord,P,Q)
print(num2)
key = hashlib.sha256(str(num2).encode()).digest()
cipher = AES.new(key, AES.MODE_ECB)
flag = unpad(cipher.decrypt(ciphertext), 16).decode()
print(f"Flag: {flag}")
#Flag: hgame{N0th1ng_bu7_up_Up_UP!}

Ancient Recall

task.py

import random

Major_Arcana = ["The Fool", "The Magician", "The High Priestess","The Empress", "The Emperor", "The Hierophant","The Lovers", "The Chariot", "Strength","The Hermit", "Wheel of Fortune", "Justice","The Hanged Man", "Death", "Temperance","The Devil", "The Tower", "The Star","The Moon", "The Sun", "Judgement","The World"]
wands = ["Ace of Wands", "Two of Wands", "Three of Wands", "Four of Wands", "Five of Wands", "Six of Wands", "Seven of Wands", "Eight of Wands", "Nine of Wands", "Ten of Wands", "Page of Wands", "Knight of Wands", "Queen of Wands", "King of Wands"]
cups = ["Ace of Cups", "Two of Cups", "Three of Cups", "Four of Cups", "Five of Cups", "Six of Cups", "Seven of Cups", "Eight of Cups", "Nine of Cups", "Ten of Cups", "Page of Cups", "Knight of Cups", "Queen of Cups", "King of Cups"]
swords = ["Ace of Swords", "Two of Swords", "Three of Swords", "Four of Swords", "Five of Swords", "Six of Swords", "Seven of Swords", "Eight of Swords", "Nine of Swords", "Ten of Swords", "Page of Swords", "Knight of Swords", "Queen of Swords", "King of Swords"]
pentacles = ["Ace of Pentacles", "Two of Pentacles", "Three of Pentacles", "Four of Pentacles", "Five of Pentacles", "Six of Pentacles", "Seven of Pentacles", "Eight of Pentacles", "Nine of Pentacles", "Ten of Pentacles", "Page of Pentacles", "Knight of Pentacles", "Queen of Pentacles", "King of Pentacles"]
Minor_Arcana = wands + cups + swords + pentacles
tarot = Major_Arcana + Minor_Arcana
reversals = [0,-1] Value = []
cards = []
YOUR_initial_FATE = []
while len(YOUR_initial_FATE)<5:
card = random.choice(tarot)
if card not in cards:
cards.append(card)
if card in Major_Arcana:
k = random.choice(reversals)
Value.append(tarot.index(card)^k)
if k == -1:
YOUR_initial_FATE.append("re-"+card)
else:
YOUR_initial_FATE.append(card)
else:
Value.append(tarot.index(card))
YOUR_initial_FATE.append(card)
else:
continue
print("Oops!lets reverse 1T!") FLAG=("hgame{"+"&".join(YOUR_initial_FATE)+"}").replace(" ","_") YOUR_final_Value = Value
def Fortune_wheel(FATE):
FATEd = [FATE[i]+FATE[(i+1)%5] for i in range(len(FATE))]
return FATEd for i in range(250):
YOUR_final_Value = Fortune_wheel(YOUR_final_Value)
print(YOUR_final_Value)
YOUR_final_FATE = []
for i in YOUR_final_Value:
YOUR_final_FATE.append(tarot[i%78])
print("Your destiny changed!\n",",".join(YOUR_final_FATE))
print("oh,now you GET th3 GOOd lU>k,^^")
"""
Oops!lets reverse 1T!
[2532951952066291774890498369114195917240794704918210520571067085311474675019, 2532951952066291774890327666074100357898023013105443178881294700381509795270, 2532951952066291774890554459287276604903130315859258544173068376967072335730, 2532951952066291774890865328241532885391510162611534514014409174284299139015, 2532951952066291774890830662608134156017946376309989934175833913921142609334]
Your destiny changed!
Eight of Cups,Ace of Cups,Strength,The Chariot,Five of Swords
oh,now you GET th3 GOOd lU>k,^^
"""

直接使用deepseek R1秒杀?

exp

Major_Arcana = ["The Fool", "The Magician", "The High Priestess","The Empress", "The Emperor", "The Hierophant","The Lovers", "The Chariot", "Strength","The Hermit", "Wheel of Fortune", "Justice","The Hanged Man", "Death", "Temperance","The Devil", "The Tower", "The Star","The Moon", "The Sun", "Judgement","The World"]
wands = ["Ace of Wands", "Two of Wands", "Three of Wands", "Four of Wands", "Five of Wands", "Six of Wands", "Seven of Wands", "Eight of Wands", "Nine of Wands", "Ten of Wands", "Page of Wands", "Knight of Wands", "Queen of Wands", "King of Wands"]
cups = ["Ace of Cups", "Two of Cups", "Three of Cups", "Four of Cups", "Five of Cups", "Six of Cups", "Seven of Cups", "Eight of Cups", "Nine of Cups", "Ten of Cups", "Page of Cups", "Knight of Cups", "Queen of Cups", "King of Cups"]
swords = ["Ace of Swords", "Two of Swords", "Three of Swords", "Four of Swords", "Five of Swords", "Six of Swords", "Seven of Swords", "Eight of Swords", "Nine of Swords", "Ten of Swords", "Page of Swords", "Knight of Swords", "Queen of Swords", "King of Swords"]
pentacles = ["Ace of Pentacles", "Two of Pentacles", "Three of Pentacles", "Four of Pentacles", "Five of Pentacles", "Six of Pentacles", "Seven of Pentacles", "Eight of Pentacles", "Nine of Pentacles", "Ten of Pentacles", "Page of Pentacles", "Knight of Pentacles", "Queen of Pentacles", "King of Pentacles"]
Minor_Arcana = wands + cups + swords + pentacles
tarot = Major_Arcana + Minor_Arcana final_values = [
2532951952066291774890498369114195917240794704918210520571067085311474675019,
2532951952066291774890327666074100357898023013105443178881294700381509795270,
2532951952066291774890554459287276604903130315859258544173068376967072335730,
2532951952066291774890865328241532885391510162611534514014409174284299139015,
2532951952066291774890830662608134156017946376309989934175833913921142609334
] def reverse_fortune_wheel(current):
v0 = (current[0] + current[4] - current[1] - current[3] + current[2]) // 2
v1 = current[0] - v0
v2 = current[1] - v1
v3 = current[2] - v2
v4 = current[3] - v3
assert v4 + v0 == current[4], "Reverse step failed"
return [v0, v1, v2, v3, v4] current = final_values.copy()
for _ in range(250):
current = reverse_fortune_wheel(current)
initial_values = current def get_card_name(value):
k_reversed = value ^ -1
if 0 <= k_reversed < len(Major_Arcana):
return f"re-{Major_Arcana[k_reversed]}"
if 0 <= value < len(Major_Arcana):
return Major_Arcana[value]
index = value % len(tarot)
return tarot[index] cards = []
for v in initial_values:
card = get_card_name(v)
card = card.replace(" ", "_")
cards.append(card) flag = "hgame{" + "&".join(cards) + "}"
print(flag)
#hgame{re-The_Moon&re-The_Sun&Judgement&re-Temperance&Six_of_Cups}

SPiCa

task.py

from Crypto.Util.number import getPrime, long_to_bytes,bytes_to_long
from secrets import flag
from sage.all import * def derive_M(n):
iota=0.035
Mbits=int(2 * iota * n^2 + n * log(n,2))
M = random_prime(2^Mbits, proof = False, lbound = 2^(Mbits - 1))
return Integer(M) m = bytes_to_long(flag).bit_length()
n = 70
p = derive_M(n) F = GF(p)
x = random_matrix(F, 1, n)
A = random_matrix(ZZ, n, m, x=0, y=2)
A[randint(0, n-1)] = vector(ZZ, list(bin(bytes_to_long(flag))[2:]))
h = x*A with open("data.txt", "w") as file:
file.write(str(m) + "\n")
file.write(str(p) + "\n")
for item in h:
file.write(str(item) + "\n")

HSSP问题,这题其实考过,y011d4.log

一模一样的,这题就是x是\(1*n\)的随机矩阵,A是\(n*m\)的随机矩阵,h=x*A

ctf-writeups/2022/zer0ptsctf/karen/solutions/solver.sage at main · roadicing/ctf-writeups · GitHub解密脚本在这

原理:HSSP与正交格学习笔记 - 0xFFFF

用\(h\)构造格基,LLL找到m−n个短向量ui

用ui构造格\(L_x^{⊥}\),用\(Lx^{⊥}\)找\(L_x^{⊥}\)的正交补\(L_x^{⊥}\)ˉ(可以看作是和\(L_x\)同一个空间,但基不是xi\pmb{x}_ixxi)

对\(L_x^{⊥}\)ˉ使用LLL恢复\(x_{i}\)

exp

#sage
from Crypto.Util.number import long_to_bytes n = 70
m = 247
p = 24727704801291912268835129736340977567569865784366882566681759917843647658060231409536848349518003784121914409876944135933654762801696486121844572452922377222301017649192408619831637530961997845860817966791811403512683444831050730277
h = (...) # https://eprint.iacr.org/2020/461.pdf
# https://pastebin.com/raw/ZFk1qjfP def orthoLattice(b,x0):
m = b.length()
M = Matrix(ZZ, m, m)
for i in range(1, m):
M[i, i] = 1
M[1:m, 0] = -b[1: m] * inverse_mod(b[0], x0)
M[0,0] = x0
for i in range(1, m):
M[i, 0] = mod(M[i, 0], x0)
return M def allones(v):
if len([vj for vj in v if vj in [0, 1]]) == len(v):
return v
if len([vj for vj in v if vj in [0, -1]]) == len(v):
return -v
return None def recoverBinary(M5):
lv = [allones(vi) for vi in M5 if allones(vi)]
n = M5.nrows()
for v in lv:
for i in range(n):
nv = allones(M5[i] - v)
if nv and nv not in lv:
lv.append(nv)
nv = allones(M5[i] + v)
if nv and nv not in lv:
lv.append(nv)
return Matrix(lv) def allpmones(v):
return len([vj for vj in v if vj in [-1, 0, 1]]) == len(v) def kernelLLL(M):
n = M.nrows()
m = M.ncols()
if m < 2 * n:
return M.right_kernel().matrix()
K = 2^(m // 2) * M.height()
MB = Matrix(ZZ, m + n, m)
MB[:n] = K * M
MB[n:] = identity_matrix(m)
MB2 = MB.T.LLL().T
assert MB2[:n, :m - n] == 0
Ke = MB2[n:, :m - n].T
return Ke def NSattack(n, m, p, h):
iota = 0.035
nx0 = int(2 * iota * n^2 + n * log(n, 2))
x0 = p
b = vector(h)
M = orthoLattice(b, x0)
M2 = M.LLL()
MOrtho = M2[:m - n]
ke = kernelLLL(MOrtho)
if n > 170:
return
beta = 2
while beta < n:
if beta == 2:
M5 = ke.LLL()
else:
M5 = M5.BKZ(block_size = beta)
if len([True for v in M5 if allpmones(v)]) == n:
break
if beta == 2:
beta = 10
else:
beta += 10
MB = recoverBinary(M5)
return MB
MB = NSattack(n, m, p, h)
for r in MB:
res = long_to_bytes(int(''.join(map(str, r.list())), 2))
if res.startswith(b"hgame{"):
FLAG = res
print(FLAG)

hgame2025-Crypto小记的更多相关文章

  1. linux 下cmake 编译 ,调用,调试 poco 1.6.0 小记

    上篇文章 小记了: 关于 Poco::TCPServer框架 (windows 下使用的是 select模型) 学习笔记. http://www.cnblogs.com/bleachli/p/4352 ...

  2. JavaScript小记

    JavaScript小记 1. 简介 1. 语言描述 JavaScript 是一门跨平台.面向对象的弱类型动态脚本编程语言 JavaScript 是一门基于原型.函数先行的语言 JavaScript ...

  3. [原]Paste.deploy 与 WSGI, keystone 小记

    Paste.deploy 与 WSGI, keystone 小记 名词解释: Paste.deploy 是一个WSGI工具包,用于更方便的管理WSGI应用, 可以通过配置文件,将WSGI应用加载起来. ...

  4. MySql 小记

    MySql  简单 小记 以备查看 1.sql概述 1.什么是sql? 2.sql发展过程? 3.sql标准与方言的关系? 4.常用数据库? 5.MySql数据库安装? 2.关键概念 表结构----- ...

  5. Git小记

    Git简~介 Git是一个分布式版本控制系统,其他的版本控制系统我只用过SVN,但用的时间不长.大家都知道,分布式的好处多多,而且分布式已经包含了集中式的几乎所有功能.Linus创造Git的传奇经历就 ...

  6. 广州PostgreSQL用户会技术交流会小记 2015-9-19

    广州PostgreSQL用户会技术交流会小记 2015-9-19 今天去了广州PostgreSQL用户会组织的技术交流会 分别有两个session 第一个讲师介绍了他公司使用PostgreSQL-X2 ...

  7. 东哥读书小记 之 《MacTalk人生元编程》

         一直以来的自我感觉:自己是个记性偏弱的人.反正从小读书就喜欢做笔记(可自己的字写得巨丑无比,尼玛不科学呀),抄书这事儿真的就常发生俺的身上. 因为那时经常要背诵课文之类,反正为了怕自己忘记, ...

  8. Paypal支付小记

    Paypal支付小记 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !impo ...

  9. javax.crypto.BadPaddingException: Given final block not properly padded 解决方法

    下面的 Des 加密解密代码,在加密时正常,但是在解密是抛出错误: javax.crypto.BadPaddingException: Given final block not properly p ...

  10. 使用crypto模块实现md5加密功能(解决中文加密前后端不一致的问题)

    正常情况下使用md5加密 var crypto = require('crypto'); var md5Sign = function (data) { var md5 = crypto.create ...

随机推荐

  1. 解决编译redis报错zmalloc.h:50:10: fatal error: jemalloc/jemalloc.h: No such file or directory

    编译redis时报错:zmalloc.h:50:10: fatal error: jemalloc/jemalloc.h: No such file or directory,执行: # sudo m ...

  2. 安装Spring源码时报错No such property: values for class: org.gradle.api.internal.tasks.DefaultTas

    IDEA进行项目拉取时:No such property: values for class: org.gradle.api.internal.tasks.DefaultTas 修改spring-be ...

  3. Qt开源作品8-通用控件移动

    一.前言 在做一些项目的过程中,有一种应用场景是需要拖动设备在一个容器中,自由拖动摆放到合适的位置,然后保存对应设备的坐标位置信息,在软件启动好以后自动加载配置好的坐标位置信息,将每个设备移动到对应的 ...

  4. 【量化读书笔记】【打开量化投资的黑箱】CH.04.风险模型

    风险管理不仅仅是规避风险和减少损失,是通过对敞口实施有目的的选择和规模控制来提高收益的质量和稳定性. (注:敞口,一般指金融活动中存在金融风险的部位以及受金融风险影响的程度) 本质上风险模型是为阿尔法 ...

  5. linux进入横线 "-" 开头的文件夹

    在linux进行文件操作时,会遇到一类文件是以"-"开头的. 例如我们想要进入名称为-126943579的文件时,我们无法直接使用cd -126943579命令来进入该文件. 那我 ...

  6. 安装Rational rose软件简单教程

    安装Rational rose软件简单教程 一.下载文件 百度云盘下载链接:https://pan.baidu.com/s/1QWmTgxKlQtE5flP7dXIF5w 提取码:wjnq 二.装虚拟 ...

  7. linux内核 list_for_each_entry

    1. linux内核中的list用法 在linus内核中,list一般这样使用: struct list_head { struct list_head *priv; struct list_head ...

  8. tar基本命令

    常用基本命令 压缩文件 # touch a.txt # tar -czvf test.tar.gz a.txt  //或  tar -czvf /path/to/file.tar.gz file 列出 ...

  9. NTRU

    介绍 NTRU(Number Theory Research Unit),NTRU是一个带有专利保护的开源公开密钥加密系统,使用基于格的加密算法来加密数据.它包括两部分算法:NTRUEncrypt用来 ...

  10. MongoDB:【索引的管理操作】