1. 综述
概况
GM/T 0091-2020《基于口令的密钥派生规范》应该是源自PKCS#5 V2.1(Password-Based Cryptography Standard)。
GM/T 0091-2020主要讲述了如下几个方面的内容:
- 基于口令的密钥导出函数PBKDF。
- 采用的是PKCS#5 V2.1的PBKDF2
- 基于口令的加密方案
- 用PBKDF导出密钥进行加密。
- 采用的是PKCS#5 V2.1 PBES2:PBKDF2 + CBC-Pad加密
- 基于口令的消息认证方案
- 用PBKDF导出密钥计算MAC。
- 采用的是PKCS#5 V2.1 PBMAC1:PBKDF2 + HMAC
主要涉及如下几个参数
- P:口令,任意长度的字符串(通常为ASCII 或UTF-8字符)。
- S:盐值,不保密,增加密文多变性,要求是不小于64比特的随机串。
- c:迭代次数,口令导出密钥时的迭代次数,要求不小于1024,以适当增加使用者负担,但可以显著增加攻击者难度。
- DK:导出密钥。
- dkLen:导出密钥的字节长度。
- hLen:杂凑函数的输出字节长度。
其它:
- 第5章描述了相关OID的定义。本文略。
- 附录B和C为规范性附录,描述了ASN.1的语法和结构定义。本文略。
对比PKCS#5 V2.1
- PKCS#5 V2.1:最全,两个PBKDF方案(一个为兼容早期V1.5版本,不安全;另一个更安全,推荐),两个PBES方案,一个PBMAC方案。
- GM/T 0091-2012:挑选PKCS#5的优选方案PBKDF2系列——PBKDF2 + PBES2 + PBMAC1方案;额外补充OID定义、ASN.1语法和结构定义。
表1标准的对比
PKCS#5 v2.1 | GM/T 0091 | |
主体机构 | RSA实验室 | 密标委 |
发布时间 | 2006年 | 2020年 |
密钥派生 | PBKDF1 (兼容V1.5,安全性差) PBKDF2 (推荐) | 仅PBKDF2 |
加密方案 | PBES1 (兼容V1.5,用PBKDF1) PBES2 (推荐;使用PBKDF2) | PBES2 (使用PBKDF2) |
MAC方案 | PBMAC1 (使用PBKDF2) | PBMAC1 (使用PBKDF2) |
备注 | 采用PBKDF2系列 |
表2.2 PBKDF参数对比
PKCS#5 v2.1 | GM/T 0091 | |
PRF | PBKDF1: HASH(MD2、MD5、SHA-1) PBKDF2: 给出实例HMAC-SHA1、HMAC-SHA2 | 无PBKDF1 PBKDF2: 给出一个实例,为HMAC-SM3 |
盐值salt | >= 64比特 | >= 64比特 |
迭代次数c | >= 1000 | >= 1024 |
备注 | 仅使用PBKDF2 |
表2.3 PBES参数对比
PKCS#5 v2.1 | GM/T 0091 | |
基础PBKDF | PBES1:使用PBKDF1 PBES2:使用PBKDF2 | 无PBES1:—— PBES2:使用PBKDF2 |
基础 加密方案 | PBES1:实例DES / RC2 – CBC PBES2:实例AES-CBC-pad | 无PBES1:—— PBES2:实例SM4-CBC-pad |
盐值salt | >= 64比特 | >= 64比特 |
迭代次数c | >= 1000 | >= 1024 |
备注 | 仅使用PBES2 |
表2.4 PBMAC参数对比
PKCS#5 v2.1 | GM/T 0091 | |
基础PBKDF | 使用PBKDF2 | 使用PBKDF2 |
基础 MAC方案 | 实例HMAC-SHA1或HMAC-SHA2 | 实例HMAC-SM3 |
盐值salt | >= 64比特 | >= 64比特 |
迭代次数c | >= 1000 | >= 1024 |
备注 | 仅使用PBES2 |
附录A. 辅助技术
A.1 Salt值与迭代次数
salt
目的:
- 攻击者无法建立一个普适性的彩虹表来破解所有用户的口令。salt值不用保密。由于不同用户有不同的salt值,攻击者只能基于特定用户获取salt值,建立基于该salt值的彩虹表对该用户实施攻击;而若要对所有用户都建立这样的彩虹表,攻击者无法办到。
建议:(见附录A.1.1)
- salt可以包括随机生成部分和非随机生成部分
- 盐值长度不少于64比特。
- 非随机生成部分应含有导出密钥的长度、用途等相关信息。
迭代次数
目的:
- 增加攻击时间,因为增加了生成每个密钥的时间。
建议:
- 规定迭代次数不小于1024。
- 既要增加攻击者穷举搜索时间,又不要对应用有明显影响(即用户/应用正确生成密钥的时间不能太长)。
A.2-A.5 PRF+基础加密机制+基础MAC机制
机制 | 本标准给的实例 |
PRF | HMAC-SM3 |
加密机制 | SM4-CBC-pad |
MAC机制 | HMAC-SM3 |
SM4-CBC-pad的填充方式:在消息M之后填充x个字节,每个字节的值都是x,其中
x = 16 - ( ||M|| mod 16)
6. 基于口令的密钥导出函数
采用PKCS#5 v2.1的PBKDF2方案,如下表。
表5.1 基于口令的密钥导出函数PBKDF (hLen为HASH函数的输出长度)
项目 | PBKDF |
PRF函数 | 实例为HMAC-SM3 |
导出密钥长度 | ≤ (232 – 1) × hLen |
备注 | 为PKCS#5 v2.1的PBKDF2函数 |
PBKDF方案
函数:DK = PBKDF (P, S, c, dkLen)
功能:基于口令的密钥导出函数PBKDF
输入参数:
- P:口令,任意长度的字符串(通常为ASCII 或UTF-8字符)。
- S:盐值,无需保密,增加密文多变性。
- c:迭代次数,越大越好,规定不小于1024。
- dkLen:导出密钥DK的字节长度,≤ (2^32 – 1) × hLen。
内部参数:
- PRF:伪随机函数,标准给的实例是HMAC-SM3。
- hLen:杂凑函数的输出字节长度。
- MSB(M, L):获取数据串M的高L字节。
返回数据:
- DK:导出密钥。
执行步骤:
步骤1:若dkLen > (232 – 1) × hLen,返回错误标识。
步骤2:分组数n和最后一个分组的大小r是
。
说明:标准在这里的描述有笔误,应该是向上取整,而不是向下取整。
步骤3:for i = 1,2,..., n
3.1 Ti = 0,U0=S || Int(i)(Int(i)为i值的32比特大端表示)
3.2 for j = 1,2,..., c
3.2.1 Uj= PRF (P, Uj-1)
3.2.2 Ti = Ti⊕Uj
步骤4:返回DK= MSB(T1 || T2 || ... || Tn, dkLen)。
7. 基于口令的加密方案
基于口令的加密PBES方案,如下表。
表7.1 基于口令的加密方案PBES
PBES | |
使用的PBKDF | 本标准的PBKDF 即PKCS#5 V2.1的PBKDF2 |
基础密码算法 | 实例为SM4-CBC-Pad |
备注 | 为PKCS#5 V2.1的PBES2 |
SM4-CBC-pad的填充方式:在消息M之后填充x个字节,每个字节的值都是x,其中
x = 16 - ( ||M|| mod 16)
PBES加密方案
函数:C = PBES-ENC (M, P, S, c)
功能:基于口令的加密方案PBES的加密算法
输入参数:
- M:明文。
- P:口令,任意长度的字符串(通常为ASCII 或UTF-8字符)。
- S:盐值,规定不小于8字节。无需保密,增加密文多变性。
- c:迭代次数,越大越好,规定不小于1024。
内部参数:
- dkLen:导出密钥DK的字节长度。
返回数据:
- C:密文。
执行步骤:
步骤1:选择密码算法,比如实例为SM4-CBC-Pad。
步骤2:生成导出密钥,DK = PBKDF(P, S, c, dkLen)。
步骤3:加密:C = SM4-CBC-Pad.ENC(DK, M)。(IV自定义)
步骤4:输出密文C。
IV的说明:附录A解释到,初始化向量为16字节随机值,可以输入口令、盐值、迭代次数和密钥长度16字节,通过本标准定义的PBKDF派生出密钥作为初始化向量使用。
PBES方案的加解密流程图
PBES解密方案
函数:M = PBES-DEC (C, P, S, c)
功能:基于口令的加密方案PBES的解密算法
输入参数:
- C:密文。
- P:口令,任意长度的字符串(通常为ASCII 或UTF-8字符)。
- S:盐值,8字节。无需保密,增加密文多变性。
- c:迭代次数,越大越好,建议不小于1024。
内部参数:
- dkLen:导出密钥DK的字节长度。
返回数据:
- M:明文。
执行步骤:
步骤1:选择密码算法,标准给的实例为SM4-CBC-Pad。
步骤2:生成导出密钥,DK = PBKDF (P, S, c, dkLen)。
步骤3:解密:M = SM4-CBC-Pad.DEC(DK, C)。(IV自定义)
步骤4:输出明文M。
IV的说明:附录A解释到,初始化向量为16字节随机值,可以输入口令、盐值、迭代次数和密钥长度16字节,通过本标准定义的PBKDF派生出密钥作为初始化向量使用。
8. 基于口令的消息认证方案
基于口令的消息认证方案PBMAC,如下表。
表5.1 基于口令的消息认证方案
PBMAC | |
使用的PBKDF | 本标准的PBKDF 即PKCS#5 V2.1的PBKDF2 |
使用的密码算法 | 标准给的实例为HMAC-SM3 |
备注 | 为PKCS#5 V2.1的PBMAC1 |
MAC生成
函数:C = PBMAC-Generate (M, P, S, c dkLen)
功能:基于口令的消息鉴别码生成
输入参数:
- M:消息。
- P:口令,任意长度的字符串(通常为ASCII 或UTF-8字符)。
- S:盐值,8字节。无需保密,增加密文多变性。
- c:迭代次数,越大越好,建议不小于1024。
- dkLen:导出密钥的字节长度。
内部参数:
- MAC:标准给的实例为HMAC-SM3。
返回数据:
- T:消息检验码。
执行步骤:
步骤1:生成导出密钥,DK = PBKDF (P, S, c, dkLen)。
步骤2:生成消息检验码T = MAC(DK, M)。
步骤3:输出消息检验码T。
PBMAC1方案的流程图
MAC验证
函数:C = PBMAC-Verify (M, P, S, c, dkLen, T)
功能:基于口令消息鉴别码验证
输入参数:
- M:消息。
- P:口令,任意长度的字符串(通常为ASCII 或UTF-8字符)。
- S:盐值,8字节。无需保密,增加密文多变性。
- c:迭代次数,越大越好,建议不小于1024。
- dkLen:导出密钥的字节长度。
- T:消息检验码。
内部参数:
- MAC:标准给的实例为HMAC-SM3。
返回数据:
- ret:TRUE为验证通过,FALSE为验证失败。
执行步骤:
步骤1:生成导出密钥,DK = PBKDF (P, S, c, dkLen)。
步骤2:生成消息检验码T1= MAC(DK, M)。
步骤3:比较T1和T,两者相同则返回ret = TRUE,否则返回ret = FALSE。
流程图参见MAC的流程图。