帶有簡單密文的 openssl 的正確選項
上週末有一個密碼挑戰,其中密文是以下十六進制:
FC 89 BF C2 B0 5F 1C 2E 64 B8 78 43 92 78 3A C9
我確信這是使用 AES/Rijndael 128 位 ECB 加密的,密鑰是 REDRYDER,並且已經發布了一個解決方案來確認這一點。純文字是 FLAG=DAISY。我編寫了一個簡單的 PHP mcrypt 腳本,它在沒有鹽或沒有 IV 字元串的情況下對此進行解密,並且它可以正確解密。但是,當我嘗試使用 openssl 時,我沒有得到純文字:
echo "0: FC 89 BF C2 B0 5F 1C 2E 64 B8 78 43 92 78 3A C9" | xxd -r | openssl aes-128-ecb -d -k REDRYDER -nosalt -nopad ; echo
這只是輸出一些二進制數據。我還嘗試通過 dd conv=swab 傳遞輸入來進行字節交換。
我究竟做錯了什麼?
openssl
命令行工具是 OpenSSL 庫的展示。它有一個非常隨意的界面和糟糕的文件。除了測試 OpenSSL 庫之外,我不建議將它用於任何其他用途。(是的,有些人用openssl
. 管理 CA。我擔心他們的理智。)AES使用密鑰而不是密碼進行操作。一個 AES-128 密鑰正好是 16 個字節。
該選項
-k
不使用密鑰作為輸入,它需要密碼。此密碼經過雜湊處理以派生密鑰;預設為 MD5,可以用命令行選項覆蓋它-md
。據我所知,這在手冊中沒有記錄,您只需閱讀原始碼(apps/enc.c
,呼叫EVP_BytesToKey
)。MD5 摘要從任何字元串中產生一個 16 字節的值,但這不是這裡使用的。在這種情況下,鍵實際上REDRYDER\0\0\0\0\0\0\0\0
是\0
空字節的位置。該選項
-K
允許您以十六進制傳遞密鑰。如果您傳遞的字節數少於密鑰大小,OpenSSL 將以空字節完成。所以要傳遞關鍵REDRYDER\0\0\0\0\0\0\0\0
,你可以傳遞$(echo REDRYDER | od -An -tx1 | tr -d ' ')
which is5245445259444552
。密鑰為 52454452594445520000000000000000 的密文塊 FC89BFC2B05F1C2E64B8784392783AC9 的 AES-128-ECB 解密操作產生 464c41473d4441495359000000000000 (使用十六進制為 那就是
FLAG=DAISY\0\0\0\0\0\0
。對於像這樣的小加密操作,我喜歡帶有Pycrypto庫的 Python 頂層。
>>> from binascii import hexlify, unhexlify >>> from Crypto.Cipher import AES >>> ciphertext = unhexlify('FC 89 BF C2 B0 5F 1C 2E 64 B8 78 43 92 78 3A C9'.replace(' ', '')) >>> key = 'REDRYDER'.ljust(16, '\0') >>> AES.new(key, AES.MODE_ECB).decrypt(ciphertext) 'FLAG=DAISY\x00\x00\x00\x00\x00\x00'