本文档对PKCS#5 v2.1(基于口令的密码标准)介绍的基于口令的密钥生成函数、基于口令的加密方案、基于口令的消息认证MAC方案进行简要分析记录。其核心为基于口令的密钥生成函数即将口令(Password)通过密钥导出函数KDF后生成主密钥,用于加密方案和消息认证方案。NIST SP 800-132(基于口令的密钥导出)也是参考PKCS5来制定的。
PKCS5 v2.1主要讲述了三个方面的内容:
主要涉及如下几个参数
口令的选择建议参考如下文档。
有两个基于口令的密钥导出函数PBKDF方案,如下表。
表5.1 基于口令的密钥导出函数PBKDF1和PBKDF2对比
(hLen为HASH函数的输出长度)
项目 |
PBKDF1 |
PBKDF2 |
HASH函数 |
MD2 MD5 SHA-1 |
HMAC (HMAC底层使用SHA-1、SHA-224、SHA-256、SHA-384、SHA-512) |
导出密钥长度 |
≤ hLen |
≤ (232 – 1) × hLen |
使用 |
不推荐 仅兼容PKCS5 v1.5 |
推荐使用 |
对比NIST SP800-132 |
NIST SP800-132无PBKDF1函数 |
NIST SP800-132的PBKDF即PBKDF2函数 |
NIST SP800-132基于口令的密钥导出函数,是基于PKCS5得到。
说明:NIST SP800-132基于口令的密钥导出函数不涉及此PBKDF1函数。
函数:DK = PBKDF1 (P, S, c, dkLen)
功能:基于口令的密钥导出函数PBKDF1
输入参数:
内部参数:
返回数据:
执行步骤:
步骤1:若dkLen > hLen,返回错误标识。
步骤2:T0 = P || S。
步骤3:for i = 1,2,..., c,执行
3.1 Ti = Hash (Ti-1)
步骤4:返回导出密钥DK = MSB (dkLen, Tc)。
说明:NIST SP800-132基于口令的密钥导出函数PBKDF即此PBKDF2函数。
函数:DK = PBKDF2 (P, S, c, dkLen)
功能:基于口令的密钥导出函数PBKDF2
输入参数:
内部参数:
返回数据:
执行步骤:
步骤1:若dkLen > (232 – 1) × hLen,返回错误标识。
步骤2:分组数l和最后一个分组的大小r是
,
,
(即r = dkLen mod hLen,但模值为0时修正为hLen)。
步骤3:for i = 1,2,..., l
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 || ... || Tl , dkLen)。
备注:PKCS5 v2.1 PBKDF2和NIST SP800-132 PBKDF中使用的PRF都是HMAC,而NIST SP800-108(普通密钥导出函数,非基于口令的密钥导出函数)中使用的PRF可以是HMAC或CMAC。
有两个基于口令的加密PBES方案,如下表。
表5.1 基于口令的加密方案PBES1和PBES2对比
(hLen为HASH函数的输出长度)
项目 |
PBES1 |
PBES2 |
使用的PBKDF |
PBKDF1 |
PBKDF2 |
使用的密码算法 |
DES / RC2 – CBC模式 |
AES-CBC-Pad |
使用 |
不推荐 仅兼容PKCS5 v1.5 |
推荐使用 |
PBES中对消息填充的方案(EM = M || PS)为:
函数:C = PBES1-ENC (M, P, S, c)
功能:基于口令的加密方案PBES1的加密算法
输入参数:
内部参数:
返回数据:
执行步骤:
步骤1:生成导出密钥,DK = PBKDF1 (P, S, c, 16)。
步骤2:生成加密密钥K(DK的高8字节)和初始化向量IV(DK的低8字节):
K = DK[0...7], IV = DK[8...15] .
步骤3:生成编码后的消息(记T = 8-(#M mod 8))
EM = M || PS,
其中填充数据PS为连续T个字节且每个字节值均为T的字符串。
步骤4:CBC加密:C = ENC-CBC(K, IV, EM)。
步骤5:输出密文C。
函数:M = PBES1-DEC (C, P, S, c)
功能:基于口令的加密方案PBES1的解密算法
输入参数:
内部参数:
返回数据:
执行步骤:
步骤1:生成导出密钥,DK = PBKDF1 (P, S, c, 16)。
步骤2:生成加密密钥K(DK的高8字节)和初始化向量IV(DK的低8字节):
K = DK[0...7], IV = DK[8...15] .
步骤3:CBC解密:EM = DEC-CBC(K, IV, C)。
步骤4:解码生成编码后的消息
M || PS = EM。
记T 为EM最后一个字节的值,填充数据PS为连续T个字节且每个字节值均为T的字符串。如果PS不满足要求(1):T=1,2,...,8;(2)PS的T个字节的值都为T;则填充数据格式验证失败,返回错误。
步骤5:输出明文M。
PBES中对消息填充的方案(EM = M || PS)为:
函数:C = PBES2-ENC (M, P, S, c)
功能:基于口令的加密方案PBES2的加密算法
输入参数:
内部参数:
返回数据:
执行步骤:(PKCS#5未详细描述dkLen、K和IV的获取,相关内容为揣测)
步骤1:根据选择的密码算法AES-CBC-Pad确定dkLen(自定义)。
步骤2:生成导出密钥,DK = PBKDF2 (P, S, c, dkLen)。
步骤3:加密:C = AES-CBC-Pad.ENC(DK, M)。(涉及K和IV的划分,自定义)
步骤4:输出密文C。
根据PKCS#5的附录B.2.4 RC5-CBC-Pad 提到的RC5-128的填充方式,猜测AES-CBC-Pad的填充方式为:the padding string consists of 16-(||M||mod 16) octets each with value 16-(||M|| mod 16).
函数:M = PBES2-DEC (C, P, S, c)
功能:基于口令的加密方案PBES2的解密算法
输入参数:
内部参数:
返回数据:
执行步骤:(PKCS#5未详细描述dkLen、K和IV的获取,相关内容为揣测)
步骤1:根据选择的密码算法AES-CBC-Pad确定dkLen(自定义)。
步骤2:生成导出密钥,DK = PBKDF2 (P, S, c, dkLen)。
步骤3:解密:M = AES-CBC-Pad.DEC(DK, C)。(涉及K和IV的划分,自定义)
步骤4:输出明文M。
仅有一个基于口令的消息认证方案PBMAC1,如下表。
表5.1 基于口令的加密方案PBES1和PBES2对比
(hLen为HASH函数的输出长度)
项目 |
PBMAC1. |
使用的PBKDF |
PBKDF2 |
使用的密码算法 |
HMAC (底层HASH使用SHA1和SHA2) |
使用 |
推荐 |
函数:C = PBMAC1-Generate (M, P, S, c dkLen)
功能:基于口令的加密方案PBES1的加密算法
输入参数:
内部参数:
返回数据:
执行步骤:
步骤1:生成导出密钥,DK = PBKDF:2 (P, S, c, dkLen)。
步骤2:生成消息检验码T = MAC(DK, M)。
步骤3:输出消息检验码T。
函数:C = PBMAC1-Verify (M, P, S, c, dkLen, T)
功能:基于口令的加密方案PBES1的加密算法
输入参数:
内部参数:
返回数据:
执行步骤:
步骤1:生成导出密钥,DK = PBKDF2 (P, S, c, dkLen)。
步骤2:生成消息检验码T1= MAC(DK, M)。
步骤3:比较T1和T,两者相同则返回ret = TRUE,否则返回ret = FALSE。