← 首页 哈希算法

哈希算法

Hash

算法 分组长度Byte 摘要长度Byte 中间迭代值byte 支持消息最大长度比特 填充方式 参考标准
SM3 64 8*4=32 32 64/32*32 GB/T 32905-2016
MD5 64 4*4=16 16 64/32*32 RFC 1321
SHA1 64 5*4=20 20 64/32*32 NIST SP 800-57
SHA256 64 8*4=32 32 64/32*32 先添加1比特1,再填充k个比特0,使得消息比特长度对512去摸后的余数是448,再填充64位数据代表原始消息的比特长度 FIPS PUB 180-4
FIPS PUB 202
SHA224 64 7*4=28 32 64/32*32 同上 同上
SHA384 32*4=128 12*4=48 64 64/32*32 先添加1比特1,再填充k个比特0,使得消息比特长度对1024去摸后的余数是896,再填充128位数据代表原始消息的比特长度 同上
SHA512 32*4=128 16*4=64 64 128/32*32 同上 同上
SHA512_224 32*4=128 7*4=28 64 128/32*32 同上 同上
SHA512_256 32*4=128 8*4=32 64 128/32*32 同上 同上
SHA3_224 36*4=144 7*4=28 200 64 FIPS PUB 202
NIST SP 800-185
SHA3_256 34*4=136 8*4=32 200 64 同上
SHA3_384 26*4=104 12*4=48 200 64 同上
SHA3_512 18*4=72 16*4=64 200 64 同上
SHAKE128 168 任意长度 200 b=r+c=2000=1744+256 FIPS 202
SHAKE256 同SHA3_256 任意长度 200 b=r+c=2000=1488+512 FIPS 202

注:

  1. 以上hash都有起始IV(迭代值),其中sha3 iv是1600bit的0,摘要结果取最后迭代值最高有效位长度byte
  2. SHAKE(Secure HASH Algorithm and KECCAK),是Keccak哈希函数家族成员,属于可拓展输出函数(XOF,Extendable Output Function),源自NIST SHA-3标准,FIPS 202

在 SHA-3 中,c 表示容量(capacity),b 表示中间状态位宽。具体介绍如下:

  • c(容量):它是 SHA-3 算法海绵结构中的一个重要参数,其长度通常为输出长度的两倍。例如对于 SHA3-256,输出长度是 256 位,那么 c 通常为 512 位。c 的主要作用是增强算法的安全性,防止碰撞等攻击,容量越大,安全性理论上越高。

  • b(中间状态位宽):b=r+c,其中 r 是消息分组长度,也称为比特率。b 代表了轮函数 f 的输入输出位宽,在 SHA-3 标准中,b 的长度固定为 1600 位。无论具体的 SHA-3 变体(如 SHA3-224、SHA3-256 等)或可扩展输出函数(如 SHAKE128、SHAKE256)如何,其内部运算时的状态大小均为 1600 位,即 b 的值是固定的,通过调整 r 和 c 的值来适应不同的安全需求和输出要求。

第一原像攻击(First-Preimage Attack):给定一个哈希值 h,找到任意一个消息 m,使得哈希函数 H(m)=h。
第二原像攻击(Second-Preimage Attack):给定一个消息 m1,找到另一个不同的消息 m2(即 m2 != m1),使得 H(m1)=H(m2)。
碰撞攻击:找任意两个不同消息 m1 != m2 使 H(m1)=H(m2)(无前提的碰撞寻找)

PBKDF

《RFC7914》
《RFC 2898》——已废除
cryptolib pbkdf2:由RFC8018定义的一种基于口令的密钥派生算法

Password-Base Key Derivation Function 基于密码的密钥派生函数

原理:通过一个伪随机函数(例如HMAC函数),把明文和一个盐值作为输入参数,然后重复运算,并最终产生密钥。

//函数定义
DK = PBKDF(PRF, Password, Password_Len, Salt, Salt_Len, iter_num, DKLen)

DK //PBKDF算法产生的密钥
PRF //伪随机数,例如HASH_HMAC,输出长度为hLen结果
Password //原文密码
Salt //用于生成密钥加盐的盐值
iter_num //迭代运算次数
DKLen //期望得到的密钥的长度

具体流程:https://blog.csdn.net/HORHEART/article/details/119968850

公式:
PRF取自hmac
2.DK=T1||T2||...||Tdklen/hlen
3.Ti=F(Password,salt,c,i)
4.F(Password,salt,c,i)=U1⊕U2⊕...⊕Uc
5.Ui=PRF(Password, Salt||INT_32_BE(i))

KDF(ANSI X9-63-2011(R2017))

Key Derivation Function(kdf)

Input:
1.secret value, of bit length at most maxlength-32
2.keydatalen, bit len shall be less than(2^32-1)hashlen
3.(optional) A bit string ShareInfo that consists of some data shared by two entities

the total bit length of Z and ShareInfo must be at most maxhashlen-32

