異或基礎知識
首先先簡單了解異或(XOR)的數學公式:
-
XOR滿足交換律
a ⊕ b = b ⊕ a
-
與0做異或運算,輸出為它本身
a ⊕ 0 = a
0 ⊕ 0 = 0
1 ⊕ 0 = 1
-
不同為1,相同為0
1 ⊕ 0 = 1
0 ⊕ 1 = 1
0 ⊕ 0 = 0
1 ⊕ 1 = 0
-
異或運算及異或運算符
^

參考資料:異或加密
異或在密碼學中的具體使用
異或加密的原理就是上述的異或運算,相信大伙們可以很容易地理解這個異或運算,下面介紹的是異或加密的具體實現。
一次性密碼本 One Time Pad(OTP)
一次性密碼本OTP可以使用異或實現,OTP的密鑰k與明文消息m有相等的長度,密鑰與明文直接進行異或運算即可得到密文c消息。如果需要解密時,只需要對密文和密鑰再進行一次異或運算就可以得到明文消息
例如:密鑰k = 73 明文消息m = 87
密文消息c = k ⊕ m = 30(見下方的圖片)

m = k ⊕ c = 73 (具體過程可以自己推推)
優缺點:若密鑰只使用一次且密鑰隨機==>安全性極高,但是在實際中,該加密的密鑰與明文一樣長且在傳輸過程中需要絕對的保密,傳輸不方便
多次密碼本 Many Time Pad(MTP)
相較於OTP,MTP通過將明文消息M分成與密鑰相同長度多組明文消息Mi,再通過共享密鑰K生成多組密文Ci, 相當於按順序用了多次的共享密鑰,但可以使得密鑰的長度大大減少
MTP解密方法
Many Time Pad Attack - Crib Drag 方法
若我們得知多組中的一組密文Ci對應的密鑰K,即共享密鑰K已知,則可以作用與其它組的密文解密

即可以通過多次的循環解密得到多個明文消息部分,再從中選擇可讀部分(有些是亂碼),這樣說不直觀,我們通過一道ALEXCTF-2017的題目來引入
參考資料:
Many Time Pad Attack - Crib Drag(需fanqiang)
個人轉載:
相關題目
題目來源:
https://adworld.xctf.org.cn/task/answer?type=crypto&number=5&grade=1&id=5028&page=2
- 文件信息
文件所給的是一長串數字字母字符串,去掉空格后為
0529242a631234122d2b36697f13272c207f2021283a6b0c79082f28202a302029142c653f3c7f2a2636273e3f2d653e25217908322921780c3a235b3c2c3f207f372e21733a3a2b37263b3130122f6c363b2b312b1e64651b6537222e37377f2020242b6b2c2d5d283f652c2b31661426292b653a292c372a2f20212a316b283c0929232178373c270f682c216532263b2d3632353c2c3c2a293504613c37373531285b3c2a72273a67212a277f373a243c20203d5d243a202a633d205b3c2d3765342236653a2c7423202f3f652a182239373d6f740a1e3c651f207f2c212a247f3d2e65262430791c263e203d63232f0f20653f207f332065262c31683137223679182f2f372133202f142665212637222220733e383f2426386b
這里的字符串記為密文m
- 腳本解密
這里推薦使用 Crib Drag腳本 該腳本是使用python2寫的
運行代碼
python2 cribdrag.py 16進制密文

接下來輸入一個可能存在於明文或者密鑰里的字符串,這里輸入該比賽的flag開頭ALEXCTF{

05 29 24 2a 63 12 34 12 密鑰m的第0位開始8位
41 4c 45 58 43 54 46 7b ALEXCTF{ 的16進制形式
XOR ———————————
44 65 61 72 20 46 72 69 異或運算的結果
結果為Dear Fri,腳本運算的結果也是如此,前面的0-280為各個位開始的8個字節進行的異或運算的結果,在較有意義的字符串前面會加上 ***
腳本會回顯一條交互命令
Enter the correct position, 'none' for no match, or 'end' to quit:
選擇一個合適的位置,沒有的話就輸入none或end
0位的字符串明顯是有意義的,我們輸入0即可
此時,腳本又會回顯一段交互命令
Is this crib part of the message or key? Please enter 'message' or 'key':
選擇將crib填入message還是key中,這里的crib(對照文)就是我們輸入的
ALEXCTF{
我們假定選擇為key(這里選key或者message似乎不是特別的重要)

繼續輸入ALEXCTF{,查看其他位是否還有有意義的字符串

簡單排查了一遍之后,key和message如上圖所示
接下來就是要進行字符串猜測,比如第一行的Dear Fri,我們可以猜測Dear Friend, 將這個字符串作為新的crib帶入腳本中,並選擇為message部分

這里key第一行為ALEXCTF{HERE,猜測完成后我們根據經驗又可以猜測之后會有一個下划線,於是下一個新的crib為ALEXCTF{HERE_

多次Crib Drag后,得到進一步的如上信息,接下來再次進行猜測,我們剛剛了解到OTP一次性密碼本,我們這里看到第二行sed One time,直接猜測並輸入新的crib:sed One time pad,大概在52位的地方可以看到一組有意義的字符串


重復上面的步驟,輸入新的crib為ALEXCTF{HERE_GOE
更新一遍信息后

這里猜測為cure, Let Me know (最后面有個空格注意下)
得到ALEXCTF{HERE_GOES_
之后就反復猜測,這里就不一一贅述了
最后得到ALEXCTF{HERE_GOES_THE_KEY}
