SHA-2概述

SHA-2安全散列算法2(Secure Hash Algorithm 2)是一种密码散列函数算法标准,由美国国家安全局研发,由美国国家标准与技术研究院(NIST)在2001年发布. 属于SHA算法之一,是SHA-1的后继者. 其下又可再分为六个不同的算法标准,包括了: SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256.

本文描述SHA-256标准.

SHA-256

字节序约定

整个SHA-2算法中,均采用大端序来处理数据.

注意: 与MD5等算法使用小端序不同.

消息填充

MD5,SHA-1类似,在计算摘要之前需要对消息进行填充.

  1. 假定输入消息的长度L<264L<2^{64},其中L的单位是bit,在消息后面追加1bit的1.
  2. 然后追加kbit个0,使其满足K为方程(L+1+K) mod 512=448( L + 1 + K )\ mod\ 512 = 448的最小非负解.
  3. 然后追加一个64-bits的二进制数,即LL的二进制表示,注意为大端序.

最终填充结果的长度为512-bits的整数倍.

函数和常量表

SHA系列函数会用到一些函数和常量,这里为SHA-256所用到的.
注: SHA-256SHA-224使用相同的数据.

函数表

下面每一个函数的操作对象都是32-bits的字,返回结果也是一个新的32-bits的字.

1
2
3
4
5
6
7
8
9
10
11
12
CH( x, y, z ) = ( x & y ) ^ ( (~x) & z )

MAJ( x, y, z ) = ( x & y ) ^ (x & z) ^ (y & z)

BSIG0( x ) = ( x >>> 2 ) ^ ( x >>> 13 ) ^ ( x >>> 22 )

BSIG1( x ) = ( x >>> 6 ) ^ ( x >>> 11 ) ^ ( x >>> 25 )

SSIG0( x ) = ( x >>> 7 ) ^ ( x >>> 18 ) ^ ( x >> 3 )

SSIG1( x ) = ( x >>> 17 ) ^ ( x >>> 19 ) ^ ( x >> 10 )

常量表

使用以下常量K0...K63,其值为前64个素数的立方根的小数部分的前32位.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
428a2f98 71374491 b5c0fbcf e9b5dba5
3956c25b 59f111f1 923f82a4 ab1c5ed5
d807aa98 12835b01 243185be 550c7dc3
72be5d74 80deb1fe 9bdc06a7 c19bf174
e49b69c1 efbe4786 0fc19dc6 240ca1cc
2de92c6f 4a7484aa 5cb0a9dc 76f988da
983e5152 a831c66d b00327c8 bf597fc7
c6e00bf3 d5a79147 06ca6351 14292967
27b70a85 2e1b2138 4d2c6dfc 53380d13
650a7354 766a0abb 81c2c92e 92722c85
a2bfe8a1 a81a664b c24b8b70 c76c51a3
d192e819 d6990624 f40e3585 106aa070
19a4c116 1e376c08 2748774c 34b0bcb5
391c0cb3 4ed8aa4a 5b9cca4f 682e6ff3
748f82ee 78a5636f 84c87814 8cc70208
90befffa a4506ceb bef9a3f7 c67178f2

计算消息摘要

初始化

SHA-256的初始化常量如下,值为前8个素数的平方根的小数部分的前32位:

1
2
3
4
5
6
7
8
H[0]0 = 6a09e667
H[0]1 = bb67ae85
H[0]2 = 3c6ef372
H[0]3 = a54ff53a
H[0]4 = 510e527f
H[0]5 = 9b05688c
H[0]6 = 1f83d9ab
H[0]7 = 5be0cd19

主循环

主循环遍历每一个分组`M[i], i = 1…N

对每一个分组如下几步:

准备消息调度W(预处理消息)

1
2
3
4
for t = 0 to 15:
W[t] = (M[i])[t]
for t = 16 to 63:
W[t] = SSIG1( W[t-2] ) + W[t-7] + SSIG0( w[t-15] ) + W[t-16]

初始化工作变量 a…h

1
2
3
4
5
6
7
8
a = H[i-1]0
b = H[i-1]1
c = H[i-1]2
d = H[i-1]3
e = H[i-1]4
f = H[i-1]5
g = H[i-1]6
h = H[i-1]7

执行主哈希运算

1
2
3
4
5
6
7
8
9
10
11
for t = 0 to 63:
T1 = h + BSIG1(e) + CH(e,f,g) + Kt + Wt
T2 = BSIG0(a) + MAJ(a,b,c)
h = g
g = f
f = e
e = d + T1
d = c
c = b
b = a
a = T1 + T2

计算中间哈希值 H[i]

1
2
3
4
5
6
7
8
H[i]0 = a + H[i-1]0
H[i]1 = b + H[i-1]1
H[i]2 = c + H[i-1]2
H[i]3 = d + H[i-1]3
H[i]4 = e + H[i-1]4
H[i]5 = f + H[i-1]5
H[i]6 = g + H[i-1]6
H[i]7 = h + H[i-1]7

输出结果

最终输出的结果就是上述的H[N]0...H[N]7的连接.
将其转为16进制即可.

参阅

RFC 6234: US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)