PKCS#5研究(合)

摘要:本文档对PKCS#5 v2.1(基于口令的密码标准)介绍的基于口令的密钥生成函数、基于口令的加密方案、基于口令的消息认证MAC方案进行简要分析记录。其核心为基于口令的密钥生成函数即将口令(Password)通过密钥导出函数KDF后生成主密钥,用于加密方案和消息认证方案。NIST SP 800-132(基于口令的密钥导出)也是参考PKCS5来制定的。

 

关键词:密码模块,口令,密钥,密码算法,密钥导出函数,加密,MAC。

 

1. 综述

PKCS5 v2.1主要讲述了三个方面的内容:

  • 基于口令的密钥导出函数PBKDF
    • PBKDF1:仅兼容PKCS5 v1.5用,使用HASH(MD2、MD5、SHA-1),导出密钥≤ hLen
    • PBKDF2:推荐使用,使用HMAC,导出密钥可很长。方案同NIST SP800-132PBKDF
  • 基于口令的加密方案,用PBKDF导出密钥进行加密。
    • PBES1:仅兼容PKCS5 v1.5,PBKDF1 + DES / RC2 – CBC
    • PBES2:推荐使用,PBKDF2 + AES-CBC-Pad
  • 基于口令的消息认证方案,用PBKDF导出密钥计算MAC。

 

主要涉及如下几个参数

  • P:口令,任意长度的字符串(通常为ASCII 或UTF-8字符)。
  • S:盐值,无需保密,增加密文多变性,可为口令索引值或伪随机数等。
  • c:迭代次数,口令导出密钥时的迭代次数,建议不小于1000,以适当增加使用者负担,但可以显著增加攻击者难度。
  • DK:导出密钥。
  • dkLen:导出密钥的字节长度。
  • hLen:杂凑函数的输出字节长度。

 

口令的选择建议参考如下文档。

  1. NIST SP 800-63: Electronic Authentication Guideline: Recommendations of the National Institute of Standards and Technology, Appendix A, April 2006.

 

5. 基于口令的密钥导出函数

有两个基于口令的密钥导出函数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得到。

5.1 PBKDF1

说明:NIST SP800-132基于口令的密钥导出函数不涉及此PBKDF1函数。

函数:DK = PBKDF1 (P, S, c, dkLen)

功能:基于口令的密钥导出函数PBKDF1

输入参数:

  1. P:口令,任意长度的字符串(通常为ASCII 或UTF-8字符)。
  2. S:盐值,无需保密,增加密文多变性。
  3. c:迭代次数,越大越好,建议不小于1000。
  4. dkLen:导出密钥DK的字节长度,≤ hLen

内部参数:

  1. HASH:杂凑函数(为MD2、MD5、SHA-1)。
  2. hLen:杂凑函数的输出字节长度。
  3. MSB(L, M):获取数据串M的高L字节。

返回数据:

  1. DK:导出密钥。

执行步骤:

步骤1:若dkLen > hLen,返回错误标识。

步骤2:T0 = P || S

步骤3:for i = 1,2,..., c,执行

      3.1        Ti = Hash (Ti-1)

步骤4:返回导出密钥DK = MSB (dkLen, Tc)。

5.2 PBKDF2

说明:NIST SP800-132基于口令的密钥导出函数PBKDF即此PBKDF2函数。

函数:DK = PBKDF2 (P, S, c, dkLen)

功能:基于口令的密钥导出函数PBKDF2

输入参数:

  1. P:口令,任意长度的字符串(通常为ASCII 或UTF-8字符)。
  2. S:盐值,无需保密,增加密文多变性。
  3. c:迭代次数,越大越好,建议不小于1000。
  4. dkLen:导出密钥DK的字节长度,≤ (232 – 1) × hLen

内部参数:

  1. PRF:伪随机函数,可以是HMAC-SHA-1、HMAC-SHA-224、HMAC-SHA-256、HMAC-SHA-384、HMAC-SHA-512。
  2. hLen:杂凑函数的输出字节长度。
  3. MSB(L, M):获取数据串M的高L字节。

返回数据:

  1. DK:导出密钥。

执行步骤:

步骤1:若dkLen > (232 – 1) × hLen,返回错误标识。

步骤2:分组数l和最后一个分组的大小r

h = \left \lceil dkLen/hLen \right \rceil

r = dkLen -(l-1)hlen

(即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 = TiUj

步骤4:返回DK= MSB(T1 || T2 || ... || Tl , dkLen)。

备注:PKCS5 v2.1 PBKDF2NIST SP800-132 PBKDF中使用的PRF都是HMAC,而NIST SP800-108(普通密钥导出函数,非基于口令的密钥导出函数)中使用的PRF可以是HMACCMAC

 

 

6. 基于口令的加密方案

有两个基于口令的加密PBES方案,如下表。

表5.1 基于口令的加密方案PBES1和PBES2对比

hLen为HASH函数的输出长度)

项目

PBES1

PBES2

使用的PBKDF

PBKDF1

PBKDF2

使用的密码算法

DES / RC2 – CBC模式

AES-CBC-Pad

使用

不推荐

仅兼容PKCS5 v1.5

推荐使用

  • AES-CBC-Pad是AES算法,密钥16/24/32字节,分组16字节,IV16字节。
  • 根据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).

 

6.1 PBES1

