NIST HashDRBG的hash_df函数及实例化实现结果错误排查
HashDRBG实现错误点排查
你代码里有三个不符合NIST SP 800-90Ar1规范的问题,是输出不匹配的直接原因:
- 1字节0值定义错误
你定义的类属性zer = int_to_bytes(0)存在逻辑缺陷:当输入整数为0时,x.bit_length()返回0,计算得到的字节长度为0,最终zer是空字节串b'',完全不符合标准要求的「计算C时在V前拼接1字节0」的规则,导致C的计算输入从一开始就错了。 - no_of_bits_to_return编码不符合规范
标准明确要求hash_df步骤4.1中的no_of_bits_to_return必须以32位(4字节)大端比特串使用,你使用的动态长度int_to_bytes函数会根据数值大小返回可变长度的字节,比如本次测试用到的440会被编码为2字节b'\x01\xb8',而非要求的4字节b'\x00\x00\x01\xb8',哈希输入不匹配自然得到错误结果。 - counter编码不规范
标准要求counter为固定8位(1字节)无符号整数,你当前用动态长度编码虽然在本次测试场景(counter最多到2)下不会出问题,但后续如果需要更长的返回比特数,counter超过255时会出现编码长度错误,不符合规范要求。
修正代码参考
import hashlib def ceildiv(a, b): return -(a // -b) class hashDrbg: V = b'' C = b'' reseed_counter = 0 # 直接定义固定1字节的0,避免动态计算出错 zer = b'\x00' def __init__(self): pass def hash_df(self, input_string, no_of_bits_to_return): temp = b'' outlen = 256 # SHA-256的输出比特长度 length = ceildiv(no_of_bits_to_return, outlen) # 固定将返回比特数编码为4字节大端,符合标准要求 bits_len_bytes = no_of_bits_to_return.to_bytes(4, 'big') for i in range(1, length + 1): # counter固定编码为1字节大端 counter = i.to_bytes(1, 'big') m_digest = hashlib.sha256() m_digest.update(counter + bits_len_bytes + input_string) temp += m_digest.digest() # 取最左侧no_of_bits_to_return比特 requested_bits = temp[:no_of_bits_to_return // 8] return requested_bits def instantiate(self, entropy_hex, nonce_hex, personalization_hex, security_strength): seed_material = bytes.fromhex(entropy_hex + nonce_hex + personalization_hex) seed = self.hash_df(seed_material, 440) self.V = seed self.C = self.hash_df(self.zer + self.V, 440) self.reseed_counter = 1
使用你给出的测试向量运行修正后的代码,就能得到预期的V和C值。
内容的提问来源于stack exchange,提问作者factor2
相关产品推荐
相关产品推荐

