文章

MT3C Level2-AES key

题目

题目原文件

  1. AES 加密模式为 CBC,初始化矢量即 IV 为零,填充为 01-00。此外,相应的密钥在身份证件上的机器可读区域(MRZ)等表格中,它与欧洲的电子护照一起使用时并不十分完整。
  2. 目标是找到以下 base 64 编码消息的明文: 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 和 base 64 解码后的密文解密

分析

  1. 求未知数 12345678 <8 <<< 1110182 <111116?<<<<<<<<<<<<<<< 4 中的?可以根据参考求解 20201106235115787.webp 20201106235211834.webp 转换成代码,由此,可以计算出“?”
    1
    2
    3
    4
    5
    6
    
     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
    

    所以,完成的护照信息为:

    1
    
     12345678<8<<<1110182<1111167<<<<<<<<<<<<<<<4
    
  2. 计算 Key
    1. 求 kseed 20201107001019751.webp
    1
    2
    3
    4
    5
    6
    7
    8
    
     def cal_Kseed() -> str:  
         # 护照信息 
         MRZ_information = "12345678<811101821111167"
         # 使用SHA1进行哈希
         H_information = sha1(MRZ_information.encode()).hexdigest()
         # 取哈希值的前32位作为K_seed 
         K_seed = H_information[0:32]   
         return K_seed
    
    1. 求 Ka 和 Kb 20201107162102301.webp 这段话的主要意思就是,把之前生成的 Kseed 和 c 级联,然后再进行一次 sha 1 散列生成了 d,然后 ka 是 d 的前十六位,kb 是 d 的后十六位。
      1
      2
      3
      4
      5
      6
      7
      8
      
       def cal_Ka_Kb(K_seed):  
       c = "00000001"  
       d = K_seed + c  
       # 对K_seed进行哈希  
       H_d = sha1(codecs.decode(d, "hex")).hexdigest()  
       ka = H_d[0:16]  # 取前16位作为ka  
       kb = H_d[16:32]  # 取后16位作为kb  
       return ka, kb
      
    2. 对 Ka 和 Kb 奇偶校验生成 key
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      
       def Parity_Check(x):  
       k_list = []  
       a = bin(int(x, 16))[2:]  # 将16进制转为2进制  
       for i in range(0, len(a), 8):  
       # 7位一组分块,计算一个校验位,使1的个数为偶数  
       if (a[i:i + 7].count("1")) % 2 == 0:  
           k_list.append(a[i:i + 7])  
           k_list.append('1')  
       else:  
           k_list.append(a[i:i + 7])  
           k_list.append('0')  
       k = hex(int(''.join(k_list), 2))  # 将2进制转为16进制  
       return k
      

      代码

      完整代码:

      ```python from hashlib import sha1
      import codecs
      import base64
      from Cryptodome.Cipher import AES
      import binascii

求未知数,是到期日的校验位,根据校验规则计算

def Unknown_Number() -> int:
Unknown_Number = 0
number = “111116” # 预设的数字
weight = “731” # 权重
for i in range(0, len(number)):
Unknown_Number += int(number[i]) * int(weight[i % 3])
return Unknown_Number % 10 # 返回校验位

计算k_seed

def cal_Kseed() -> str:
MRZ_information = “12345678<811101821111167” # 护照信息
H_information = sha1(MRZ_information.encode()).hexdigest() # 使用SHA1进行哈希
K_seed = H_information[0:32] # 取哈希值的前32位作为K_seed
return K_seed

def cal_Ka_Kb(K_seed):
c = “00000001”
d = K_seed + c
H_d = sha1(codecs.decode(d, “hex”)).hexdigest() # 对K_seed进行哈希
ka = H_d[0:16] # 取前16位作为ka
kb = H_d[16:32] # 取后16位作为kb
return ka, kb

对Ka和Kb分别进行奇偶校验,得到新的k1和k2

def Parity_Check(x):
k_list = []
a = bin(int(x, 16))[2:] # 将16进制转为2进制
for i in range(0, len(a), 8):
# 7位一组分块,计算一个校验位,使1的个数为偶数
if (a[i:i + 7].count(“1”)) % 2 == 0:
k_list.append(a[i:i + 7])
k_list.append(‘1’)
else:
k_list.append(a[i:i + 7])
k_list.append(‘0’)
k = hex(int(‘‘.join(k_list), 2)) # 将2进制转为16进制
return k

def main():
K_seed = cal_Kseed() # 计算K_seed
ka, kb = cal_Ka_Kb(K_seed) # 计算ka和kb
k_1 = Parity_Check(ka) # 对ka进行奇偶校验
k_2 = Parity_Check(kb) # 对kb进行奇偶校验
key = k_1[2:] + k_2[2:] # 合并k_1和k_2作为最终的密钥
print(“The key is:”, key) # 输出密钥

1
2
3
4
5
6
7
8
# 待解密的密文  
ciphertext = base64.b64decode(  
    "9MgYwmuPrjiecPMx61O6zIuy3MtIXQQ0E59T3xB6u0Gyf1gYs2i3K9Jxaa0zj4gTMazJuApwd6+jdyeI5iGHvhQyDHGVlAuYTgJrbFDrfB22Fpil2NfNnWFBTXyf7SDI")  
IV = '0' * 32  # 初始化向量  
  
# 使用AES进行解密  
m = AES.new(binascii.unhexlify(key), AES.MODE_CBC, binascii.unhexlify(IV)).decrypt(ciphertext)  
print(m.decode())  # 输出解密后的明文  

if name == “main”:
main()

1
### 结果:

The key is: ea8645d97ff725a898942aa280c43179 Herzlichen Glueckwunsch. Sie haben die Nuss geknackt. Das Codewort lautet: Kryptographie! ```

参考

[mysterytwisterc3-challenge-AES key — encoded in the machine readable zone of a European ePassport码农家园](https://www.codenong.com/cs109540921/)

GitHub - Joel-Q-Xu/MT3-mysterytwisterc3

密码学大作业 - J4m - 博客园

本文由作者按照 CC BY 4.0 进行授权