Actions:
1.Initiate a 32-bit, big endian bit string counter as 0x00000001
2.for i=1 to j=integer_up(keydatalen/hashlen):
    2.1 Compute Hash_i = H(Z||counter||Shareinfo)
    2.2 Increment counter
    2.3 Increment i
3. Let HHash_j denote Hash_j if keydatalen/hashlen is an integer, and let it denote the (keydatalen-(hashlen)_j) leftmost bits of Hash_j otherwise
4.Set KeyData = Hash_1||Hash_2||Hash_3||...||Hash_j

Output: The bit string KeyData of length keydatalen bits

X9.63 KDF-SHA256

计算流程示例

[SHA-256]
[shared secret length = 192]
[SharedInfo length = 128]
[key data length = 1024]

COUNT = 0
Z = 22518b10e70f2a3f243810ae3254139efbee04aa57c7af7d
SharedInfo = 75eef81aa3041e33b80971203d2c0c52
    Counter = 00000001
    Hash input 1 = 22518b10e70f2a3f243810ae3254139efbee04aa57c7af7d0000000175eef81aa3041e33b80971203d2c0c52 //Z||Counter||ShareInfo
    K1 = c498af77161cc59f2962b9a713e2b215152d139766ce34a776df11866a69bf2e
    Counter = 00000002
    Hash input 2 = 22518b10e70f2a3f243810ae3254139efbee04aa57c7af7d0000000275eef81aa3041e33b80971203d2c0c52
    K2 = 52a13d9c7c6fc878c50c5ea0bc7b00e0da2447cfd874f6cf92f30d0097111485
    Counter = 00000003
    Hash input 3 = 22518b10e70f2a3f243810ae3254139efbee04aa57c7af7d0000000375eef81aa3041e33b80971203d2c0c52
    K3 = 500c90c3af8b487872d04685d14c8d1dc8d7fa08beb0ce0ababc11f0bd496269
    Counter = 00000004
    Hash input 4 = 22518b10e70f2a3f243810ae3254139efbee04aa57c7af7d0000000475eef81aa3041e33b80971203d2c0c52
    K4 = 142d43525a78e5bc79a17f59676a5706dc54d54d4d1f0bd7e386128ec26afc21
key_data = c498af77161cc59f2962b9a713e2b215152d139766ce34a776df11866a69bf2e52a13d9c7c6fc878c50c5ea0bc7b00e0da2447cfd874f6cf92f30d0097111485500c90c3af8b487872d04685d14c8d1dc8d7fa08beb0ce0ababc11f0bd496269142d43525a78e5bc79a17f59676a5706dc54d54d4d1f0bd7e386128ec26afc21

PBKDF2

由RFC8018定义的一种基于口令的密钥派生算法.

公式:
PRF取自hmac
2.DK=T1||T2||...||Tdklen/hlen
3.Ti=F(Password,salt,c,i) //c为迭代次数,i为块索引号,F为密钥派生使用的方式,在此为hmac
4.F(Password,salt,c,i)=U1⊕U2⊕...⊕Uc //每轮迭代值进行异或,异或c轮
5.其中,U1=PRF(Password, Salt||INT_32_BE(i)) //INT_32_BE占用4字节,即最多2^32-1个分组
6.其中,U2=PRF(Password, U1) ... Uc=PRF(Password, Uc-1)

//demo pbkdf2-sha256-hmac
//key-password-16Byte
2C66FFF7B11A80DEA2F6B40C195D5004
//salt-4Byte
73616C74
//iter-4Byte
1
//keybytes-Byte
32
//pbkdf2-sha256-hmac
2221967a15e14c16e45f6334fcd5058f4698eed1b137a30029b92428c21301e4

//result
=hmac(key,  Salt||INT_32_BE(i))
=hmac(2C66FFF7B11A80DEA2F6B40C195D5004,73616C7400000001)
=2221967A15E14C16E45F6334FCD5058F4698EED1B137A30029B92428C21301E4


//demo pbkdf2-sha256-hmac
//key-password-16Byte
2C66FFF7B11A80DEA2F6B40C195D5004
//salt-4Byte
73616C74
//iter-4Byte
2
//keybytes-Byte
32
//pbkdf2-sha256-hmac
2221967a15e14c16e45f6334fcd5058f4698eed1b137a30029b92428c21301e4

//result
U1=hmac(key,  Salt||INT_32_BE(i))
=hmac(2C66FFF7B11A80DEA2F6B40C195D5004,73616C7400000001)
=2221967A15E14C16E45F6334FCD5058F4698EED1B137A30029B92428C21301E4
U2=hmac(key,  U1)
=hmac(2C66FFF7B11A80DEA2F6B40C195D5004, 2221967A15E14C16E45F6334FCD5058F4698EED1B137A30029B92428C21301E4)
=FF3F55577345ABEC90C5D7B9A151AC0B3E7363CC89FE893E533F172F0C36E4B2

result=U1 xor U2
=2221967A15E14C16E45F6334FCD5058F4698EED1B137A30029B92428C21301E4 xor FF3F55577345ABEC90C5D7B9A151AC0B3E7363CC89FE893E533F172F0C36E4B2
=DD1EC32D66A4E7FA749AB48D5D84A98478EB8D1D38C92A3E7A863307CE25E556

