Sekai CTF 2022¶
Mình làm 1 bài rồi đứng hình. :)))
FalLProoF¶
Đề bài có thể tải ở file chall.py
.
Ở bài này hệ mật mã tạo một public key từ một secret và một hàm hash.
Tạo public key¶
Để tạo public key cần truyền vào một chuỗi byte secret và hàm hash. Chúng ta đã biết hàm hash luôn cho output có độ dài cố định không liên quan độ dài input.
Mình gọi hàm hash là \(H(x)\) cho input \(x\) và độ dài (cố định) của hàm hash là \(L\). Mình kí hiệu việc thực hiện hash \(k\) lần là \(H^{(k)}(x)\). Tức là \(H^{(k)}(x) = H(H(\cdots (H(x))\cdots))\) (\(k\) lần). Như vậy public key tương ứng với secret \(s\) đầu vào là \([H^{(1)}(s), H^{(2)}(s), \ldots, H^{(4*L)}(s)]\).
Prototype của hàm tạo public key dùng SHA512 nhưng ở chương trình chính dùng SHA256. Do đó \(L = 32\) bytes và độ dài public key là \(64\).
Encode message¶
Bước vào hàm encrypt, message ban đầu sẽ được pad thành bội của \(32\) (theo độ dài public key / 4 - độ dài hàm hash
) và được chia thành từng chunk \(32\) bytes.
Happiness¶
Hàm happiness
có một tính chất thú vị.
Giả sử mình có đầu vào là \(x=x_n 2^n + x_{n-1} 2^{n-1} + \ldots + x_1 2 + x_0\).
Khi đó:
suy ra
Tóm lại hàm happiness
tính tổng các bit của \(x\). :))))
Encrypt¶
Giả sử mình gọi chunk đầu là \(m\). Do \(m\) có \(32\) bytes, tương ứng \(256\) bit, nên mình viết dưới dạng nhị phân là
\(m_i \in \{0, 1\}\).
Mình tiếp tục kí hiệu public key thứ \(j\) là \(p_j\), \(j = \overline{0, 127}\). Và mình cũng viết dưới dạng nhị phân
Do đó phép AND cho kết quả
Qua hàm happiness chính là tổng
Do đó với 128 public key mình có thể viết dưới dạng ma trận như sau
Vấn đề ở đây là ma trận \(P\) không phải ma trận vuông. Do đó mình không thể tính nghịch đảo được :((
Để ý rằng \(m\) luôn không đổi mỗi lần netcat nên mình chỉ cần request thêm một lần nữa và có thêm \(64\) public key nữa. Khi đó ghép các public key đó nối tiếp xuống dưới ma trận \(P\) cũng như ghép thêm các ciphertext mới xuống dưới cột \(c\) thì mình đã đủ ma trận vuông để giải.
Code giải các bạn xem ở solve.py
.
Cám ơn các bạn đã đọc writeup siêu dài cho một bài ... không dài lắm.