HMAC 可以与任何哈希算法进行结合,在逆向的过程中,经常会遇到 HMAC-MD5/SHA1/SHA256 之类的,类似于哈希算法进行加盐,只不过这里叫做密钥,这里我用 HMAC-SHA1 来进行举例
流程
我选择数据的密钥(盐)的是 123456789abcdef ,数据是 123456
密钥处理
首先,需要对密钥进行预处理,使其长度与哈希函数内部块的大小一致
- 如果密钥长度大于哈希函数的块长度,则先对密钥进行哈希,用得到的哈希值作为新密钥
- 如果密钥长度小于哈希函数的块长度,则对密钥的末尾进行填充 0x00,使其长度等于块长度
1
2
3
4
| if len(key) > block_size:
key = hash(key) # 密钥过长,则哈希压缩
if len(key) < block_size:
key = key + b'\x00' * (block_size - len(key)) # 密钥过短,则补零
|
由于密钥 123456789abcdef (16 字节)小于 64 字节,需要对其进行填充,直至长度满足哈希算法的数据块长度
1
2
3
4
| K' = 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66
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
|
创建 ipad 和 opad
1
2
3
4
5
| ipad = bytes([0x36] * 64)
opad = bytes([0x5c] * 64)
ipad_key = bytes([key[i] ^ ipad[i] for i in range(64)])
opad_key = bytes([key[i] ^ opad[i] for i in range(64)])
|
生成长度是 64 的 0x36 和 0x5c,然后将填充过后的密钥逐字节与 ipad 和 opad 进行异或
1
2
3
4
5
6
7
8
9
10
11
12
13
| # ipad_key
07 04 05 02 03 00 01 0e 0f 57 54 55 52 53 50
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
# opad_key
6d 6e 6f 68 69 6a 6b 64 65 3d 3e 3f 38 39 3a
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
|
内部计算
1
2
3
4
5
| inner_input = ipad_key + message
inner_hash = hashlib.sha1(inner_input).digest()
outer_input = opad_key + inner_hash
outer_hash = hashlib.sha1(outer_input).digest().hex()
|
首先会将得到的 ipad_key 和密钥进行拼接,然后进行哈希运算
接着将得到的哈希值与 opad_key 进行拼接,最后进行哈希运算,就得到了最终的 hmac-sha1 加密的值了
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| import hashlib
def hmac_sha1(key, message):
# 如果密钥超过64个字节,先进行hash
if len(key) > 64:
key = hashlib.sha1(key).digest()
if len(key) < 64:
key += b'\x00' * (64 - len(key))
# 创建ipad和opad
ipad = bytes([0x36] * 64)
opad = bytes([0x5c] * 64)
ipad_key = bytes([key[i] ^ ipad[i] for i in range(64)])
opad_key = bytes([key[i] ^ opad[i] for i in range(64)])
# 内部计算
inner_input = ipad_key + message
inner_hash = hashlib.sha1(inner_input).digest()
outer_input = opad_key + inner_hash
outer_hash = hashlib.sha1(outer_input).digest().hex()
return outer_hash
if __name__ == '__main__':
key = b"123456789abcdef"
message = b"123456"
print(hmac_sha1(key, message))
|
算法倒没什么难的,需要注意的也就 0x36 和 0x5c 这两个数字,在 ida 中看到了要反应过来,貌似就没啥了