SipHash

没有被制定为NIST标准,被业界广泛认可和采纳的事实标准,学术论文链接:https://www.aumasson.jp/siphash/siphash.pdf

Siphash是一系列针对短消息输入的为随机函数,主要应用程序包括网络身份校验和哈希表查询,抵抗哈希洪泛拒绝服务攻击

SipHash-c-d

含义:

c = 每处理一个 8 字节消息块时执行的压缩轮数
d = 最终输出 MAC 前执行的 finalization 轮数

SipHash_4_8

输入:
密钥:16字节
消息:任意长度消息(含空消息)
输出:
mac:8字节

特点:较慢(约为SipHash_2_4的50%),更高安全性(对安全性要求更高的场景)

SipHash_2_4

输入:
密钥:16字节
消息:任意长度消息(含空消息)
输出:
mac:8字节

特点:性能最快,足够安全(大多数hash表场景使用)

总结:

  1. siphash输入无消息长度限制,支持空消息,设计初衷为短输入

HKDF

HKDF 全称 HMAC-based Extract-and-Expand Key Derivation Function,由 RFC 5869 定义

设计背景
提取:在许多应用中,输入的密钥材料不一定均匀分布,攻击者可嫩掌握部分信息,提取阶段的目的是将输入密钥材料可能分散的熵,集中到一个短的、但加密性强的伪随机密钥中。
拓展:将伪随机密钥拓展到指定的长度

输入:
hash,哈希算法(SHA256/384/512)
salt,可选的随机盐(不提供默认为全0字符串,长度等于hash的输出长度)
info,上下文,可为空
ikm,密钥材料,非hmac key

输出:
PRK,长度等于hash的输出长度

注:

  1. 对于salt,理想情况下是长度为HashLen的随机(或伪随机)字符串,即使质量较低salt,也可能对安全性做出重大贡献
  2. 对于info,可以是算法标识符,使用者标识符,协议编号等等,可以容纳密钥拓展部分的额外输入比如长度信息L

Extract

​ 输入:
​ salt,【optional】盐值,optinal,为空时,默认为Hash摘要长度的零字符串
​ IKM,密钥材料
​ 输出:
​ PRK,伪随机密钥,Hash摘要长度,PRK=HMAC(salt, IKM)

【Extract】
PRK = HMAC-Hash(salt, IKM)

Expand

​ 输入:
​ PRK,伪随机密钥,至少是Hash摘要长度,通常取Extract的输出
​ info,【optional】上下文和应用程序指定的信息(可以是零长度字符串)
​ L,输出密钥的字节长度,<=255*Hash摘要长度,即最大255个分组长度
​ 输出:
​ OKM,输出密钥材料(L字节)

【Expand】
N=ceil(L/HashLen)
T = T(1) || T(2) || ... || T(N)
OKM = first L Bytes of T

T(0) = 空字符串,长度为0
T(1) = HMAC-Hash(PRK, T(0) || info || 0x01)
T(2) = HMAC-Hash(PRK, T(1) || info || 0x02)
...
T(N) = HMAC-Hash(PRK, T(N-1) || info || N)

示例Demo

//IKM
0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
//salt
000102030405060708090a0b0c
//info
f0f1f2f3f4f5f6f7f8f9

//Extract: PRK = HMAC-Hash(salt, IKM)
HMAC-Sha256(key,msg)=(000102030405060708090a0b0c, 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b)
=077709362C2E32DF0DDC3F0DC47BBA6390B6C73BB50F9C3122EC844AD7C2B3E5

//Expand: OKM=42B
T(0) = NULL
T(1) = HMAC-Sha256(PRK, T(0) || info || 0x01)=(077709362C2E32DF0DDC3F0DC47BBA6390B6C73BB50F9C3122EC844AD7C2B3E5,f0f1f2f3f4f5f6f7f8f9||01)
=3CB25F25FAACD57A90434F64D0362F2A2D2D0A90CF1A5A4C5DB02D56ECC4C5BF
T(2) = HMAC-Sha256(PRK, T(1) || info || 0x02)=(077709362C2E32DF0DDC3F0DC47BBA6390B6C73BB50F9C3122EC844AD7C2B3E5,3CB25F25FAACD57A90434F64D0362F2A2D2D0A90CF1A5A4C5DB02D56ECC4C5BF||f0f1f2f3f4f5f6f7f8f9||01)
=34007208D5B887185865B4B0A85A993B89B9B65683D60F0106D28FFF039D0B6F //左边截取(42-32)=10B

//OKM
=T(1)||T(2)
=3CB25F25FAACD57A90434F64D0362F2A2D2D0A90CF1A5A4C5DB02D56ECC4C5BF||34007208D5B887185865

注:标准中未提及HKDF限定在哪些hash算法上,从标准协议上看,适用于md5/sha1/sha2/sha3这类有固定输出长度的hash算法,不适用于shake128/256这类任意长度输出的算法上