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

时间:2019-05-09 15:49:41

标签: python hash hmac

我想通过RFC 2104中的定义用SHA-1实现hmac算法。代码正在运行,但是结果与test-vectors from RFC不同。我不确定是否要正确加载值(从字符串转换为十六进制,还是从字符串转换为字节?)。

作为模板,我使用了wikipedia的伪代码

我不确定术语“块大小”和“输出大小”。在Wikipedia的代码中,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'\0') #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()

1 个答案:

答案 0 :(得分:0)

我不了解您代码中的所有步骤,但这是一个简短的示例,显示仅使用hashlib.sha1和辅助功能xor的HMAC-SHA1。

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