哈希算法是信息安全领域重要的组成部分,主要包括:
- 生成和验证数字签名
- 密钥导出 (key derivation)
- 伪随机位生成 (pseudorandom bit generation)
SHA-3 算法是第三代标准的哈希函数,基于 Keccak 算法实现。与之前的哈希算法有所不同,SHA-3 算法是基于置换 ( permutation-based ) 的加密函数。本文主要介绍 SHA-3 算法生成哈希结果的流程,下面根据 SHA-3 标准的流程进行简要介绍。本文只介绍到定长输出部分。
开始
输出长度为 X 位的 SHA-3 哈希函数表示为:
SHA3-X(M)
下面以输出长度为 256 位的函数为例。标准中,输出长度为 256 位的 SHA-3 函数的表示为
SHA3-256(M)
其中 M 为需要进行哈希的数据。对数据哈希的过程主要基于海绵结构 ( sponge construction ) 进行,因此先介绍一下海绵结构。
海绵结构
海绵结构能够进行数据转换,将任意长的输入转换成任意长的输出。下图是一个海绵结构的示意图。
如图所示,海绵结构包含 3 个重要的组成部分:
- 一个对数据进行等长映射的函数 f,即输出串长度与输入串长度相同,记为 b。
- 一个参数称为比率 ( rate ),记作 r,是指每轮要吸收的 长度为 b 的串中数据的长度,剩余部分称为容量,记为 c,因此,有 b=r+c。
- 一个填充 ( padding ) 函数,记作 pad(x,m),返回将长度为 m 的串填充为 x 的整数倍长度的串。例如 pad(5,2)=010,指将长度为 2 的串填充为 5 的整数倍长度,需要添加一个长度为 3 的串,任意长为 3 的串均可,本例中返回值为 010,其长度为 3。
给定上述组成后,可以对数据进行操作并得到映射结果。形式化定义如下:
SPONGE[f,pad,r]
基于该海绵结构可以定义海绵函数,用于将输入转换成指定长度的串,因此,函数有两个参数:1. 输入串 N,2. 输出长度 d。函数定义如下:
SPONGE[f,pad,r](N,d)
下面根据图,简要说明海绵函数的执行流程:
- 首先对输入 N 进行填充,使其长度为 r 的整数倍,结果为 P=N∣∣pad(r,len(N)),“∣∣” 表示串连接。
- 记 n=len(P)/r,将 P 分成 n 段,记为 P=P0∣∣P2∣∣⋯∣∣Pn−1,每段长度为 r。
- 定义 S=0b 表示长度为 b 的 0 串,这个 S 也被称为状态,之后进行介绍。
- 定义 i 从 0 到 n−1,对 S 依次进行转换,S=f(S⊕(Pi∣∣0c)),上述过程称为吸收 (absorbing) 过程。
- 定义 Z 为空串。
- Z=Z∣∣Truncr(S),其中 Truncr(S) 指 S 前 r 个字符组成的串。
- 如果此时 d≤len(Z),返回 Truncd(Z)。
- 令 S=f(S),返回步骤 6。
定义一个海绵结构需要指明海绵结构中的三个组成成分
- 一个对数据进行等长映射的函数 f。
- 一个参数称为比率 r。
- 一个填充 ( padding ) 函数,记作 pad(x,m)。
SHA-3 中使用的 KECCAK 海绵函数的三个组件形式如下:
- 映射函数 KECCAK-p[b,nr](S),将长度为 b 的串 S,经过 nr 轮转换输出为长度为 b 的结果,也被称为 KECCAK-p 置换函数。该函数之后会详细说明。
- 比率 r 根据输出长度不同进行调整。
- 填充函数为 pad10∗1(x,m),除了返回将长度为 m 的串填充为 x 的整数倍长度的串外,还保证返回的串满足表达式 10∗1 形式。
KECCAK-p 置换将输入串进行多轮重新排列得到长度相同的输出串。设输入串 S 长度为 b,置换进行 nr 轮重新排列,则进行的 KECCAK-p 置换函数记为
KECCAK-p[b,nr](S)
其中,b∈{25,50,100,200,400,800,1600}
置换函数也可以认为是在进行状态转移,前面提到,这个函数的输入 S 又称为状态,KECCAK-p 置换,就是对 S 进行状态转移。下面简要介绍一下状态的概念。
状态 ( state )
一个一直被更新的位数组称为一个状态。一个状态可以表示成一个位串或一个状态数组。位串就是指状态的二进制串,记为 S,长度记为 b;状态数组将状态表示为一个 5×5×w 的三维数组,其中 w=b/25,记为 A。S 和 A 都表示状态,可以互相转换。这里不详细描述有兴趣可以参看文末链接。
状态数组中的每一位可以用 A[x,y,z] 表示,状态数组的坐标系统如下所示:
其中,x,y 方向都以中心点为原点。下面是状态数组中不同子数组的命名。
阶段映射 ( step mappings )
SHA-3 标准中共有 5 个映射函数,可以对状态数组 A 进行不同的排列,下面简要进行介绍。
- θ(A),对 column 进行重排列。
- ρ(A),对 lane 进行重排列。
- π(A),对 slice 进行重排列。
- χ(A),对 row 进行重排列。
- ι(A,ir),对 A[0,0,z] 部分进行重排列。
对于 nr 轮转换,每一轮使用函数 Rnd 进行转换:
Rnd(A,ir)=ι(χ(π(ρ(θ(A)))),ir)
其中,每轮转换的 ir∈[12+2ℓ−nr,12+2ℓ−1]
置换过程
置换过程总结如下:
- 将 S 转换为 A
- 对于 ir,从 12+2ℓ−nr 到 12+2ℓ−1 取值,得到 A=Rnd(A,ir)
- 将 A 转换为 S′,并返回 S′
定义 SHA-3
SHA-3 中的哈希函数基于 Keccak 海绵结构实现,并将一些参数设置为常量:
- 设置 KECCAK-p 置换输入长度为 1600 bit,也是状态的长度。
- 设置 KECCAK-p 置换进行 24 轮。
参数 r=1600−c,且其值取决于需要输出的哈希结果的长度。因此,SHA-3 中使用的海绵函数定义为:
KECCAK[c](N,d)=SPONGE[KECCAK-p[1600,24],pad10∗1,1600−c](N,d)
参数 c 取决于输出长度。
基于上述定义,SHA-3 哈希函数定义如下:
SHA3-224(M)=KECCAK[448](M∣∣01,224)
SHA3-256(M)=KECCAK[512](M∣∣01,256)
SHA3-384(M)=KECCAK[768](M∣∣01,384)
SHA3-512(M)=KECCAK[1024](M∣∣01,512)
其中,c 被设为输出长度的 2 倍,输入串还需要添加后缀 01 作为海绵函数的输入。SHA-3 系列函数最终分别得到给定长度的哈希结果。
参考资料
SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions