• HMAC(Hash-based Message Authentication Code)实现原理


    1、HMAC 概念

    HMAC(Hash-based Message Authentication Code)基于 hash 的消息验证码,是 安全通信中必要的组成部件。

    主要是 防止消息被篡改,和对称加密一起保护数据通信的 完整性。

    参考HMAC实现规范,基于的 Hash 算法可以是 md5,sha1,sha-2(sha256,sha385,sha512)等;

    在不考虑 hash算法具体实现的情况下,其实现原理图如下:


    1)密钥填充

          如果密钥比Hash函数的分组长度(block_size)要长,则要用Hash函数求出密钥的散列值,然后将这个散列值用作HMAC的密钥。

          如果密钥比分组长度要短,就在末尾填充0,直到其长度达到单向散列函数的分组长度为止。

          注:散列值长度digest_size 一般都会短于 分组长度block_size,因此,实际上 长于分组长度计算散列值之后,仍然需要在尾部填0。

    2)填充后的密钥与ipad的XOR 将填充后的密钥,与被称为ipad的比特序列进行XOR运算。

         ipad是将00110110这一比特序列(即16进制的36) 不断循环反复直到达到分组长度所形成的比特序列。其中:ipad的i 是inner的意思。

         XOR运算所得到的值,就是一个和单向散列函数的分组长度相同,且和密钥相关的比特序列。这里我们将这个比特序列成为ipadkey。

    3)与消息结合 将ipadkey与消息进行组合,也就是将和密钥相关的比特序列(ipadkey)附加在消息的开头

    4)计算散列值 将步骤3的结果输入单向散列函数,并计算出散列值。

    5)填充后的密钥与opad的XOR 将填充后的密钥与被称为opad的比特序列进行XOR运算。

        opad是将01011100这一比特序列(即十六进制5C)不断循环反复直到达到分组长度所形成的比特序列,其中opad的o是outer的意思。

        XOR运算所得到的结果也是一个和单向散列函数的分组长度相同,且和密钥相关的比特序列。这里我们将这个比特序列称为opadkey。

    6)与散列值组合 opadkey附加在步骤4的散列值前面。

    7)计算散列值 将步骤6的结果输入单向散列函数,并计算出散列值。这个值就是最终的MAC值。

    2、HMAC Python hmac库实现

    在 Python 中, 直接提供了 hmac 库实现相关操作。

    如下所示,是yvivid基于 hmac库的一个实现。

    更多hmac库的使用,请参考 python doc。

    3、HMAC 的 笨办法( 仅利用Python hashlib库实现)

    基于HMAC的原理,是否可以在已有 hash算法上,自己实现 HMAC算法。

    下面是 yvivid 在 Python上,基于 hashlib库(hash算法)的基础上,HMAC自行编码的一个实现的。

    1)由于 需要 XOR是实现,因此 使用了 int 和 bytes的转换,写的不是很简洁(逻辑电路的思维)。

    2) i_key_pad 和 o_key_pad 实际上展开到 block_size长度了。

    注:其实 在自己实现时,还没注意到 python的 hmac 库,结果是自己摸索 和 openssl输出进行对比分析的。

    大家可自己分析 Python36Libhmac.py 的代码。部分处理比我写的简洁,使用了 bytes的 ljust,translate特性。

    但只有自己实现 才能感觉到其真实的原理。

    4、易混淆的概念

    1)填充阶段,尤其是 分组长度block_size 和 摘要(散列值)长度digest_size,

    描述的概念比较混淆,导致编写代码过程走了弯路。

    分组长度block_size 是 Hash 处理输入数据时,是按照 block_size大小来分块(block)处理的。

    摘要(散列值)长度digest_size 是 Hash完成后,输出的 摘要(散列值)字节长度。 

    2)XOR 阶段,yvivid的实现采用了并行的思路,基于整数 的异或操作(python语法的 ^)。

    3)Python 语法方面,对于 bytes 还是不熟悉,需要进一步学习。

    附录:常用散列算法的分组长度和摘要长度。

    单向散列函数 分组长度 block_size 摘要长度digest_size
    MD5 64 Bytes (512bit) 16 Bytes (128bit)
    SHA1 64 Bytes (512bit) 20 Bytes (160bit)
    SHA256 64 Bytes (512bit) 32 Bytes (256bit)
    SHA512 128 Bytes (1024bit)

    64 Bytes (512bit)

     

     

     

    原创声明:

    HMAC原理是公共的,但 python代码实现(尤其是 基于hashlib下 自己的编写),是基于本人在 python 实现,转载请声明出处。

    https://www.cnblogs.com/yvivid/p/hmac_basic.html 

    参考文献:

    1) 图解密码技术(第3版) ,[日]结城浩;

        学习笔记:http://flamepeak.com/2016/11/23/tu-jie-mi-ma-ji-shu-authentication20161123/

    2) Python 3.6.8 documentation / Library Reference

         hashlib — Secure hashes and message digests

         hmac — Keyed-Hashing for Message Authentication

    3)扩展阅读(文章写完后发现的):

        HMAC算法原理:https://www.cnblogs.com/shoshana-kong/p/11497676.html

  • 相关阅读:
    Spring总结四:IOC和DI 注解方式
    Spring总结二:IOC(控制反转)xml方式
    Spring总结一:Srping快速入门
    TCP UDP HTTP 的关系和区别
    sql 一些偶尔会用到的写法和函数 不定时更新
    AngularJS分层开发
    AngularJS入门
    url和uri的区别
    MyBatis总结八:缓存介绍(一级缓存,二级缓存)
    Javascript 中 == 与=== 对比
  • 原文地址:https://www.cnblogs.com/yvivid/p/hmac_basic.html
Copyright © 2020-2023  润新知