Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

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

李悔之2015
95 0 0
1.SHA简介1 U6 o! C- q, }( Q
关于SHA的定义直接参考wiki介绍:
, D# J  H; ^" G安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的机率很高。
9 a# J$ J0 }5 W- E8 sSHA可看作是是一种单向函数,几乎不可逆,给一段信息,它会给你生成固定长度的摘要,当然,不同的信息是的确有可能生成相同的摘要的,这被称作碰撞,简单来说,摘要的长度越长,碰撞几率越低。  z# f2 A9 A& s  ~; g+ @
既然有碰撞这种可能性,那碰撞肯定会被拿来用作攻击手段的,SHA-1已经在17年被Google和荷兰的小组攻破了,目前使用的标准是SHA-2,其实在算法上SHA-2和SHA-1区别不大,但是至今SHA-2还没被攻破,所以暂且当它没什么弱点。# ^1 I8 d* b% I; f1 l
从SHA的特点来看,用来作文件验证和数字签名是非常合适的。比特币使用的就是SHA-2中的SHA256算法。
; O/ z, [4 g) o$ _* E4 U& `+ d2.SHA256的算法实现
, H/ N3 H' e6 h5 f首先,SHA算法在数学原理上是相当复杂的(那些移位与或非对于算法的作用看着就头大),对于不以密码学研究为目的,同时也是初学者的我来说,去分析它的数学细节对我没有什么意义,因此我暂且忽略那一部分直接看它的算法实现。1 t( R' h9 Q) w- n2 @: }
实现可以分为三个部分:常量初始化,信息预处理,生成摘要。9 V( o& X+ ]: x
2.1常量初始化
! O: _6 _8 f9 |5 u/ |首先是初始化8个值,分别是最开始的连续8个素数(从2到19)的平方根的二进制表示的小数部分的前32位,有点绕,不过就是这样啦,这些后面会作为迭代的初值使用。+ N- A: ~* b1 N/ I7 z
Initialize variables2 P1 e( q! c% X
(first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):9 t" F9 r. l. h
h0 := 0x6a09e667$ v; w4 {) j6 C* w, x( O+ L, j& ^* T7 b
h1 := 0xbb67ae85
3 l/ `2 }% ^. d5 kh2 := 0x3c6ef372
6 [+ p) w& M. N' J9 }6 Mh3 := 0xa54ff53a$ G4 I# r7 x. K
h4 := 0x510e527f
# f; _$ [: D; `. z, I" Zh5 := 0x9b05688c
  l  o2 h& ^+ w8 z9 _3 sh6 := 0x1f83d9ab2 {% }/ }( I. S# g; \4 T
h7 := 0x5be0cd19
; n# x% O) |2 {6 t+ T* A然后还要初始化64个值,分别是最开始的连续64个素数(从2到311)的立方根的二进制表示的小数部分的前32位,可以看到这64个数也成了数组的形式,因为是要在后面每次迭代中拿来进行循环运算的。
% i( H2 u! v& P. V7 q8 c. zInitialize table of round constants- D9 T; [' N, M; H  S
(first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311):/ n) z5 R! {0 ~& @1 Y3 {
k[0..63] :=' e( z# g1 _- c2 X& {
   0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,! f+ a% r/ |* U1 M+ ~6 B
   0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
) g1 v' f- s) r; b   0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,9 R1 |: K$ D$ [0 ~$ E. |
   0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,/ g/ O+ Y: ?& Z6 _9 Y. P
   0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
/ I) P) s$ Q+ Q: T" l! ~5 N   0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
* `9 x0 }4 f' b   0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
9 D# [9 H8 b. t- Y7 j) q. `   0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f25 N( G* R- p/ {4 L) S* y
2.2信息预处理
& J3 w2 U* @9 h# A- a预处理分为三步,首先是在原信息后加一个‘1’;然后再添加k个0,直到信息长度 mod 512 = 448,如果原信息是447这种长度,那其实就不用加0了;最后就是再添加原信息的长度到末尾,是64位的大端模式的格式。; i: @# O; k9 W7 w4 e+ Y4 w+ k# A
Pre-processing:/ a2 V/ {, k' O! P! N- p! x/ X( c
append the bit '1' to the message
/ J3 L! E8 \, o* p5 S2 Uappend k bits '0', where k is the minimum number >= 0 such that the resulting message
# B0 \% p/ f5 W/ H5 O7 ?; Q: S    length (in bits) is congruent to 448(mod 512)- k5 l" e- e( Z* t
append length of message (before pre-processing), in bits, as 64-bit big-endian integer6 \7 h5 p( k% r0 R" l7 `( v- C
2.3生成摘要
- w4 e0 j( B2 X5 ^8 m+ V* N到了最麻烦的一步了,生成摘要。
( a/ {5 S" C! Q- ~& B' N8 ~& t首先,经过第二步,现在信息已经是512bit的倍数这种格式了,所以这里首先是把信息分成块,每一块是512bit,然后每一块都是一次迭代,每一次迭代都会更新摘要,最后一次迭代结果就是最终生成的摘要。
( {/ s& z! P% [: v- C4 z) c$ b- i所以,关键就是每一步迭代过程中发生了什么。- s5 @' Q1 z! R; T7 u
对于SHA256算法,最终的摘要是256bit的,结合前面的8个32bit的初值,这里就不难理解了,总的摘要是分成8个值进行更新的。块大小是512bit的,将其也以32bit为单位分成16个,然后通过对16个数进行运算,生成另外48个数,总之,得到了64个值,这和前面的64个常量相对应,剩下的就直接看下图吧:
& {0 x# f7 ~5 M0 t5 n+ N: M
( c* A( V5 a& V- B- v/ W每次迭代摘要的更新流程( N+ Q( A3 d/ d" d" O
中间各种运算符什么的,就是一些运算而已,没什么好说的, W是从块中得到的64个数的集合,K是之前初始化的64个数的集合,可以看到一次迭代内部有64次循环,每次循环都会更新一次摘要。
8 S2 g1 q5 ]/ ]2 o最后,来看看伪代码把:
$ `; x  y8 `! c! S- Y! @8 `Process the message in successive 512-bit chunks:
# d1 Q8 f" I) V  N/ n5 y1 }1 ?break message into 512-bit chunks" o" r) h! E# n, \
for each chunk
, P8 o) d& A" \( z    break chunk into sixteen 32-bit big-endian words w[0..15]% g. H  P& S0 G
    Extend the sixteen 32-bit words into sixty-four 32-bit words:
# r- f: W7 U5 W* |: p    for i from 16 to 63
9 b" ~- Z8 ]3 V1 y1 N        s0 := (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor(w[i-15] rightshift 3)! g8 f$ R/ B  h
        s1 := (w[i-2] rightrotate 17) xor (w[i-2] rightrotate 19) xor(w[i-2] rightshift 10)1 [. K+ g4 |7 ]
        w := w[i-16] + s0 + w[i-7] + s1
5 r: b9 h& ~- g6 f% d3 T/ a2 c2 Q    Initialize hash value for this chunk:
9 N2 g0 O2 ~# Q" @$ O: d    a := h0
+ v/ }+ r4 T5 b9 V. d9 b    b := h1* P0 m. P! f7 V
    c := h2% C% w% b: V3 u7 g3 }
    d := h3: p" n3 m2 |3 g5 J* U3 ^4 ^8 Y! F
    e := h4
* |2 c0 U& ~6 M$ W  f; J    f := h5" c) [  A$ c- b7 y! r* y
    g := h61 m6 b0 Q; I% o- s# q5 G/ E1 e
    h := h7
1 D% _. F8 w1 Q3 a" ]& Q# n    Main loop:: G0 `' j; v3 J* U/ }( j+ Y
    for i from 0 to 63! `( M) R+ K$ a5 U3 D5 C
        s0 := (a rightrotate 2) xor (a rightrotate 13) xor(a rightrotate 22)/ g- B' D2 K" u& m  x9 d
        maj := (a and b) xor (a and c) xor(b and c)
/ F: S, _" R  p6 p        t2 := s0 + maj5 D$ c" Y0 Z) \8 t* }
        s1 := (e rightrotate 6) xor (e rightrotate 11) xor(e rightrotate 25)1 p; t" D: v; Q" V
        ch := (e and f) xor ((not e) and g)8 q" e4 T' m6 i& d" K/ h. |
        t1 := h + s1 + ch + k + w
% i/ I. p+ _7 l. v0 c+ I        h := g7 x* h0 \+ A8 H5 o
        g := f
4 ^! Z! r& R7 d        f := e
, D" K) y+ r  U* s/ L5 r) B: a        e := d + t1
1 l* b' f: k: ~2 A% f( r8 g        d := c* ~/ q1 e6 K5 U; f2 m
        c := b1 Y) i1 x  h8 Q2 `) p7 M
        b := a& u1 A" ]) a+ [
        a := t1 + t2: x; y5 L3 d* L/ {) J) T
    Add this chunk's hash to result so far:
% J% O. t/ Z- f3 w" J    h0 := h0 + a
; \4 I; x0 u! K5 N" r) S    h1 := h1 + b8 Z+ I: C" x' e
    h2 := h2 + c1 [) H: o  `. C* i
    h3 := h3 + d( w  ?# h8 ^" w" t" O4 b$ C
    h4 := h4 + e( P- W$ K, O9 i* Z* z, x2 I, k
    h5 := h5 + f" H6 v# f: W0 U8 B
    h6 := h6 + g
3 v& j& `4 q5 f* r' R    h7 := h7 + h. f) V, W1 U6 ]2 Q& G% x
Produce the final hash value (big-endian):
1 P! S3 ?+ b/ D, M' }digest = hash = h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7
0 J1 B- Q" C; S8 ]) [一目了然,对吧。
$ p! _( l5 K) Y& R  ~; t0 t
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

李悔之2015 初中生
  • 粉丝

    1

  • 关注

    0

  • 主题

    13