Skip to main content

A.1.2. Generation of k

A.1.2. Generation of k (k 的生成)

我们要签名的消息 (在本例中, 这是 ASCII 字符串 "sample") 首先使用哈希函数 SHA-256 进行哈希。这产生以下 256 比特的输出 (下面显示的值是十六进制编码):

h1 = SHA-256("sample")
= AF2BDBE1AA9B6EC1E2ADE1D694F41FC71A831D0268E9891562113D8A62ADD1BF

请注意, qlen = 163, 而哈希输出长度是 hlen = 256。rlen 是 qlen 向上舍入到下一个 8 的倍数, 因此 rlen = 168。

我们首先通过 bits2octets 运行 h1。这首先通过 bits2int 提取最左边的 qlen = 163 比特, 然后对 q 取模约简, 产生:

h1' = bits2int(h1) mod q
= 0x01795EDF0D54DB760F156D0DAC04C0322B3A204224

然后 h1' 通过 int2octets 编码为 rlen = 168 比特的序列 (21 个八位字节):

bits2octets(h1) = 01795EDF0D54DB760F156D0DAC04C0322B3A204224

根据第 3.2 节中的算法:

步骤 b: V 初始化为包含 32 个值为 0x01 的八位字节的序列 (hlen = 256, 因此 8*ceil(hlen/8) = 256, 产生 32 个八位字节)。

步骤 c: K 初始化为包含 32 个值为 0x00 的八位字节的序列。

步骤 d: 使用密钥 K 和消息 V || 0x00 || int2octets(x) || bits2octets(h1) 计算 HMAC。连接的长度为:

  • V: 32 个八位字节
  • 0x00: 1 个八位字节
  • int2octets(x): 21 个八位字节 (rlen = 168 比特)
  • bits2octets(h1): 21 个八位字节

总计 75 个八位字节。生成的 HMAC 输出 (32 个八位字节) 成为 K 的新值:

K = 42D6D3D99099E78B9188E297C9ECB244796FA0B5FF0D49902DC1EE0E7A4FA496

步骤 e: V 更新为 HMAC_K(V):

V = 26F8910FB1A1E7341E3D7E041F7BDF0939E4343A02EA9E36C6FFF2C8DDB3DA8F

步骤 f: K 再次更新, 使用 0x01 而不是 0x00:

K = FB630D677CA87FE7C8C8BC50EC4444AA2C1BD1AF5BD79C69293AD8F0AE9F1F6D

步骤 g: V 再次更新:

V = 90DF5B0C7B518F9E3073CAE0655F55D2450FF05EE21F5BA8A2A443ACDC816BE7

步骤 h: 生成候选 k 值。我们生成 T, 直到其长度达到至少 qlen = 163 比特。由于 V 的长度为 256 比特, 一次迭代就足够了:

V = HMAC_K(V)
= 67C57C9059CAC58C54FB9F4D21D8071BC1EB398BC5D0C3FF077E6A8C8E653476

T = V

从 T 中提取 k:

k = bits2int(T)
= 0x33BEAE6AC9A55D768C92AFE0AB952CAE42AFA2304A

该值在 [1, q-1] 范围内, 因此是可接受的。