🔥
ångstromCTF 2021 - Circle of Trust
問題概要
Clam created a 1337 secret sharing scheme for his 1337 trio of friends. Can you crack it?
gen.py
import random
import secrets
import math
from decimal import Decimal, getcontext
from Crypto.Cipher import AES
BOUND = 2 ** 128
MULT = 10 ** 10
getcontext().prec = 50
def nums(a):
b = Decimal(random.randint(-a * MULT, a * MULT)) / MULT
c = (a ** 2 - b ** 2).sqrt()
if random.randrange(2):
c *= -1
return (b, c)
with open("flag", "r") as f:
flag = f.read().strip().encode("utf8")
diff = len(flag) % 16
if diff:
flag += b"\x00" * (16 - diff)
keynum = secrets.randbits(128)
ivnum = secrets.randbits(128)
key = int.to_bytes(keynum, 16, "big")
iv = int.to_bytes(ivnum, 16, "big")
x = Decimal(random.randint(1, BOUND * MULT)) / MULT
for _ in range(3):
(a, b) = nums(x)
print(f"({keynum + a}, {ivnum + b})")
cipher = AES.new(key, AES.MODE_CBC, iv=iv)
enc = cipher.encrypt(flag)
print(enc.hex())
三平方を使った面白めの問題です。
解説
ランダムに生成されたx
という変数から、a
,b
がa
,b
にそれぞれkey
,iv
がノイズとして追加され、そもそも知りたい情報はkey
,iv
の方です。
ここから思いっきり数式を弄るパートです。
- 与えられたペアの数値(
a+key
,b+iv
)を とします。x, y 、x = a + key で、y = b + iv は既知です。x, y -
は3ペア与えられるので、x,y という表記で区別します。同様にx_i, y_i も使用します。a_i, b_i -
についてa, b が成立します。a_1^2 + b_1^2 = a_2^2 + b_2^2 = a_3^2 + b_3^2 - 3に
を代入すると、以下のような式になります。a=x-key, b=y-iv
- このように変数
key
,iv
を用いた1次方程式になりました。ところで を用いてもう1つ式を作ることが出来ます。これらを連立させて解くことで、(x_2, y_2), (x_3, y_3) key
とiv
の値を求めることが出来ます。
key
、iv
を求めることでAESの復号が出来ます。
solve.py
from decimal import *
from Crypto.Util.number import *
from Crypto.Cipher import AES
getcontext().prec = 128
MULT = 10 ** 10
bc = [
(Decimal("45702021340126875800050711292004769456.2582161398"), Decimal("310206344424042763368205389299416142157.00357571144")),
(Decimal("55221733168602409780894163074078708423.359152279"), Decimal("347884965613808962474866448418347671739.70270575362")),
(Decimal("14782966793385517905459300160069667177.5906950984"), Decimal("340240003941651543345074540559426291101.69490484699")),
]
c = bytes.fromhex("838371cd89ad72662eea41f79cb481c9bb5d6fa33a6808ce954441a2990261decadf3c62221d4df514841e18c0b47a76")
equations = [
(2 * (bc[0][0] - bc[1][0]), 2 * (bc[0][1] - bc[1][1]), (bc[0][0] ** 2 - bc[1][0] ** 2) + (bc[0][1] ** 2 - bc[1][1] ** 2)),
(2 * (bc[1][0] - bc[2][0]), 2 * (bc[1][1] - bc[2][1]), (bc[1][0] ** 2 - bc[2][0] ** 2) + (bc[1][1] ** 2 - bc[2][1] ** 2))
]
xn = (equations[0][2] * equations[1][1] - equations[0][1] * equations[1][2])
xd = (equations[0][0] * equations[1][1] - equations[0][1] * equations[1][0])
yn = (equations[0][2] * equations[1][0] - equations[0][0] * equations[1][2])
yd = (equations[0][1] * equations[1][0] - equations[0][0] * equations[1][1])
print("xn:", xn)
print("xd:", xd)
print("mod:", xn % xd)
print("yn:", yn)
print("yd:", yd)
print("mod:", yn % yd)
x = int(xn / xd) + 1
y = int(yn / yd)
key = int.to_bytes(x, 16, "big")
iv = int.to_bytes(y, 16, "big")
cipher = AES.new(key, AES.MODE_CBC, iv=iv)
dec = cipher.decrypt(c)
print(dec)
Discussion