XOR暗号化されたデータから暗号鍵を取得する【CTF】

手軽に使えるXOR暗号化ですが、鍵が分からなければ比較的安全ではあるものの、暗号化された元のデータが入手可能な場合に脆弱になります。
そのような条件の解読手法として既知平文攻撃(KPA)がありますが、XOR暗号化はKPAに対して非常に脆弱です。
今回はXOR暗号化されたデータを元に実際に既知平文攻撃を試してみます。

注: CELTF の "ToDo管理サービス" に関する解析方法を含みます。

XOR暗号化

そもそもXOR暗号化とは何かですが、XORの特性として可逆の性質があります。

ABXOR
000
011
101
110

その性質を利用し、共通鍵暗号を実現したものがXOR暗号化になります。
例として、 "1101" と "1001" というバイナリデータをXORすると、結果として得られるのは "0100" となります。

1101 XOR 1001 = 0100

得られた "0100" の結果ですが、入力に利用した値と再度XORを行うと元の値に戻るという性質があります。

0100 XOR 1001 = 1101
0100 XOR 1101 = 1001

これを利用し、例えば暗号鍵として "0110" を利用し、"0011" というデータを暗号化しようとします。

0110 XOR 0011 = 0101

"0101" という暗号化されたデータが入手できました。
その後、 "0101" というデータを復号化するために、暗号化で利用した "0110" を使用して復号化してみます。
XOR暗号化は共通鍵暗号になるため、暗号化に利用する鍵と復号化に利用する鍵が同一になります。

0110 XOR 0101 = 0011

暗号鍵で暗号化後のデータをXORした結果、暗号化前のデータが入手できました。
この方法を利用した暗号化がXOR暗号となります。

既知平文攻撃

既知平文攻撃とは、暗号化前のデータと、その暗号化されたデータが入手可能な場合に行う事ができる暗号解読の手法です。
暗号化といえばエニグマがありますが、エニグマは既知平文攻撃によって解読できる暗号の一つです。
エニグマは毎日鍵を更新する事で安全性を担保していましたが、日々送られる定型文を利用し解読されるに至りました。
エニグマに関して気になる方は「イミテーション・ゲーム」を見ると面白いです。

実際の解読

実際に、CELTFの問題を利用して解読してみます。
今回利用する暗号化される前のデータは "e852b4f2-37c0-4403-8df1-faea8805d41b" になります。
また、暗号化後のデータは "VllRAlMDBAEAAlJbVQAABwULAABTX1IAVFldWQsBVg1TBAUA" になります。
暗号化後のデータは印字不可文字を含むためbase64にてエンコードされています。

暗号鍵の取得

今回、暗号鍵の取得にはPythonを利用します。

データ定義

まずはデータを変数に定義します。

encrypted = "VllRAlMDBAEAAlJbVQAABwULAABTX1IAVFldWQsBVg1TBAUA"
plain = b"e852b4f2-37c0-4403-8df1-faea8805d41b"
# plainはXORするためにbytesとして扱う必要があるため、バイト型で定義しています。

暗号化データのデコード

次に、暗号化されたデータをbase64でデコードします。

import base64
encrypted_raw = base64.b64decode(encrypted)

暗号鍵を取得

最後に、暗号化されたデータを利用し暗号鍵を取得します。
"暗号化されたデータ XOR 暗号鍵" で暗号化されたデータを復号化出来ますが、 "暗号化されたデータ XOR 暗号化される前のデータ" とする事で暗号鍵を取得できます。
zip関数を利用すれば1行で記載する事も可能ですが、今回は処理の可読性を上げるためにfor文で記載しています。

dec_chars = []
for i in range(len(plain)):
    dec = encrypted_raw[i] ^ plain[i] # XORをして暗号鍵を取得
    dec_char = chr(dec) # 暗号鍵は印字可能文字なのでASCIIに変換
    dec_chars.append(dec_char) # 最後にまとめて表示するためにリストに格納

暗号鍵を表示

取得した暗号鍵を表示します。
表示した暗号鍵はCELTFの "復号化キー" のフラグとなります。

print("".join(dec_chars))

おわりに

今回はXOR暗号化された暗号データから既知平文攻撃を利用し、暗号鍵を入手しました。
暗号解読には大まかに4つの種類が存在し、それらの攻撃に耐えられるアルゴリズムが求められます。
暗号化されていれば安全だと思いがちですが、暗号化アルゴリズムによっては様々な脆弱性が発見されています。
自分の手で攻撃する事で、机上だけではなく脆弱性のあるアルゴリズムは実際にセキュリティリスクがある事を実感できたと思います。
今後は暗号化有無だけではなく、暗号化アルゴリズムにも目を向けていけるとセキュリティレベルが上がります。