第九届工业信息安全技能大赛-枫叶杯-密码应用安全①初赛
题目1
1. 已知某分组算法分组长度 32比特,采用CBC 分组算法工作模式,初始向量为 IV=0x12345678,
四组明文消息和密文分别是[11223344 aaaaaaaa 14725836 11335577],和 [be91835a 03ec3058 370606ae f1e58037]。
请构建另一组明文消息,采用同样的密钥加密,初始向量IV_1 为 ffffffff,加密后密文为:[03ec3058 be91835a f1e58037 370606ae]。
则新的明文是?(格式为16进制)。
CBC 加密流程回顾

C[0] = Enc(P[0] ^ IV)C[1] = Enc(P[1] ^ C[0])C[2] = Enc(P[2] ^ C[1])C[3] = Enc(P[3] ^ C[2])
所以:
P[0] = Dec(C[0]) ^ IVP[1] = Dec(C[1]) ^ C[0]P[2] = Dec(C[2]) ^ C[1]P[3] = Dec(C[3]) ^ C[2]
解密流程:

lst = [(0x11223344 ^ 0x12345678),
(0xaaaaaaaa ^ 0xbe91835a),
(0x14725836 ^ 0x03ec3058),
(0x11335577 ^ 0x370606ae)]
print([f'0x{x:08x}' for x in lst])
# [0x0316653c, 0x143b29f0, 0x179e686e, 0x263553d9]
""" 映射表
Enc(0x0316653c) = be91835a
Enc(0x143b29f0) = 03ec3058
Enc(0x179e686e) = 370606ae
Enc(0x263553d9) = f1e58037
"""
# 求 [03ec3058 be91835a f1e58037 370606ae]
# 根据映射表 异或后输入值为 0x143b29f0 0x0316653c 0x263553d9 0x179e686e
iv1 = 0xffffffff
p1 = 0x143b29f0 ^ iv1
p2 = 0x0316653c ^ 0xbe91835a
p3 = 0x263553d9 ^ 0xf1e58037
p4 = 0x179e686e ^ 0x370606ae
print(' '.join(f"{x:08x}" for x in [p1, p2, p3, p4]))
# ebc4d60f bd87e666 d7d0d3ee 20986ec0
2. 在加密通讯中,随机数是保障安全性的核心要素之一,其作用贯穿密钥生成、协议设计、身份验证等多个环节。某系统中的一台设备随机数发生器出现故障,在DH交换时私钥全为0xCC,造成私钥泄露。现采集其通讯数据(见附件),请分析:
附件:
1).密钥交换算法是? (15/分)
Diffie-Hellman (DH)
2).IKE的数据完整性校验算法是? (15/分)
- 从Frame 1和Frame 2的Security Association payload中可以看到
- Transform Type: Integrity Algorithm (INTEG) (3)
- Transform ID (INTEG): AUTH_HMAC_SHA1_96 (2)
AUTH_HMAC_SHA1_96
3).是通讯发起方设备还是响应方设备出现故障(填写"发起方"或“响应方”) (20/分)
响应方
4).DH共享密钥值是(十六进制方式) (30/分)
0582a72064aed69a5729c3cd84055feb9eecf2bb14bae26a26f0e322e667d174554fc11c06b204469de0650178ecd53d56a0ad8e016e93e66288f9e997a868488334ec61f0cbf35d6314f081e9555ef34cfb6021cbb68f97eaea0b66fc44dccb97fe2f64bd9cf02bf648f88bbccea0053b26007ac9b1fd82c616d14b1805ae4eb2e2e0c55fd0fc1e9f0ee6451120c1e8c6962755cb417776e3ef1f9da896110930f8551189a29dfa940bcf3d1bdbd05d4b5924922c7655c3224c9f4cb792f86b44f22bc95f5c42cca76d2e063a03e651f3eb4bae75c13499ce6891680114cab502b50541ca76895e55c4984e60adb899d1bd2deb5e3b06aff634b53d00f20883
5).密钥种子SKEYSEED是(十六进制方式) (30/分)
95c58ae7ff1554186e450f94c3f70a31d64fbb8c
6).发起方的IKE加密密钥SK_ei是: (40/分)
# AES-CBC-256 , key 为 32Bytes
from Crypto.Hash import HMAC, SHA
import binascii
SPIi = binascii.a2b_hex('e0b156c9f61def4b')
SPIr = binascii.a2b_hex('c56eb49736d476d3')
SKEYSEED = bytes.fromhex('95c58ae7ff1554186e450f94c3f70a31d64fbb8c')
K = SKEYSEED
Ni = bytes.fromhex('76e1dbf5a2fd251d663c8f10103bb876c9f02eb6807168b3bea0f5b6a314565b')
Nr = bytes.fromhex('6c8fe3ce8951c4ebce5e9b167b00c02e684fa26ebc4487226f349b52ea34fb78')
S = Ni + Nr + SPIi + SPIr
T = b''
TotalKey = b''
for i in range(1, 10): # 10 次循环足够生成所需密钥
count_byte = binascii.a2b_hex('%02d' % i) # 0x01 0x02 0x03 ...
data = T + S + count_byte
T = HMAC.new(K, data, SHA).hexdigest()
T = binascii.a2b_hex(T)
TotalKey += T
SK_d = TotalKey[0:20]
SK_ai = TotalKey[20:20 + 20]
SK_ar = TotalKey[40:40 + 20]
SK_ei = TotalKey[60:60 + 32]
SK_er = TotalKey[92:92 + 32]
SK_pi = TotalKey[124:124 + 20]
SK_pr = TotalKey[144:144 + 20]
# 打印结果
print(f'SK_d = {SK_d.hex()}')
print(f'SK_ai = {SK_ai.hex()}')
print(f'SK_ar = {SK_ar.hex()}')
print(f'SK_ei = {SK_ei.hex()} (长度: {len(SK_ei)} 字节)')
print(f'SK_er = {SK_er.hex()} (长度: {len(SK_er)} 字节)')
print(f'SK_pi = {SK_pi.hex()}')
print(f'SK_pr = {SK_pr.hex()}')
# 453d6774c0eaf163864c1340b05fd7c219cc17cf7492ac716f6be2318b9f8f2c
7).由于密钥泄露,可以解密数据,解密ESP后,可以得到ESP明文,是UDP数据包,内容格式如下:
45 00 00 3c b6 ed 00 00 80 11 00 00 c0 a8 03 15
c0 a8 02 30 03 e8 07 d0 00 28 86 cf 73 65 6e 64
20 6d 73 67 20 3d 20 7b 30 31 32 33 34 35 36 37
38 39 30 31 32 33 34 35 36 7d 0d 0a
分析可以发现UDP报文数据类似“send msg = {01234567890123456}”,请解密实际数据,填写解密后UDP报文数据中大括号内的字符串: (50/分)
学了一天才学会。
73047882172936819
# https://www.rfc-editor.org/rfc/rfc3526.html
# g = 2, p_hex 是 2048-bit MODP Group 用到的标准质数 g ^ d % p = pow(g,d,p)
# ESP 格式 https://datatracker.ietf.org/doc/html/rfc4303#section-3.1
import hashlib
import hmac
from Cryptodome.Cipher import AES
import re
print(f'{" Q3 ":-^30}')
p_hex = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF"
p = int(p_hex, 16)
g = 2
priv_key_faulty_hex = "cc" * 256
priv_key_faulty = int(priv_key_faulty_hex, 16)
result = pow(g, priv_key_faulty, p)
h = hex(result)
if '1119cf0e23' in h:
print('发起方')
if '1b2f22ea5e' in h:
print('响应方')
# 响应方
print(f'{" Q4 ":-^30}')
# K = (发起方的公钥 A) ^ (响应方的故障私钥 b) mod p
pub_key_i = 0x1119cf0e2342bc9dd981e34e345ea68e363ef54cf4328afa40b2d55a9e473736d16d2a824d18be5ee395149d785de49178725f55368cffa26d6c67927fe7d540e5e17cc6ce22c7481a873a28035371ca1427745eb9975686d0774342533d2d469a422f28bdb2ba0684521fd5eeadcec18c240de35308b594390513cdba65246a3aa6cbdd506822086d2a733864198a46290fc32687f183d26a81cc8ebf0bb0e6d2f52ee8db3980207cbe266bf6d8b080d6a9c1ed1b4fcf1936bb54e0eb173fcaec4869d97b1a9917e31d20de3328ff4c8d6258d5be699c7d69e4e59768c4d152fa4bdcc0be4fb6b981fb16675fd197878fd5384ab4d9f9c1a7d690eb23b13b98
priv_key_r_faulty = priv_key_faulty
shared_key = pow(pub_key_i, priv_key_r_faulty, p)
shared_key_hex = f'{shared_key:0{256 * 2}x}'
print(f"DH共享密钥值是: {shared_key_hex}")
# 0582a72064aed69a5729c3cd84055feb9eecf2bb14bae26a26f0e322e667d174554fc11c06b204469de0650178ecd53d56a0ad8e016e93e66288f9e997a868488334ec61f0cbf35d6314f081e9555ef34cfb6021cbb68f97eaea0b66fc44dccb97fe2f64bd9cf02bf648f88bbccea0053b26007ac9b1fd82c616d14b1805ae4eb2e2e0c55fd0fc1e9f0ee6451120c1e8c6962755cb417776e3ef1f9da896110930f8551189a29dfa940bcf3d1bdbd05d4b5924922c7655c3224c9f4cb792f86b44f22bc95f5c42cca76d2e063a03e651f3eb4bae75c13499ce6891680114cab502b50541ca76895e55c4984e60adb899d1bd2deb5e3b06aff634b53d00f20883
print(f'{" Q5 ":-^30}')
# Ni: Initiator's Nonce,发起方生成的、本次会话使用的一次性随机数。
# Nr: Responder's Nonce,响应方生成的、本次会话使用的一次性随机数。
"""
tshark -r capture.pcap -T fields -e isakmp.nonce
76e1dbf5a2fd251d663c8f10103bb876c9f02eb6807168b3bea0f5b6a314565b
6c8fe3ce8951c4ebce5e9b167b00c02e684fa26ebc4487226f349b52ea34fb78
"""
bh = lambda x: bytes.fromhex(x)
Ni = bh('76e1dbf5a2fd251d663c8f10103bb876c9f02eb6807168b3bea0f5b6a314565b')
Nr = bh('6c8fe3ce8951c4ebce5e9b167b00c02e684fa26ebc4487226f349b52ea34fb78')
nonce_concat = Ni + Nr
g_ir_bytes = shared_key.to_bytes(256, 'big')
# tshark -r capture.pcap -V | grep PRF , PRF_HMAC_SHA1
SKEYSEED = hmac.new(nonce_concat, g_ir_bytes, hashlib.sha1).digest()
print(f"密钥种子SKEYSEED是: {SKEYSEED.hex()}")
# 9ec82c13e5f2beb1c7af21f6873e113ba04c47fda57fce06c3e0f5141d2fc452
print(f'{" Q6 ":-^30}')
# --- Q4: Initiator's IKE Encryption Key (SK_ei) ---
SPIi = bytes.fromhex('e0b156c9f61def4b') # frame1_payload_hex[:16]
SPIr = bytes.fromhex('c56eb49736d476d3') # frame2_payload_hex[16:32])
seed = Ni + Nr + SPIi + SPIr
s = seed
t1 = hmac.new(SKEYSEED, s + b'\x01', hashlib.sha1).digest()
t2 = hmac.new(SKEYSEED, t1 + s + b'\x02', hashlib.sha1).digest()
t3 = hmac.new(SKEYSEED, t2 + s + b'\x03', hashlib.sha1).digest()
t4 = hmac.new(SKEYSEED, t3 + s + b'\x04', hashlib.sha1).digest()
t5 = hmac.new(SKEYSEED, t4 + s + b'\x05', hashlib.sha1).digest()
TotalKey = t1 + t2 + t3 + t4 + t5
"""
SK_d (用于派生更多密钥 20字节)
SK_ai (发起方认证密钥,20字节)
SK_ar (响应方认证密钥,20字节)
SK_ei (发起方加密密钥,32字节)
SK_er (响应方加密密钥,32字节)
SK_pi (发起方身份伪随机函数密钥,32字节)
SK_pr (响应方身份伪随机函数密钥,32字节)
"""
SK_d = TotalKey[0:20]
SK_ai = TotalKey[20:20 + 20]
SK_ar = TotalKey[40:40 + 20]
SK_ei = TotalKey[60:60 + 32]
print(f"发起方的IKE加密密钥SK_ei是: {SK_ei.hex()}")
print(f'{" Q7 ":-^30}')
# --- Q5: Decrypt ESP ---
seed_child = Ni + Nr
keymat_t1 = hmac.new(SK_d, seed_child + b'\x01', hashlib.sha1).digest()
keymat_t2 = hmac.new(SK_d, keymat_t1 + seed_child + b'\x02', hashlib.sha1).digest()
keymat_t3 = hmac.new(SK_d, keymat_t2 + seed_child + b'\x03', hashlib.sha1).digest()
keymat_t4 = hmac.new(SK_d, keymat_t3 + seed_child + b'\x04', hashlib.sha1).digest()
keymat_t5 = hmac.new(SK_d, keymat_t4 + seed_child + b'\x05', hashlib.sha1).digest()
keymat = keymat_t1 + keymat_t2 + keymat_t3 + keymat_t4 + keymat_t5
# ESP_KEY_ei: Starts at 0, length 32. --> [0:32]
# ESP_KEY_ai: Starts at 32, length 20. --> [32:52]
# ESP_KEY_er: Starts at 52, length 32. --> [52:84]
# ESP_KEY_ar: Starts at 84, length 20. --> [84:104]
ESP_KEY_ei = keymat[0: 32]
ESP_KEY_ai = keymat[32: 52]
ESP_KEY_er = keymat[52: 84]
ESP_KEY_ar = keymat[84: 104]
key_len_esp_encr = 32
SK_ei_esp = keymat[0:key_len_esp_encr]
esp_hex = "cf867ae800000001b9cc1fd530becf6aefbe19ec41c6e23cfa86f899a99e8b64180de9858e06977a8a91553a741f930845228caf0604b8b0c9169d641406ce7c1415ffe0fd6fca58815177f46e515dd9ccb5102625afb41c1f883c943933d75260b1ba82"
esp_data = bytes.fromhex(esp_hex)
# ESP_Payload = SPI (4B) + Seq (4B) + IV (16B) + Ciphertext (可变) + ICV (12B)
spi, seq, esp_iv, esp_ciphertext, icv = esp_data[:4], esp_data[4:8], esp_data[8:8 + 16], esp_data[24:-12], esp_data[-12:]
# 响应方发包用 ESP_KEY_er 解,请求方发包用 ESP_KEY_ei 解
cipher = AES.new(ESP_KEY_er, AES.MODE_CBC, esp_iv)
plaintext_padded = cipher.decrypt(esp_ciphertext)
result = re.findall(rb'\{(.*)\}', plaintext_padded)[0].decode()
print(f"Decrypted Data: {result}")
# 73047882172936819

浙公网安备 33010602011771号