Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

SHA256实现解析(不涉及数学原理)

李悔之2015
243 0 0
1.SHA简介
& }. l" O: {! d" Y关于SHA的定义直接参考wiki介绍:
0 z) H" r# Q5 p8 `, J6 p$ t3 t安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的机率很高。7 G/ l5 g, L" ^& E+ L! k2 t
SHA可看作是是一种单向函数,几乎不可逆,给一段信息,它会给你生成固定长度的摘要,当然,不同的信息是的确有可能生成相同的摘要的,这被称作碰撞,简单来说,摘要的长度越长,碰撞几率越低。& y  D* K8 o, G
既然有碰撞这种可能性,那碰撞肯定会被拿来用作攻击手段的,SHA-1已经在17年被Google和荷兰的小组攻破了,目前使用的标准是SHA-2,其实在算法上SHA-2和SHA-1区别不大,但是至今SHA-2还没被攻破,所以暂且当它没什么弱点。
8 b" Y7 [6 C+ H4 q从SHA的特点来看,用来作文件验证和数字签名是非常合适的。比特币使用的就是SHA-2中的SHA256算法。: \2 r  W0 d2 v+ f& w: K% M: C8 m9 s
2.SHA256的算法实现* b2 s9 C9 t3 Z  L0 O& E( J
首先,SHA算法在数学原理上是相当复杂的(那些移位与或非对于算法的作用看着就头大),对于不以密码学研究为目的,同时也是初学者的我来说,去分析它的数学细节对我没有什么意义,因此我暂且忽略那一部分直接看它的算法实现。
1 c/ o+ E0 ~& l7 ?  k+ W实现可以分为三个部分:常量初始化,信息预处理,生成摘要。" H6 G4 C% Y- e! M
2.1常量初始化
3 I0 I- R# i2 e5 b( b! f首先是初始化8个值,分别是最开始的连续8个素数(从2到19)的平方根的二进制表示的小数部分的前32位,有点绕,不过就是这样啦,这些后面会作为迭代的初值使用。$ Y6 S" G' p* N/ R& h) r& e
Initialize variables7 Z6 B% e" U) `- n, f7 I
(first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
( Q! }0 e' w) ~2 o: gh0 := 0x6a09e6679 d- m) y! Z& y
h1 := 0xbb67ae85" D; v% k7 w6 j& c* F
h2 := 0x3c6ef372( e7 g$ ]6 S& X. D: h' j+ G
h3 := 0xa54ff53a
* e/ i. T  O& ~1 {! ]: mh4 := 0x510e527f
9 m, y  V' M$ Z+ J9 Lh5 := 0x9b05688c
5 u1 e  b: B8 rh6 := 0x1f83d9ab
4 @3 Q- {3 @. ~. ah7 := 0x5be0cd19/ i" [# e' X8 }/ d6 q5 `$ b6 S0 P
然后还要初始化64个值,分别是最开始的连续64个素数(从2到311)的立方根的二进制表示的小数部分的前32位,可以看到这64个数也成了数组的形式,因为是要在后面每次迭代中拿来进行循环运算的。1 v5 a' _, @3 {
Initialize table of round constants3 W8 W3 m2 J2 C1 z$ k
(first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311):( Q6 u  c% e5 X& W( ^
k[0..63] :=
0 Z5 Z8 {- U7 g; Z! ?1 E3 [) x   0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,8 m# R  A) S5 Y3 M& i
   0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
$ R* X& h9 L/ d  y; F! r. s   0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
; p1 C3 y- G1 _6 _* x   0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
- p# J% M8 p# B" o( I. H: ?, Z6 G   0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0 [( W- K) t. z   0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,# T0 L. m5 t9 ]' \( ^) c
   0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,2 Y6 n4 ?. ^# Y, A9 e
   0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2; f) v. ?5 \' h3 j: C" `$ `
2.2信息预处理
" Y6 j0 a: W+ P; ]预处理分为三步,首先是在原信息后加一个‘1’;然后再添加k个0,直到信息长度 mod 512 = 448,如果原信息是447这种长度,那其实就不用加0了;最后就是再添加原信息的长度到末尾,是64位的大端模式的格式。+ P8 i  O" Q& @
Pre-processing:3 e) o, r  A5 T6 Z. X8 d, l
append the bit '1' to the message
3 M# K- R$ O0 o: ?  eappend k bits '0', where k is the minimum number >= 0 such that the resulting message" u  u1 T& _0 D" a! K& G' [% J- Q! ]
    length (in bits) is congruent to 448(mod 512)
. x5 }  u. q& Happend length of message (before pre-processing), in bits, as 64-bit big-endian integer! l8 H; k3 f5 l& B8 P2 Y- l6 O! I
2.3生成摘要- w7 c7 B8 ^  p
到了最麻烦的一步了,生成摘要。
! L! ^( U2 V; Q$ ?6 |首先,经过第二步,现在信息已经是512bit的倍数这种格式了,所以这里首先是把信息分成块,每一块是512bit,然后每一块都是一次迭代,每一次迭代都会更新摘要,最后一次迭代结果就是最终生成的摘要。) X. Z! @" g9 [5 M4 {( K8 _$ z+ W
所以,关键就是每一步迭代过程中发生了什么。. m9 m( o4 ?2 @, t* w4 m
对于SHA256算法,最终的摘要是256bit的,结合前面的8个32bit的初值,这里就不难理解了,总的摘要是分成8个值进行更新的。块大小是512bit的,将其也以32bit为单位分成16个,然后通过对16个数进行运算,生成另外48个数,总之,得到了64个值,这和前面的64个常量相对应,剩下的就直接看下图吧:# r7 `) e* S3 P
, z1 p! O& [+ A- h# q
每次迭代摘要的更新流程
4 v: c: I/ ~; V0 X" Y  f- l( q中间各种运算符什么的,就是一些运算而已,没什么好说的, W是从块中得到的64个数的集合,K是之前初始化的64个数的集合,可以看到一次迭代内部有64次循环,每次循环都会更新一次摘要。
4 r# _2 z& ^5 v& e) [2 h最后,来看看伪代码把:: C" g" Q* ^* S% t$ B) M! n: q
Process the message in successive 512-bit chunks:
$ R3 u* U/ T- j! C2 J& f' a2 Ybreak message into 512-bit chunks( \9 v: _2 C: L
for each chunk
. I! u, a6 ?6 f& S    break chunk into sixteen 32-bit big-endian words w[0..15]
4 F1 L8 A! X4 Y- O, U; Y* j    Extend the sixteen 32-bit words into sixty-four 32-bit words:
: x% U" q3 k! N: ]    for i from 16 to 63
. g$ S7 u& |7 o: i6 A. Q        s0 := (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor(w[i-15] rightshift 3)! q& I3 U- y+ k+ u" b
        s1 := (w[i-2] rightrotate 17) xor (w[i-2] rightrotate 19) xor(w[i-2] rightshift 10)- R# E- l5 V3 }5 `
        w := w[i-16] + s0 + w[i-7] + s1; W9 j+ X& F9 y, u0 C- f
    Initialize hash value for this chunk:/ u' b+ g! t0 f+ V; p% E& g
    a := h0
9 K- g. {5 d+ n+ R+ d1 j5 i4 b$ ~    b := h18 g! {6 k( u9 ?5 p( H! E9 m) X
    c := h2
3 s5 s- p0 E& x* Q/ P    d := h3
" T0 D* R# P7 L" w( O3 W    e := h4
0 {3 _+ A2 s$ }6 N4 {2 r    f := h5
( e: s. b. `- m; m6 B& {    g := h6" S( x0 f& m1 i( }; c
    h := h7
3 d0 }3 O; `, P& R- {    Main loop:
% R' Q' y( \9 V. V7 Y    for i from 0 to 631 j* r$ i6 q/ ]% L$ ~
        s0 := (a rightrotate 2) xor (a rightrotate 13) xor(a rightrotate 22)% f% u; E" j& }
        maj := (a and b) xor (a and c) xor(b and c)
$ n4 h* P8 b8 z6 h& X1 b& f. ]" X        t2 := s0 + maj" h1 ]& c) R( h9 q
        s1 := (e rightrotate 6) xor (e rightrotate 11) xor(e rightrotate 25)
0 y$ J/ i1 x: v9 h6 C3 l. {        ch := (e and f) xor ((not e) and g)
) r, A/ X2 H8 a4 F1 ^: g& a        t1 := h + s1 + ch + k + w2 D1 J( C9 A% N# d
        h := g
+ V7 w9 e" z9 k: O, v( D& o        g := f
0 c  H) ?, c1 c0 B  y        f := e
0 s& m+ \/ j+ ?6 e- i5 V        e := d + t1
/ ~3 N  i2 A% Y0 V" `* M2 @        d := c
' N, v, C, j: W0 ]; V/ H" j        c := b. D! i3 X4 L1 ]2 h
        b := a
$ C8 R# V0 V1 }6 O, Z/ r        a := t1 + t2
" f  ?' u0 j3 }( d# Q    Add this chunk's hash to result so far:* P" n9 c8 o/ l& m( A  V
    h0 := h0 + a
8 d! ~& m; K+ w9 w' W$ w    h1 := h1 + b
, W' n  i2 w, O9 H1 A2 K# d# F    h2 := h2 + c
* Z5 V$ c" _( m4 A' j    h3 := h3 + d
5 T( e$ Q$ Y3 a2 s) z2 }" n    h4 := h4 + e! c) _. z1 K4 A" w1 O6 A9 E4 }
    h5 := h5 + f5 p+ ?* |, N1 q% L' [: O
    h6 := h6 + g1 {3 }6 z- ]" K& H& M3 n* k0 K) ^
    h7 := h7 + h
. Y1 L* A/ I; \* r9 d7 iProduce the final hash value (big-endian):
- v1 C9 w" i4 N) F! I) Udigest = hash = h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7/ J! J) M+ ^' }' W4 g
一目了然,对吧。; l8 w6 _2 @# K3 Q
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

李悔之2015 初中生
  • 粉丝

    1

  • 关注

    0

  • 主题

    13