古典密码-异或加密XOR
异或基础知识
首先先简单了解异或(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}