Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

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

李悔之2015
245 0 0
1.SHA简介9 b6 W' A2 C8 R  V  f9 Q+ S9 S
关于SHA的定义直接参考wiki介绍:% ?) c. W8 R: J1 u! e7 k
安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的机率很高。5 v) n( e6 f4 h- B8 b2 d
SHA可看作是是一种单向函数,几乎不可逆,给一段信息,它会给你生成固定长度的摘要,当然,不同的信息是的确有可能生成相同的摘要的,这被称作碰撞,简单来说,摘要的长度越长,碰撞几率越低。: R3 b0 V4 ]% d5 I0 Z
既然有碰撞这种可能性,那碰撞肯定会被拿来用作攻击手段的,SHA-1已经在17年被Google和荷兰的小组攻破了,目前使用的标准是SHA-2,其实在算法上SHA-2和SHA-1区别不大,但是至今SHA-2还没被攻破,所以暂且当它没什么弱点。2 x- V0 N9 A  n6 ^8 C% o( w7 ^
从SHA的特点来看,用来作文件验证和数字签名是非常合适的。比特币使用的就是SHA-2中的SHA256算法。7 m. e7 y9 V5 t1 [3 o0 Q/ z/ j) X2 U
2.SHA256的算法实现* D/ Q% a' Z- [' h- C. ^
首先,SHA算法在数学原理上是相当复杂的(那些移位与或非对于算法的作用看着就头大),对于不以密码学研究为目的,同时也是初学者的我来说,去分析它的数学细节对我没有什么意义,因此我暂且忽略那一部分直接看它的算法实现。' T! i6 K0 o7 C6 v+ h
实现可以分为三个部分:常量初始化,信息预处理,生成摘要。
- _% f& [2 Z1 m  A% X' X2.1常量初始化3 y0 ?! d5 U2 n
首先是初始化8个值,分别是最开始的连续8个素数(从2到19)的平方根的二进制表示的小数部分的前32位,有点绕,不过就是这样啦,这些后面会作为迭代的初值使用。
: a: N: `. M2 n# B5 ?% dInitialize variables
' h# a7 M% w3 X(first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
% K  W1 h: g; Y# w* E2 S$ wh0 := 0x6a09e667. Y) y7 k3 f( p0 ^2 {+ x
h1 := 0xbb67ae85( Y( a) P' ~/ m+ p' j9 Z
h2 := 0x3c6ef372
; m- ~1 x+ _; _7 L+ dh3 := 0xa54ff53a" @8 o& l5 \+ C) S4 o8 u
h4 := 0x510e527f
3 \1 O5 _* w* U4 z# I$ n' Dh5 := 0x9b05688c( _6 Z/ c4 N; ^; K3 `
h6 := 0x1f83d9ab! B+ G" b/ Q4 X) r$ o. [
h7 := 0x5be0cd19
3 w, Q3 c9 @3 D1 R/ W! M然后还要初始化64个值,分别是最开始的连续64个素数(从2到311)的立方根的二进制表示的小数部分的前32位,可以看到这64个数也成了数组的形式,因为是要在后面每次迭代中拿来进行循环运算的。( [4 I6 P: }& X+ l5 ]* |. W2 m
Initialize table of round constants- X: o  ^0 s7 x
(first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311):- g6 ~/ X  }2 v  U( h0 j' m  t! q8 y
k[0..63] :=8 W2 g# q2 A6 q  W! d; |' Y7 |
   0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
7 m' S9 _3 a2 F/ _# K  ^! L( L   0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
1 W2 E( K5 c0 y; z* P. c& e6 E! I  d   0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,. b; X) {. @. X6 T' Q9 U/ j! [5 p
   0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,# F6 V# ~# J% a( X  e! b/ Y# v
   0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
8 v( c) K  o1 E. b   0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,1 l9 h# b9 y$ l6 f- d
   0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,0 p0 X, i% `9 [8 j
   0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2' _: @$ G2 [  Y* _+ }, k; m
2.2信息预处理' R6 z2 ]% m( I6 j1 c3 Q* p5 W+ q
预处理分为三步,首先是在原信息后加一个‘1’;然后再添加k个0,直到信息长度 mod 512 = 448,如果原信息是447这种长度,那其实就不用加0了;最后就是再添加原信息的长度到末尾,是64位的大端模式的格式。
2 p8 V4 [/ y1 R# F% E/ ^Pre-processing:
; }/ ?% |5 p" r8 _9 P$ [append the bit '1' to the message
6 b# D% [7 [! o: F7 [( ^7 iappend k bits '0', where k is the minimum number >= 0 such that the resulting message! Y% f% K; h- @* ?" [
    length (in bits) is congruent to 448(mod 512)" _/ {+ ]* d; |  F2 _5 G
append length of message (before pre-processing), in bits, as 64-bit big-endian integer
5 P: J1 R  T, W3 Z/ x) r" x( P3 D2.3生成摘要% C+ D! o! i4 b& V0 B1 J* f
到了最麻烦的一步了,生成摘要。, K: M+ H* R7 Q, A6 C' X- P- e
首先,经过第二步,现在信息已经是512bit的倍数这种格式了,所以这里首先是把信息分成块,每一块是512bit,然后每一块都是一次迭代,每一次迭代都会更新摘要,最后一次迭代结果就是最终生成的摘要。
5 G$ u' ?) O" ^. Y" f8 |, u5 W, ~所以,关键就是每一步迭代过程中发生了什么。
+ w  c% q( K4 k# X# q. \对于SHA256算法,最终的摘要是256bit的,结合前面的8个32bit的初值,这里就不难理解了,总的摘要是分成8个值进行更新的。块大小是512bit的,将其也以32bit为单位分成16个,然后通过对16个数进行运算,生成另外48个数,总之,得到了64个值,这和前面的64个常量相对应,剩下的就直接看下图吧:
4 ^" g7 d3 {% r2 z& b3 J- r) y- K8 k; r$ k8 c1 O# c+ s, h
每次迭代摘要的更新流程
% T3 V# S0 y$ r' C! q4 _; e. Q2 p, K中间各种运算符什么的,就是一些运算而已,没什么好说的, W是从块中得到的64个数的集合,K是之前初始化的64个数的集合,可以看到一次迭代内部有64次循环,每次循环都会更新一次摘要。0 H3 f6 p, v3 [6 o
最后,来看看伪代码把:
$ N' s: y( S4 I' @. b- ?; f. m& B5 m" TProcess the message in successive 512-bit chunks:7 }4 b6 o5 w6 p! Q3 f
break message into 512-bit chunks
( k6 D, L# U5 y6 ?for each chunk
$ r3 ~9 \! b8 }& A7 ~$ ]    break chunk into sixteen 32-bit big-endian words w[0..15]
, V  p4 ]3 W  ?3 C$ e    Extend the sixteen 32-bit words into sixty-four 32-bit words:
2 v6 {$ ^; x5 r- d2 R    for i from 16 to 63
4 U' m) y4 ]- n& ]3 v        s0 := (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor(w[i-15] rightshift 3)9 E8 m& B! p# K
        s1 := (w[i-2] rightrotate 17) xor (w[i-2] rightrotate 19) xor(w[i-2] rightshift 10). t* p: V' c, w3 G! U
        w := w[i-16] + s0 + w[i-7] + s1
5 C7 c7 f# [6 J. o    Initialize hash value for this chunk:
+ [+ M" O) p! M) G9 e3 Q    a := h0
7 W0 f8 ?7 i4 F5 H3 N    b := h1+ T( m: Y. y5 Q9 e1 T' R2 J
    c := h28 N6 O6 n  H) R- M* M+ U
    d := h3
8 d5 i/ ]: W4 d2 h+ T0 `& n" K  i    e := h4" I0 l, q' s3 {6 ^
    f := h5
, E; U& s; M* m    g := h6  Q# @5 S" r* N' X5 m3 }/ o
    h := h7
6 X, j& d% d0 h) J4 ^    Main loop:5 H  ]3 c1 X! s# U  v; Y
    for i from 0 to 63; C3 [) L& B% w* ?8 Z
        s0 := (a rightrotate 2) xor (a rightrotate 13) xor(a rightrotate 22)& _+ j( P( h  b, q& s
        maj := (a and b) xor (a and c) xor(b and c)7 {+ v3 T8 u1 _+ z* H+ u0 r
        t2 := s0 + maj
( R' P2 ~( Q9 O5 [3 `        s1 := (e rightrotate 6) xor (e rightrotate 11) xor(e rightrotate 25)$ x, O9 T8 b, P+ i
        ch := (e and f) xor ((not e) and g)6 y. i$ L/ h' N& P# a6 {! \* F
        t1 := h + s1 + ch + k + w* S4 {' b& G; E8 |0 @
        h := g
7 x) q5 N1 c5 B' c: E! S$ v        g := f5 }$ }0 T* r4 R, _% t
        f := e
* Q, ~. P0 p6 Y! ]: c; x        e := d + t1
/ Y% n* t' a) V! r4 m        d := c0 v  g) a! U& D% _
        c := b; c0 F" h8 C0 a, J6 q3 E
        b := a' E% n! P( P- ]9 b$ ^7 J
        a := t1 + t27 V, L/ G3 N( ]9 J" o4 z0 y
    Add this chunk's hash to result so far:* {/ F+ R1 `! B+ x) s
    h0 := h0 + a1 y; o, i/ l; V6 V0 C6 l
    h1 := h1 + b3 d3 M/ f* j' n& J% t
    h2 := h2 + c
* v3 g4 j+ e6 P* I5 Q" g3 O    h3 := h3 + d6 ]( l1 e$ ~- x3 Z
    h4 := h4 + e  i* _1 o1 c$ L6 [
    h5 := h5 + f* M0 ~8 O/ I: b* n* _8 S2 m( _' f
    h6 := h6 + g
5 q) j! D6 M/ G, c5 c    h7 := h7 + h
0 p$ l) v4 X; {0 t' l+ a  [Produce the final hash value (big-endian):
7 k# q2 Y  m- D' ]" u% Xdigest = hash = h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7; @* \8 b9 ^' k8 L4 g: Z
一目了然,对吧。
0 N. d' t! K; X/ H4 u8 {' A
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

李悔之2015 初中生
  • 粉丝

    1

  • 关注

    0

  • 主题

    13