Bootstrap

2024熵密杯初始题2

问题简要:

已知
counter = 0x7501E6EA
token = 0xF4CE927C79B616E8E8F7223828794EEDF9B16591AE572172572D51E135E0D21A
伪造出另一个可以通过验证的counter和token。

给出token生成及验证代码如下:

import binascii
from gmssl import sm3

# 读取HMAC key文件
def read_hmac_key(file_path):
    with open(file_path, 'rb') as f:
        hmac_key = f.read().strip()
    return hmac_key
    
# 生成token
def generate_token(hmac_key, counter):
    # 如果HMAC_KEY长度不足32字节,则在末尾补0,超过64字节则截断
    if len(hmac_key) < 32:
        hmac_key = hmac_key.ljust(32, b'\x00')
    elif len(hmac_key) > 32:
        hmac_key = hmac_key[:32]
    # 将计数器转换为字节表示
    counter_bytes = counter.to_bytes((counter.bit_length() + 7) // 8, 'big')
    # print("counter_bytes:", binascii.hexlify(counter_bytes))
    tobe_hashed = bytearray(hmac_key + counter_bytes)
    # print("tobe_hashed:", binascii.hexlify(tobe_hashed))
    # 使用SM3算法计算哈希值
    sm3_hash = sm3.sm3_hash(tobe_hashed)
    # 将SM3的哈希值转换为十六进制字符串作为token
    token = sm3_hash
    return token

current_counter = 0
def verify_token(hmac_key, counter, token):
    # 生成token
    generated_token = generate_token(hmac_key, counter)
    global current_counter
    # 比较生成的token和输入的token是否相同
    if generated_token == token:
        if counter & 0xFFFFFFFF > current_counter:
            current_counter = counter & 0xFFFFFFFF
            print("current_counter: ", hex(current_counter))
            return "Success"
        else:
            return "Error: counter must be increasing"
    else:
        return "Error: token not match"
        
# 假设HMAC key文件路径
hmac_key_file = 'hmac_key.txt'

# 假设计数器值
counter = 0x12345678

# 读取HMAC key
hmac_key = read_hmac_key(hmac_key_file)

# 生成token
token = generate_token(hmac_key, counter)
print("Generated token:", token)
print(verify_token(hmac_key, counter, token))

解题思路:
(1)token的生成算法为SM3,算法的输入包括2个部分:hmac_key||counter,其中hmac_key无法掌握,counter可自由选择。
(2)hmac_key为定长32字节,且以头部形式拼接counter。
(3)SM3算法分组长度64字节,输出长度32字节。
(4)通过以上分析,恰好符合Hash扩展长度攻击条件特征。
(之前以MD5算法为例介绍过Hash扩展长度攻击实例,有兴趣可以参考https://blog.csdn.net/ryanzzzzz/article/details/142325183 )

SM3算法的分组填充规则如下:
若输入长度L比特的消息,首先在消息末尾填充比特"1",然后填充k个"0",k满足L+k+1=448 mod 512的最小非负整数,最后填充64位的二进制串(L的二进制表示)。

开始构造新的counter:
(1)已掌握counter(7501E6EA),长度4字节
(2)0x80,长度1字节
(3)0x00 * 19,长度19字节
(4)0x0000000000000120,长度8字节
(5)0xAA * 4,长度4字节
即伪造的counter = 0x7501E6EA80000000000000000000000000000000000000000000000000000120AAAAAAAA

开始构造新的token:
(1)修改SM3算法代码,将IV值改为0xF4CE927C79B616E8E8F7223828794EEDF9B16591AE572172572D51E135E0D21A(也就是掌握的token)
(2)修改SM3算法代码,将消息长度len += 512
(3)运行修改后SM3杂凑算法,输入0xAAAAAAAA,输出即为对应的token。

;