如何在不使用 hmac 库的情况下在 python 中实现 HMAC?

How to implement HMAC in python without using the hmac library?

我想根据 RFC 2104 的定义使用 SHA-1 实现 hmac 算法。代码是 运行 但结果与 test-vectors from RFC 不同。我不确定我是否正确加载了值(字符串到十六进制,还是字符串到字节?)。

作为模板,我使用了 wikipedia

中的伪代码

我不确定 'blocksize' 和 'output size' 这两个词。在维基百科的代码中,outputsize 是输入值之一,但从未使用过。

到目前为止,这是我的代码: 首先,我设置了一个散列函数,然后将我的输入字符串(键和消息)转换为十六进制值。下一步是查看密钥是否已被散列或填充为零。接下来,我将键中的单个字符与这些值进行异或运算(我不知道它们来自哪里,但它们在每个示例中都没有任何评论)。最后但并非最不重要的一点是,我正在组合一个内部字符串(I_key_pad + 消息)并对其进行哈希处理,这会导致一个外部字符串与外部垫组合并再次对其进行哈希处理。

    import hashlib
    from functools import reduce
    
    
    def hmac(key, message, hashfunc):
        hasher = hashlib.sha1
        blocksize = 40
        message = toHex(message) #is this right?
        key = toHex(key)
        #alternative: loading values as bytes
        #message = bytes(message, 'utf-8')
        #key = bytes(key, 'utf-8')
        if len(key) > blocksize:
            key = hasher(key)
        else:
            #key = key.ljust(blocksize, '0') #filling from right to left
            #key = key.ljust(blocksize, b'[=11=]') #same as above but for bytes
            key = pad(key, blocksize)  #filling from left to right
    
        val1 = 0x5c 
        val2 = 0x36 
    
        i = 0
        o_key_pad = ""
        i_key_pad = ""
        while i < blocksize:
            o_key_pad += str(ord(key[i]) ^ val1)
            i_key_pad += str(ord(key[i]) ^ val2)
    
            i += 1
    
        tmp_string = str(i_key_pad) + str(message)
        tmp_string = tmp_string.encode()
        inner_hash = hasher(tmp_string).hexdigest()
        fullstring = str(o_key_pad) + inner_hash
        fullstring = fullstring.encode()
        fullstring = hasher(fullstring).hexdigest()
        print(fullstring)
    
    
    def pad(key, blocksize):
        key = str(key)
        while len(key) < blocksize:
            key = '0' + key
        key = key
        return key
    
    
    def toHex(s):
        lst = []
        for ch in s:
            hv = hex(ord(ch)).replace('0x', '')
            if len(hv) == 1:
                hv = '0' + hv
            lst.append(hv)
    
        return reduce(lambda x, y: x + y, lst)
    
    
    
    def main():
        while (1):
            key = input("key = ")
            message = input("message = ")
            hash = input("hash (0: SHA-256, 1: SHA-1) = ")
            hmac(key, message, hash)
    
    
    if __name__ == "__main__":
        main()

我不理解您代码中的所有步骤,但这里有一个简短的示例,显示仅使用 hashlib.sha1 的 HMAC-SHA1,以及辅助函数 xor

import hashlib

def xor(x, y):
    return bytes(x[i] ^ y[i] for i in range(min(len(x), len(y))))

def hmac_sha1(key_K, data):
    if len(key_K) > 64:
        raise ValueError('The key must be <= 64 bytes in length')
    padded_K = key_K + b'\x00' * (64 - len(key_K))
    ipad = b'\x36' * 64
    opad = b'\x5c' * 64
    h_inner = hashlib.sha1(xor(padded_K, ipad))
    h_inner.update(data)
    h_outer = hashlib.sha1(xor(padded_K, opad))
    h_outer.update(h_inner.digest())
    return h_outer.digest()


def do_tests():
    # test 1
    k = b'\x0b' * 20
    data = b"Hi There"
    result = hmac_sha1(k, data)
    print(result.hex())
    # add tests as desired