安卓逆向-HmacMd5算法

下雨天
10月23日发布 /正在检测是否收录...

hmacmd5算法

1. 简介

  • HMAC-MD5算法是一种基于MD5散列函数和密钥的消息认证码算法,它通过结合密钥和消息内容来生成一个长度为128位的哈希值,用于验证消息的完整性和身份;
  • 与普通的 MD5 哈希算法不同,HMAC-MD5 在计算过程中使用了一个密钥,使得攻击者无法仅凭猜测数据本身来伪造消息的认证码;
  • 如果密钥太长,它需要被压缩;如果太短,它需要被填充到特定长度;
  • 总结就是:两次加盐,两次哈希;

2. 算法流程

  • 输入:

    • 消息(Message):需要进行验证的消息数据;
    • 密钥(Key):用于生成消息认证码的密钥;
  • 输出:

    • HMAC-MD5值:一个128位的签名值(32个十六进制位的数据),用于验证消息的完整性和真实性;
  • 步骤详述:
  • 步骤 1:密钥准备

    • 如果密钥长度大于MD5的块大小(64字节),则先对密钥执行一次MD5哈希运算,生成一个16字节(128位)的密钥摘要(K'),然后再进行填充;
    • 如果密钥长度小于64字节,则用零字节(0x00)填充密钥至64字节;
    • 如果密钥长度正好是64字节,则直接使用密钥;
  • 步骤2:异或0x36,也叫ipad

    • 逐字节异或得到扩展密钥1;0x36的十进制是54;这里的ipad不是一个数据,应该是与key相同长度的数组;
  • 步骤3:异或0x5c,也叫opad

    • 逐字节异或得到扩展密钥2;0x54的十进制是92;
  • 步骤5:第一次加盐

    • 扩展密钥1与明文拼接;
  • 步骤6:第一次哈希

    • 加盐的结果进行哈希;
  • 步骤7:第二次加盐

    • 扩展密钥2与第一次哈希的结果拼接;
  • 步骤8:第二次哈希

    • 将上述拼接的结果进行哈希;
  • 总结:

    • HMAC(K, M) = H((K' ⊕ opad) || H((K' ⊕ ipad) || M))
    • K:密钥
    • M:明文
    • H:哈希函数
    • K':扩展密钥
    • ⊕:逐字节异或
    • opad:0x5c
    • ipad:0x36
    • || :拼接
  • 算法流程简述如上,以一个简单的示例来看整体的流程;

3. 完整示例

  • 以sana为明文,xiayutian为key,进行整个流程的介绍;
  • 参考公式: H((K' ⊕ opad) || H((K' ⊕ ipad) || M))

3.1 密钥扩展

  • 首先进行密钥扩展,xiayutian的十六进制表示为:
78 69 61 79 75 74 69 61 6e
  • 长度不够512个比特位,所以需要进行填充,填充后的结果如下:
78 69 61 79 75 74 69 61 6E 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
  • 一共是55个零字节,加上原有的数据就是64个字节;

3.2 与0x36异或

  • 随后密钥与0x36(ipad)逐字节异或,这里的0x36不是单独的一个数据,而是64个,毕竟要一一对应;
  • 得到异或的结果,这就对应着第一个扩展密钥,也叫扩展密钥1;
4E 5F 57 4F 43 42 5F 57 58 36 36 36 36 36 36 36 
36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 
36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 
36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 

3.3 第一次加盐

  • 然后拼接明文,将明文放在最后,这就是第一次加盐;
  • 明文sana的十六进制:73 61 6e 61
拼接后数据(68字节):
4E 5F 57 4F 43 42 5F 57 58 36 36 36 36 36 36 36 
36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 
36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 
36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 
73 61 6E 61 

3.4 第一次哈希

  • 将这个结果做一个md5加密,这就是第一次哈希;
fa23080448b15547fe4b2a19226cf9b7

3.5 与0x5c异或

  • 获取扩展密钥2,也就是密钥与opad(0x5c)逐字节异或;
24 35 3D 25 29 28 35 3D 32 5C 5C 5C 5C 5C 5C 5C 
5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 
5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 
5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 

3.6 第二次加盐

  • 将扩展密钥2与第一步哈希的结果拼接起来,这就是第二次加盐;
24 35 3D 25 29 28 35 3D 32 5C 5C 5C 5C 5C 5C 5C 
5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 
5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 
5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 5C 
fa 23 08 04 48 b1 55 47 fe 4b 2a 19 22 6c f9 b7 

3.7 第二次哈希

  • 将第二次加盐的结果进行哈希,这就是第二次哈希;
3d38802f21ef45a3eb05524f504810bc
  • 做一下结果对比;

image-20250130004823879

  • 结果是没问题的,主要的流程就是两次加盐两次哈希;

4. 总结

  • 首先是流程:HMAC(K, M) = H((K' ⊕ opad) || H((K' ⊕ ipad) || M))
  • 两次加盐、两次哈希;也有可能是三次哈希,密钥如果超过64字节则需要先哈希再填充;
  • 算法的特征就是0x36和0x5c,也有可能是十进制的形式,54和92;
  • 魔改的点一般在于载体哈希函数,并不去魔改两次加盐两次哈希这个流程,但也说不好;

5. 代码实现

import hmac
import hashlib


def hmac_md5(key, message):
    # 将 key 和 message 转换为字节类型
    key = bytes(key, 'utf-8')
    message = bytes(message, 'utf-8')

    # 计算 HMAC-MD5
    hmac_md5_hash = hmac.new(key, message, hashlib.md5).hexdigest()

    return hmac_md5_hash


# 示例使用
key = "xiayutian"
message = "sana"
result = hmac_md5(key, message)
print("HMAC-MD5:", result)
# 3d38802f21ef45a3eb05524f504810bc
© 版权声明
THE END
喜欢就支持一下吧
点赞 0 分享 收藏
评论 抢沙发
OωO
取消