- Category: Crypto
- Score: 500/500
- Solves: 2/286
題目給了個 RSA 的加密 oracle (
from random import getrandbits
N_BITS = 1024
PAD_SIZE = 64
def generate_padding():
pad = getrandbits(PAD_SIZE)
s = 0
for _ in range(N_BITS // PAD_SIZE):
s = (s << PAD_SIZE) | pad
return s
這題的第一個問題在於這行: from random import getrandbits
。因為 python 的 random
使用的是 MT19937,是一個可以在擁有夠多的輸出後就能被預測的 PRNG。
Google 一下可以找到像是 randcrack 之類的東西,可以知道它一共需要 624 的輸出才能預測 random,每個輸出為 32 bits。
首先第一關在於怎麼取得 padding。應該不難發現 generate padding 的時候是拿同樣的 64 bits 結合 bit shifting 弄出來的 1024 bits 數字。在 16 進位下也能發現它是一個重複的 pattern 反覆出現,所以當原本的 64 bits padding 為
所以輸入
因為
再來是因為
random.seed(8763); hex(random.getrandbits(64))
random.seed(8763); hex(random.getrandbits(32)), hex(random.getrandbits(32))
可以知道它是類似 Little Endian 的方式來輸出的,所以是先底部的 32 bits 之後才是頂部的 32 bits。
PS: 其實
$m \neq 0$ 的時候也能透過 Coppersmith attack 還原$x$
等蒐集到了 624 個 32 bits 的輸出之後可以預測未來的輸出,這邊可以直接用 randcrack 之類的解決,不用自己實作。
我個人是喜歡使用 eboda/mersenne-twister-recover,因為它可以 return 一個 Python 內建的 random 物件,api 用起來比較方便。
能夠預測 padding 之後又能做什麼呢? 如果取得兩個 flag 的 ciphertext
其中的
Related Message Attack 大致上可以這麼解釋:
其中的
此處一律在
$\mathbf{Z}_n$ 下做運算
顯然
假設
而這題是
當然,實際上要完成這些事需要對 Sage 有一定的熟悉才能做到
詳見 solve.py。
此題靈感來源來自 RaRCTF 2021 - randompad,姑且算是它的簡化版