文章目录
- 一、写在前面
- 二、题目概述
- 二、解题步骤
-
- 1.求未知数字
- 2.求key
-
- 2.1求Kseed
- 2.2求Ka和Kb
- 2.3对Ka和Kb奇偶校验生成key
- 三、总结
一、写在前面
密码学老师布置的作业,虽然题不是很难,但是这个进制转换晕了好久。
先给一下原题目的链接:
https://www.mysterytwisterc3.org/en/challenges/level-2/aes-key–encoded-in-the-machine-readable-zone-of-a-european-epassport
二、题目概述
因为题目是英文的,这里简单机翻加一点点渣渣自翻。
1、AES加密模式为CBC,初始化矢量即IV为零,填充为01-00。此外,相应的密钥在身份证件上的机器可读区域(MRZ)等表格中,它与欧洲的电子护照一起使用时并不十分完整。

2、目标是找到以下base64编码消息的明文:
9MgYwmuPrjiecPMx61O6zIuy3MtIXQQ0E59T3xB6u0Gyf1gYs2i3K9Jxaa0zj4gTMazJuApwd6+jdyeI5iGHvhQyDHGVlAuYTgJrbFDrfB22Fpil2NfNnWFBTXyf7SDI
3、对于加密,已生成并应用基于基本访问控制(BAC)协议的密钥KENC。对于解密,已经发送了以下字符,从中可以导出KENC(这些字符的编码类型在[1]中描述):
12345678 <8 <<< 1110182 <111116?<<<<<<<<<<<<<<< 4
(就是图里面给的那个)
4、在传输过程中丢失了并且突出显示了一个’’?’’。可以在[2]的帮助下恢复它。为了能够在之后计算密钥KENC,可以找到应用编码的概述[3],[4]中的协议和[5]中的一个例子。
5、在解密之前解码base64代码。
总而言之,就是根据它给的那一串数字,然后按照它参考文章里面用到的方法去还原加密的明文。
二、解题步骤
我把这道题分为三步:
1、求未知数字
2、根据得到的数字计算出key
3、拿key和base64解码后的密文解密
1.求未知数字
按照提示,他说在参考文章2中可以找到恢复的方法,我在最后把这两个用到的参考文章还有题目的pdf文件放在最后的百度云链接。


可以得到那个问号,是一个校验到期日期的校验位。而且校验位的方法也给出了。所以我们只需要按照他给的方法,就能很方便的求出那个问号是7。
下面展示实现代码
1 2 3 4 5 6 7 | a = [1,1,1,1,1,6] b = [7,3,1,7,3,1] for i in range(0,6): c = c + a[i]*b[i] res = c % 10 print (res) #res = 7 |
这样就得到了最终的护照信息是
‘12345678<8<<<1110182<1111167<<<<<<<<<<<<<<<4’
2.求key
这个就是此题的关键部分,也是我搞得最久的部分。
大体上分为
1、求Kseed
2、求Ka和Kb
3、对Ka和Kb奇偶校验生成key
2.1求Kseed
这部分也是按照参考文章,就可以轻松的得到Kseed了。

简单来说,就是把-证件的那些数字和校验位,直接sha1散列,然后取前16位即可。
1 2 3 | H_information = sha1(information.encode()).hexdigest() #十进制先变为二进制散列再换成十六进制 K_seed = H_information[:32]# 取前16位 |
2.2求Ka和Kb

这段话的主要意思就是,把之前生成的Kseed和c级联,然后再进行一次sha1散列生成了d,然后ka是d的前十六位,kb是d的后十六位。
1 2 3 4 5 6 7 8 9 | c = '00000001' #0x00000001 d = K_seed + c #print(d) H_d = sha1(codecs.decode(d,"hex")).hexdigest() #十六进制先变为二进制散列再换成十六进制 #print(H_d) ka = sha1(codecs.decode(d,"hex")).hexdigest()[:16] kb = sha1(codecs.decode(d,"hex")).hexdigest()[16:32] |
2.3对Ka和Kb奇偶校验生成key
根据上段话,其实学过计算机网络的话其实非常好理解,就是算1的个数并且把第八位当作奇偶校验位。
这里就不多说什么了,直接上代码了,如果有什么不懂的可以在评论里面问我或者去百度或者google一下,网上的教程有很多。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | k_1 = jiaoyan(ka) k_2 = jiaoyan(kb) key = k_1 + k_2 print(key) #ea8645d97ff725a898942aa280c43179 m=AES.new(binascii.unhexlify(key),AES.MODE_CBC,binascii.unhexlify(IV)) print(m.decrypt(cipher)) #b'Herzlichen Glueckwunsch. Sie haben die Nuss geknackt. Das Codewort lautet: Kryptographie!\x01\x00\x00\x00\x00\x00\x00' #奇偶校验位的判断 def jiaoyan(x): k = [] a = bin(int(x,16))[2:] for i in range(0,len(a),8): if (a[i:i+7].count("1"))%2 == 0: k.append(a[i:i+7]) k.append('1') else : k.append(a[i:i+7]) k.append('0') a1 = hex(int(''.join(k),2)) #print("this is " + x + "---" +a1) return a1[2:] |
三、总结
因为找到了题目中参考文章的中文版本,所以阅读和理解起来其实还算挺轻松的。
这里面主要的难点就是里面的几个进制转换问题,这个我没有过多的去介绍,因为我也没特别明白,而且这几天也没有时间去投入精力,所以如果有问题评论私信都可以,我会尽量的去解答。
我也没有写sha1散列和AES的相关知识,我觉得做这种题的人应该对这几个密码都很熟悉的(笑)。
还有里面用到的校验位和奇偶校验问题,这个知识其实计算机网络里面讲的特别详细易懂,网上的教程应该也挺多的,我就不多讲了。
有任何问题都可以在评论区里面问我。
最后附上相关文件的百度云网盘地址:
链接:https://pan.baidu.com/s/1sI-gBIMsEidYtNvgbGiIAw
提取码:4k74