iT邦幫忙

2024 iThome 鐵人賽

DAY 25
0
Security

密碼學小白的學習之路系列 第 25

[Day 25] 題目(Symmetric-9)

  • 分享至 

  • xImage
  •  

PASSWORDS AS KEYS

https://aes.cryptohack.org/passwords_as_keys/

題目敘述摘要:

在對稱金鑰加密中,確保金鑰是隨機生成的而不是來自密碼或其他可預測的資料非常重要。因為如果金鑰具有可預測性,密碼的安全性會大幅降低,攻擊者就可能利用這一點來破解密文。

然而即使一個金鑰看起來像是隨機的,但實際上是由簡單的密碼經過雜湊函數生成的,那麼這樣的金鑰也不夠安全,甚至可能更容易被破解。

題目給的 source code 與註解

from Crypto.Cipher import AES
import hashlib
import random

# 從指定的字典文件中讀取所有單詞
#https://gist.githubusercontent.com/wchargin/8927565/raw/d9783627c731268fb2935a731a618aa8e95cf465/words 
with open("/usr/share/dict/words") as f:
    words = [w.strip() for w in f.readlines()]  # 去除每行結尾的換行符並存入列表

# 從讀取的單詞列表中隨機選擇一個詞作為密碼
keyword = random.choice(words)

# 使用 MD5 將選定的詞轉換為 16 bytes
KEY = hashlib.md5(keyword.encode()).digest()
FLAG = ?


@chal.route('/passwords_as_keys/decrypt/<ciphertext>/<password_hash>/')
def decrypt(ciphertext, password_hash):
    ciphertext = bytes.fromhex(ciphertext)  
    key = bytes.fromhex(password_hash)
    cipher = AES.new(key, AES.MODE_ECB) # 使用指定的密鑰和 ECB 模式來建立 AES 加密器
    try:
        # 解密密文
        decrypted = cipher.decrypt(ciphertext) 
    except ValueError as e:
        # 如果解密過程中出現錯誤,則返回錯誤信息
        return {"error": str(e)}
    return {"plaintext": decrypted.hex()}

@chal.route('/passwords_as_keys/encrypt_flag/')
def encrypt_flag():
    # 使用先前生成的 KEY 以 ECB 模式來建立 AES 加密器
    cipher = AES.new(KEY, AES.MODE_ECB)
    encrypted = cipher.encrypt(FLAG.encode())
    return {"ciphertext": encrypted.hex()}

解法

跟上一題一樣,我們可以直接從ENCRYPT_FLAG()得到 hex 格式的密文,但這題由於解密的時候還需要密碼,所以我們需要先找出密碼是甚麼。
原始碼中告訴了我們密碼是從一份單字列表中隨機選擇一個詞再經過 MD5 雜湊而成,具有隨機性。

要解題的話要先下載這份文字檔,然後改名(我改為words.txt)
放上我們得到的密文,依序讀取文字檔中的每一個單字,並進行md5雜湊來得到密鑰,接下來就依序使用密鑰進行和原始碼差不多的解密步驟。
而我們都知道flag的組成為crypto{...}所以如果解密出來的字串包含crypto{,就代表找到了對的密鑰,返回當前明文。

crypto{k3y5__r__n07__p455w0rdz?}

詳細程式碼:

import hashlib
from Crypto.Cipher import AES

with open('words.txt', 'r', encoding='utf-8', errors='ignore') as f:
    words = [w.strip() for w in f.readlines()]


ciphertext="c92b7734070205bdf6c0087a751466ec13ae15e6f1bcdd3f3a535ec0f4bbae66"
def decrypt(ciphertext):
    ciphertext = bytes.fromhex(ciphertext)
    for keyword in words:
        key = hashlib.md5(keyword.encode()).digest()
        cipher = AES.new(key, AES.MODE_ECB)
        decrypted = cipher.decrypt(ciphertext)
        try:
            decrypted = cipher.decrypt(ciphertext) 
            if b"crypto{" in decrypted :
                return decrypted.decode()
        except ValueError as e:
            return {"error": str(e)}

print(decrypt(ciphertext))

因為當初執行程式碼時一直發生 UnicodeDecodeError 的問題,在問了chatbot後將開啟檔案改成程式碼中的那樣後就沒有問題了~

參考資料:

https://ithelp.ithome.com.tw/m/articles/10332384

後話:

最近又開始沒空了,希望能寫完這部分的課程,進入到刷題的部分。


上一篇
[Day 24] 題目(Symmetric-8) & ECB 簡單介紹
下一篇
[Day 26] 題目(Network Attacks )
系列文
密碼學小白的學習之路31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言