import os
# secp521r1 patemeter
p = 0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
K = GF(p)
a = K(0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc)
b = K(0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00)
EC = EllipticCurve(K, (a, b))
whileTrue:
Q = EC.random_point()
q = int(Q.xy()[0])
R = 2*Q
r = int(R.xy()[0])
if is_prime(q) and is_prime(r):
break
n = q*r
e = 65537
m = int.from_bytes(os.environ.get("FLAG", "Alpaca{dummy}").encode(), "big")
assert m < n
c = pow(m, e, n)
print("n = {}".format(n))
print("e = {}".format(e))
print("c = {}".format(c))
import os
from Crypto.Util.number import getPrime
FLAG = os.getenv("FLAG", "ctf4b{dummy_flag}").encode()
m = int.from_bytes(FLAG, 'big')
p = getPrime(512)
q = getPrime(16)
n = p * q
e = 65537
c = pow(m, e, n)
print(f"{n = }")
print(f"{c = }")
from ptrlib import Socket, chunks
# sock = Socket("nc localhost 9999")
sock = Socket("nc 01-translator.challenges.beginners.seccon.jp 9999")
sock.sendlineafter("0> ", "0" * 16)
sock.sendlineafter("1> ", "1" * 16)
ct = sock.recvlineafter("ct:").decode().strip()
cs = chunks(ct, 32)
flag = 0for c in cs[:-1]: # last block is paddingif c == cs[0]:
flag = flag*2 + 1else:
flag = flag*2print(bin(flag))
print(bytes.fromhex(hex(flag)[2:]))
elliptic4b
import os
import secrets
from fastecdsa.curve import secp256k1
from fastecdsa.point import Point
flag = os.environ.get("FLAG", "CTF{dummy_flag}")
y = secrets.randbelow(secp256k1.p)
print(f"{y = }")
x = int(input("x = "))
ifnot secp256k1.is_point_on_curve((x, y)):
print("// Not on curve!")
exit(1)
a = int(input("a = "))
P = Point(x, y, secp256k1)
Q = a * P
if a < 0:
print("// a must be non-negative!")
exit(1)
if P.x != Q.x:
print("// x-coordinates do not match!")
exit(1)
if P.y == Q.y:
print("// P and Q are the same point!")
exit(1)
print("flag =", flag)
from ptrlib import Socket
p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
K = GF(p)
a = K(0x0000000000000000000000000000000000000000000000000000000000000000)
b = K(0x0000000000000000000000000000000000000000000000000000000000000007)
E = EllipticCurve(K, (a, b))
G = E(0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798, 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8)
E.set_order(0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 * 0x1)
PR.<x> = PolynomialRing(K)
whileTrue:
# sock = Socket("nc localhost 9999")
sock = Socket("nc elliptic4b.challenges.beginners.seccon.jp 9999")
y = int(sock.recvlineafter("y = "))
f = y**2 - (x**3 + a*x + b)
roots = f.roots()
iflen(roots) != 0:
break
x = roots[0][0]
G1 = E((x, y))
inv = Zmod(E.order())(-1)
G2 = inv *G1
assert G1[0] == G2[0]
sock.sendlineafter("x = ", str(x))
sock.sendlineafter("a = ", str(inv))
sock.interactive()
Golden Ticket
問題のスクリプトはやや長いので省略。encryption ticketを利用するとEnc(key, iv, input || pad) がえられるオラクルが利用でき、decryption ticketを利用するとDec(key, iv, input || pad)が得られるオラクルが利用できます。Enc, Dec AES-CBCによる暗号化・復号で、どちらもinput は16バイト(1ブロック)までで、それぞれ3回まで利用できます。
f = open("output.txt")
n = int(f.readline().strip().split(" = ")[1])
e = int(f.readline().strip().split(" = ")[1])
c = int(f.readline().strip().split(" = ")[1])
r = int(f.readline().strip().split(" = ")[1])
r2 = next_prime(r)
a = r2 - r
# calculate q mod r
q3r = n % r * Zmod(r)(a).inverse() # q^3 mod r
ns = ecm.factor(r)
all_roots = []
for p in ns:
roots = GF(p)(q3r).nth_root(3, all=True)
all_roots.append([int(root) for root in roots])
import itertools
root_combinations = list(itertools.product(*all_roots))
q_r_list = [crt(list(c), ns) for c in root_combinations]
# calculate q_max - q under mod r# q_max - q mod r = q_max - q - k*r with small k# because q_max - q is approximately 250bit, r is 224 bit
q_max = floor((Integer(n) / r)**(1/3))
for q_r in q_r_list:
q_delta_r = (q_max - q_r) % r
print(q_max)
print(q_delta_r)
# find k and solve q_max - q = q_delta_r + k*r for qfor k inrange(2048):
q = q_max - (int(q_delta_r) + k*r)
if n % q == 0:
print(f"[+] {q=}")
breakelse:
continue
p = n // q
d = pow(e, -1, (p-1)*(q-1))
m = pow(c, d, n)
print(bytes.fromhex(hex(m)[2:]))