水滴
分类: LINUX
2018-09-04 10:50:11
为了更好的理解SHA256的原理,这里首先将算法中可以单独抽出的模块,包括常量的初始化、信息预处理、使用到的逻辑运算分别进行介绍,甩开这些理解上的障碍后,一起来探索SHA256算法的主体部分,即消息摘要是如何计算的。
SHA256算法中用到了8个哈希初值以及64个哈希常量
其中,SHA256算法的8个哈希初值如下:
h0:= 0x6a09e667这些初值是对自然数中前8个质数(2,3,5,7,11,13,17,19)的平方根的小数部分取前32bit而来
举个例子来说,2的平方根小数部分约为0.414213562373095048,而0.414213562373095048
于是,质数2的平方根的小数部分取前32bit就对应出了0x6a09e667。
在SHA256算法中,用到的64个常量如下:
和8个哈希初值类似,这些常量是对自然数中前64个质数(2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97…)的立方根的小数部分取前32bit而来。
SHA256算法中的预处理就是在想要Hash的消息后面补充需要的信息,使整个消息满足指定的结构。
信息的预处理分为两个步骤:附加填充比特和附加长度
STEP1:附加填充比特
在报文末尾进行填充,使报文长度在对512取模以后的余数是448
填充是这样进行的:先补第一个比特为1,然后都补0,直到长度满足对512取模后余数是448。
需要注意的是,信息必须进行填充,也就是说,即使长度已经满足对512取模后余数是448,补位也必须要进行,这时要填充512个比特。
因此,填充是至少补一位,最多补512位。
例:以信息“abc”为例显示补位的过程。
a,b,c对应的分别是97,98,99
于是原始信息的二进制编码为:01100001 01100010 01100011
补位第一步,首先补一个“1” : 0110000101100010 01100011 1
补位第二步,补423个“0”:01100001 01100010 01100011 10000000 00000000 … 00000000
补位完成后的数据如下(为了简介用16进制表示):
61626380 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000因为在第一步的预处理后,第二步会再附加上一个64bit的数据,用来表示原始报文的长度信息。而448+64=512,正好拼成了一个完整的结构。
STEP2:附加长度值
附加长度值就是将原始数据(第一步填充前的消息)的长度信息补到已经进行了填充操作的消息后面。
wiki百科中给出的原文是:append length of message (before pre-processing), in bits, as 64-bit big-endian integer
SHA256用一个64位的数据来表示原始消息的长度。
因此,通过SHA256计算的消息长度必须要小于264
,当然绝大多数情况这足够大了。
长度信息的编码方式为64-bit big-endian integer
关于Big endian的含义,文末给出了补充
回到刚刚的例子,消息“abc”,3个字符,占用24个bit
因此,在进行了补长度的操作以后,整个消息就变成下面这样了(16进制格式)
61626380 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000018SHA256散列函数中涉及的操作全部是逻辑的位运算
包括如下的逻辑函数:
逻辑运算 | 含义 |
---|---|
∧ |
|
按位“与” |
? |
|
按位“补” |
⊕ |
|
按位“异或” |
Sn |
|
右移n个bit |
Rn |
|
循环右移n个bit |
现在来介绍SHA256算法的主体部分,即消息摘要是如何计算的。
首先:将消息分解成512-bit大小的块
假设消息M可以被分解为n个块,于是整个算法需要做的就是完成n次迭代,n次迭代的结果就是最终的哈希值,即256bit的数字摘要。
一个256-bit的摘要的初始值H0,经过第一个数据块进行运算,得到H1,即完成了第一次迭代, H1经过第二个数据块得到H2,……,依次处理,最后得到Hn,Hn即为最终的256-bit消息摘要.
将每次迭代进行的映射用Map(Hi?1)=Hi
图中256-bit的Hi被描述8个小块,这是因为SHA256算法中的最小运算单元称为“字”(Word),一个字是32位。
此外,第一次迭代中,映射的初值设置为前面介绍的8个哈希初值,如下图所示:
下面开始介绍每一次迭代的内容,即映射Map(Hi?1)=Hi
的具体算法
STEP1:构造64个字(word)
break chunk into sixteen 32-bit big-endian words w[0], …, w[15]
对于每一块,将块分解为16个32-bit的big-endian的字,记为w[0], …, w[15]
也就是说,前16个字直接由消息的第i个块分解得到
其余的字由如下迭代公式得到:
STEP2:进行64次循环
映射Map(Hi?1)=Hi
包含了64次加密循环
即进行64次加密循环即可完成一次迭代
每次加密循环可以由下图描述:
图中,ABCDEFGH这8个字(word)在按照一定的规则进行更新,其中
深蓝色方块是事先定义好的非线性逻辑函数,上文已经做过铺垫
红色田字方块代表 mod232
addition,即将两个数字加在一起,如果结果大于232,你必须除以232并找到余数。
ABCDEFGH一开始的初始值分别为Hi?1(0),Hi?1(1),...,Hi?1(7)
Kt是第t个密钥,对应我们上文提到的64个常量
Wt是本区块产生第t个word。原消息被切成固定长度512-bit的区块,对每一个区块,产生64个word,通过重复运行循环n次对ABCDEFGH这八个字循环加密。
最后一次循环所产生的八个字合起来即是第i个块对应到的散列字符串Hi
由此变完成了SHA256算法的所有介绍