PBES中对消息填充的方案(EM = M || PS)为:

  • 记T = 8-(#M mod 8),
  • 填充数据PS为连续T个字节且每个字节值均为T的字符串。
  • 例:若#M mod 8 = 7,PS = 01
  • 例:若#M mod 8 = 0,PS = 08 08 08 08 08 08 08 08
  • 此填充规则来至于RFC 1423。

6.1.1 PBES1-ENC

函数:C = PBES1-ENC (M, P, S, c)

功能:基于口令的加密方案PBES1的加密算法

输入参数:

  1. M:明文。
  2. P:口令,任意长度的字符串(通常为ASCII 或UTF-8字符)。
  3. S:盐值,8字节。无需保密,增加密文多变性。
  4. c:迭代次数,越大越好,建议不小于1000。

内部参数:

  1. ENC-CBC:加密函数CBC模式(如AES-ENC-CBC)。

返回数据:

  1. C:密文。

执行步骤:

步骤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的字符串。

  • 例:若#M mod 8 = 7,PS = 01
  • 例:若#M mod 8 = 0,PS = 08 08 08 08 08 08 08 08

步骤4:CBC加密:C = ENC-CBC(K, IV, EM)。

步骤5:输出密文C。

6.1.2 PBES1-DEC

函数:M = PBES1-DEC (C, P, S, c)

功能:基于口令的加密方案PBES1的解密算法

输入参数:

  1. C:密文。
  2. P:口令,任意长度的字符串(通常为ASCII 或UTF-8字符)。
  3. S:盐值,8字节。无需保密,增加密文多变性。
  4. c:迭代次数,越大越好,建议不小于1000。

内部参数:

  1. DEC-CBC:解密函数CBC模式(如AES-DEC-CBC)。

返回数据:

  1. M:明文。

执行步骤:

步骤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。

6.2 PBES2

PBES中对消息填充的方案(EM = M || PS)为:

  • 记T = 8-(#M mod 8),
  • 填充数据PS为连续T个字节且每个字节值均为T的字符串。
  • 例:若#M mod 8 = 7,PS = 01
  • 例:若#M mod 8 = 0,PS = 08 08 08 08 08 08 08 08
  • 此填充规则来至于RFC 1423。

6.2.1 PBES2-ENC

函数:C = PBES2-ENC (M, P, S, c)

功能:基于口令的加密方案PBES2的加密算法

输入参数:

  1. M:明文。
  2. P:口令,任意长度的字符串(通常为ASCII 或UTF-8字符)。
  3. S:盐值,8字节。无需保密,增加密文多变性。
  4. c:迭代次数,越大越好,建议不小于1000。

内部参数:

  1. dkLen:导出密钥DK的字节长度。

返回数据:

  1. C:密文。

执行步骤:(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).

6.2.2 PBES2-DEC

函数:M = PBES2-DEC (C, P, S, c)

功能:基于口令的加密方案PBES2的解密算法

输入参数:

  1. C:密文。
  2. P:口令,任意长度的字符串(通常为ASCII 或UTF-8字符)。
  3. S:盐值,8字节。无需保密,增加密文多变性。
  4. c:迭代次数,越大越好,建议不小于1000。

内部参数:

  1. dkLen:导出密钥DK的字节长度。

返回数据:

  1. M:明文。

执行步骤:(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。

 

7. 基于口令的消息认证方案

仅有一个基于口令的消息认证方案PBMAC1,如下表。

表5.1 基于口令的加密方案PBES1和PBES2对比

hLen为HASH函数的输出长度)

项目

PBMAC1.

使用的PBKDF

PBKDF2

使用的密码算法

HMAC

(底层HASH使用SHA1和SHA2)

使用

推荐

7.1 PBMAC1

7.1.1 PBMAC1 generation

函数:C = PBMAC1-Generate (M, P, S, c dkLen)

功能:基于口令的加密方案PBES1的加密算法

输入参数:

  1. M:消息。
  2. P:口令,任意长度的字符串(通常为ASCII 或UTF-8字符)。
  3. S:盐值,8字节。无需保密,增加密文多变性。
  4. c:迭代次数,越大越好,建议不小于1000。
  5. dkLen:导出密钥的字节长度。

内部参数:

  1. MAC:HMAC-SHA1或HMAC-SHA2。

返回数据:

  1. T:消息检验码。

执行步骤:

步骤1:生成导出密钥,DK = PBKDF:2 (P, S, c, dkLen)。

步骤2:生成消息检验码T = MAC(DK, M)。

步骤3:输出消息检验码T

7.1.2 PBMAC1 verification

函数:C = PBMAC1-Verify (M, P, S, c, dkLen, T)

功能:基于口令的加密方案PBES1的加密算法

输入参数:

  1. M:消息。
  2. P:口令,任意长度的字符串(通常为ASCII 或UTF-8字符)。
  3. S:盐值,8字节。无需保密,增加密文多变性。
  4. c:迭代次数,越大越好,建议不小于1000。
  5. dkLen:导出密钥的字节长度。
  6. T:消息检验码。

内部参数:

  1. MAC:HMAC-SHA1或HMAC-SHA2。

返回数据:

  1. ret:TRUE为验证通过,FALSE为验证失败。

执行步骤:

步骤1:生成导出密钥,DK = PBKDF2 (P, S, c, dkLen)。

步骤2:生成消息检验码T1= MAC(DK, M)。

步骤3:比较T1和T,两者相同则返回ret = TRUE,否则返回ret = FALSE。