日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

SHA256算法原理及其实现

發(fā)布時(shí)間:2023/12/10 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SHA256算法原理及其实现 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

SHA家族的五個(gè)算法,分別是SHA-1、SHA-224、SHA-256、SHA-384,和SHA-512,由美國(guó)國(guó)家安全局(NSA)所規(guī)劃,并由美國(guó)國(guó)家規(guī)范與技能研究院(NIST)發(fā)布。
該算法是美國(guó)的政府規(guī)范算法,后四者有時(shí)并稱為SHA-2。
SHA在很多安全協(xié)定中廣為運(yùn)用,包含TLS和SSL、PGP、SSH、S/MIME和IPsec,曾被視為是MD5(更早之前被廣為運(yùn)用的雜湊函數(shù))的后繼者。 但SHA-1的安全性現(xiàn)在被密碼學(xué)家嚴(yán)峻質(zhì)疑,有學(xué)者曾經(jīng)爆出NSA在SHA-1留下的后門。
雖然至今尚未出現(xiàn)對(duì)SHA-2有效的攻擊,但是它的算法跟SHA-1基本上仍然相似,因此有些人開始發(fā)展其他替代的雜湊算法。

學(xué)習(xí)區(qū)塊鏈,總是無(wú)法避開各種加密算法,因?yàn)楦鞣N加密算法在實(shí)現(xiàn)區(qū)塊鏈當(dāng)中的各個(gè)環(huán)節(jié)都有著不可替代的作用。這里介紹一下在比特幣挖礦以及merkle樹當(dāng)中被大量使用的鼎鼎大名的SHA256算法。

SHA-2 族算法簡(jiǎn)介

一個(gè)n位的哈希函數(shù)就是一個(gè)從任意長(zhǎng)的消息到n位哈希值的映射,一個(gè)n位的加密哈希函數(shù)就是一個(gè)單向的、避免碰撞的n位哈希函數(shù)。這樣的函數(shù)是目前在數(shù)字簽名和密碼保護(hù)當(dāng)中極為重要的手段。

當(dāng)前比較流行的哈希函數(shù)主要有128位的MD4和MD5和160位的SHA-1,今天介紹的SHA-2族有著更多位的輸出哈希值,破解難度更大,能夠提高更高的安全性。

SHA-2,名稱來(lái)自于安全散列算法2(英語(yǔ):Secure Hash Algorithm 2)的縮寫,一種密碼散列函數(shù)算法標(biāo)準(zhǔn),由美國(guó)國(guó)家安全局研發(fā),由美國(guó)國(guó)家標(biāo)準(zhǔn)與技術(shù)研究院(NIST)在2001年發(fā)布。屬于SHA算法之一,是SHA-1的后繼者。其下又可再分為六個(gè)不同的算法標(biāo)準(zhǔn),包括了:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。

這些變體除了生成摘要的長(zhǎng)度、循環(huán)運(yùn)行的次數(shù)等一些細(xì)微差異之外,基本結(jié)構(gòu)是一致的。本文主要講一講SHA256。

SHA256原理詳解

概述

對(duì)于任意長(zhǎng)度的消息,SHA256都會(huì)產(chǎn)生一個(gè)256位的哈希值,稱作消息摘要。這個(gè)摘要相當(dāng)于是個(gè)長(zhǎng)度為32個(gè)字節(jié)的數(shù)組,通常有一個(gè)長(zhǎng)度為64的十六進(jìn)制字符串來(lái)表示,其中1個(gè)字節(jié)=8位,一個(gè)十六進(jìn)制的字符的長(zhǎng)度為4位。

來(lái)看一個(gè)具體的例子:

BlockChain

這句話經(jīng)過(guò)哈希函數(shù)SHA256后得到的哈希值為:

3a6fed5fc11392b3ee9f81caf017b48640d7458766a8eb0382899a605b41f2b9

總體上,HSA256與MD4、MD5以及HSA-1等哈希函數(shù)的操作流程類似,待哈希的消息在繼續(xù)哈希計(jì)算之前首先要進(jìn)行以下兩個(gè)步驟:

  • 對(duì)消息進(jìn)行補(bǔ)位處理,是的最終的長(zhǎng)度是512位的倍數(shù),然后
  • 以512位為單位對(duì)消息進(jìn)行分塊為

?

?消息區(qū)塊將進(jìn)行逐個(gè)處理:從一個(gè)固定的初始哈希開始,進(jìn)行以下序列的計(jì)算:

?

其中是SHA256的壓縮函數(shù),是mod?加法,即將兩個(gè)數(shù)字加在一起,如果對(duì)取余,?是消息區(qū)塊的哈希值.

算法詳細(xì)描述

SHA256的壓縮函數(shù)主要對(duì)512位的消息區(qū)塊和256位的中間哈希值進(jìn)行操作,本質(zhì)上,它是一個(gè)通過(guò)將消息區(qū)塊為密鑰對(duì)中間哈希值進(jìn)行加密的256位加密算法。 因此,為了描述SHA256算法,有以下兩方面的組件需要描述:

  • SHA256壓縮函數(shù)
  • SHA256消息處理流程

以下的描述當(dāng)中所使用到的標(biāo)記如下:

  • : 按位異或
  • : 按位與
  • : 按位或
  • : 補(bǔ)位
  • : 相加以后對(duì)求余
  • : 右移n位
  • : 循環(huán)右移n位

以上所有的操作都是針對(duì)32位字節(jié).

常量初始化

初始哈希值取自自然數(shù)中前面8個(gè)素?cái)?shù)(2,3,5,7,11,13,17,19)的平方根的小數(shù)部分, 并且取前面的32位. 下面舉個(gè)例子:?小數(shù)部分約為0.414213562373095048, 而其中

于是, 質(zhì)數(shù)2的平方根的小數(shù)部分取前32位就對(duì)應(yīng)0x6a09e667.

如此類推, 初始哈希值由以下8個(gè)32位的哈希初值構(gòu)成:

SHA256算法當(dāng)中還使用到64個(gè)常數(shù), 取自自然數(shù)中前面64個(gè)素?cái)?shù)的立方根的小數(shù)部分的前32位, 如果用16進(jìn)制表示, 則相應(yīng)的常數(shù)序列如下:

428a2f98 71374491 b5c0fbcf e9b5dba5 3956c25b 59f111f1 923f82a4 ab1c5ed5 d807aa98 12835b01 243185be 550c7dc3 72be5d74 80deb1fe 9bdc06a7 c19bf174 e49b69c1 efbe4786 0fc19dc6 240ca1cc 2de92c6f 4a7484aa 5cb0a9dc 76f988da 983e5152 a831c66d b00327c8 bf597fc7 c6e00bf3 d5a79147 06ca6351 14292967 27b70a85 2e1b2138 4d2c6dfc 53380d13 650a7354 766a0abb 81c2c92e 92722c85 a2bfe8a1 a81a664b c24b8b70 c76c51a3 d192e819 d6990624 f40e3585 106aa070 19a4c116 1e376c08 2748774c 34b0bcb5 391c0cb3 4ed8aa4a 5b9cca4f 682e6ff3 748f82ee 78a5636f 84c87814 8cc70208 90befffa a4506ceb bef9a3f7 c67178f2

消息預(yù)處理

在計(jì)算消息的哈希摘要之前需要對(duì)消息進(jìn)行預(yù)處理:

  • 對(duì)消息進(jìn)行補(bǔ)碼處理: 假設(shè)消息的二進(jìn)制編碼長(zhǎng)度為位. 首先在消息末尾補(bǔ)上一位"1", 然后再補(bǔ)上個(gè)"0", 其中為下列方程的最小非負(fù)整數(shù)

舉個(gè)例子, 以消息"abc"為例顯示補(bǔ)位的過(guò)程.

a,b,c對(duì)應(yīng)的ASCII碼和二進(jìn)制編碼分別如下:

原始字符 ASCII碼 二進(jìn)制編碼 a 97 01100001 b 98 01100010 c 99 01100011

因此, 原始信息"abc"的二進(jìn)制編碼為:01100001 01100010 01100011, 第一步補(bǔ)位, 首先在消息末尾補(bǔ)上一位"1", 結(jié)果為:?01100001 01100010 01100011 1; 然后進(jìn)行第二步的補(bǔ)位, 因?yàn)? 可以得到, 在第一步補(bǔ)位后的消息后面再補(bǔ)423個(gè)"0", 結(jié)果如下:

最后還需要在上述字節(jié)串后面繼續(xù)進(jìn)行補(bǔ)碼, 這個(gè)時(shí)候補(bǔ)的是原消息"abc"的二進(jìn)制長(zhǎng)度的64位二進(jìn)制表示形式, 補(bǔ)完以后的結(jié)果如下:

最終補(bǔ)完以后的消息二進(jìn)制位數(shù)長(zhǎng)度是512的倍數(shù).

這里需要注意的兩點(diǎn)是不管原來(lái)的消息長(zhǎng)度是多少, 即使長(zhǎng)度已經(jīng)滿足對(duì)512取模后余數(shù)是448,補(bǔ)位也必須要進(jìn)行,這時(shí)要填充512位. 另外, 考慮到最后要將消息長(zhǎng)度轉(zhuǎn)換為64位二進(jìn)制編碼, 因此, 長(zhǎng)度的必須小于, 絕大多數(shù)情況, 這個(gè)足夠大了.

  • 將補(bǔ)碼處理后的消息以512位為單位分塊為:?, 其中第個(gè)消息塊的前32位表示為:?, 后面32位為:?, 以此類推, 最后32位的消息塊可表示為:?. 我們采用Big endian約定對(duì)數(shù)據(jù)進(jìn)行編碼, 即認(rèn)為第一個(gè)字節(jié)是最高位字節(jié), 因此, 對(duì)于每一個(gè)32位字節(jié), 最最左邊的比特是最大的比特位.

摘要計(jì)算主循環(huán)

哈希計(jì)算算法如下:

  • ?(?= 補(bǔ)碼后消息塊個(gè)數(shù))
    • 用第個(gè)中間哈希值來(lái)對(duì)?進(jìn)行初始化, 當(dāng)時(shí), 就使用初始化哈希, 即:

  • 應(yīng)用SHA256壓縮函數(shù)來(lái)更新
      • 計(jì)算(具體定義如下)

  • 計(jì)算第個(gè)中間哈希值

  • 為最終需要的哈希。

邏輯函數(shù)定義

SHA256算法當(dāng)中所使用到的6個(gè)邏輯函數(shù)如下:每個(gè)函數(shù)都對(duì)32位字節(jié)進(jìn)行操縱,并輸出32位字節(jié)。

擴(kuò)展消息塊通過(guò)以下方式進(jìn)行計(jì)算:

圖形表示

SHA256壓縮函數(shù)的圖形表示如下:

擴(kuò)展消息塊的求解算法可以表示如下:

SHA偽代碼

Note 1: All variables are 32 bit unsigned integers and addition is calculated modulo 232 Note 2: For each round, there is one round constant k[i] and one entry in the message schedule array w[i], 0 ≤ i ≤ 63 Note 3: The compression function uses 8 working variables, a through h Note 4: Big-endian convention is used when expressing the constants in this pseudocode,and when parsing message block data from bytes to words, for example,the first word of the input message "abc" after padding is 0x61626380Initialize hash values: (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19): h0 := 0x6a09e667 h1 := 0xbb67ae85 h2 := 0x3c6ef372 h3 := 0xa54ff53a h4 := 0x510e527f h5 := 0x9b05688c h6 := 0x1f83d9ab h7 := 0x5be0cd19Initialize array of round constants: (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311): k[0..63] :=0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2Pre-processing (Padding): begin with the original message of length L bits append a single '1' bit append K '0' bits, where K is the minimum number >= 0 such that L + 1 + K + 64 is a multiple of 512 append L as a 64-bit big-endian integer, making the total post-processed length a multiple of 512 bitsProcess the message in successive 512-bit chunks: break message into 512-bit chunks for each chunkcreate a 64-entry message schedule array w[0..63] of 32-bit words(The initial values in w[0..63] don't matter, so many implementations zero them here)copy chunk into first 16 words w[0..15] of the message schedule arrayExtend the first 16 words into the remaining 48 words w[16..63] of the message schedule array:for i from 16 to 63s0 := (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor (w[i-15] rightshift 3)s1 := (w[i- 2] rightrotate 17) xor (w[i- 2] rightrotate 19) xor (w[i- 2] rightshift 10)w[i] := w[i-16] + s0 + w[i-7] + s1Initialize working variables to current hash value:a := h0b := h1c := h2d := h3e := h4f := h5g := h6h := h7Compression function main loop:for i from 0 to 63S1 := (e rightrotate 6) xor (e rightrotate 11) xor (e rightrotate 25)ch := (e and f) xor ((not e) and g)temp1 := h + S1 + ch + k[i] + w[i]S0 := (a rightrotate 2) xor (a rightrotate 13) xor (a rightrotate 22)maj := (a and b) xor (a and c) xor (b and c)temp2 := S0 + majh := gg := ff := ee := d + temp1d := cc := bb := aa := temp1 + temp2Add the compressed chunk to the current hash value:h0 := h0 + ah1 := h1 + bh2 := h2 + ch3 := h3 + dh4 := h4 + eh5 := h5 + fh6 := h6 + gh7 := h7 + hProduce the final hash value (big-endian): digest := hash := h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7

SHA256代碼實(shí)現(xiàn)

下面是基于上述偽代碼用go語(yǔ)言對(duì)SHA256進(jìn)行的實(shí)現(xiàn).

package mainimport ("encoding/binary" )func wikiSha256(message []byte) [32]byte {//初始哈希值h0 := uint32(0x6a09e667)h1 := uint32(0xbb67ae85)h2 := uint32(0x3c6ef372)h3 := uint32(0xa54ff53a)h4 := uint32(0x510e527f)h5 := uint32(0x9b05688c)h6 := uint32(0x1f83d9ab)h7 := uint32(0x5be0cd19)//計(jì)算過(guò)程當(dāng)中用到的常數(shù)k := [64]uint32{0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}padded := append(message, 0x80)if len(padded) % 64 < 56 {suffix := make([]byte, 56 - (len(padded) % 64))padded = append(padded, suffix...)} else {suffix := make([]byte, 64 + 56 - (len(padded) % 64))padded = append(padded, suffix...)}msgLen := len(message) * 8bs := make([]byte, 8)binary.BigEndian.PutUint64(bs, uint64(msgLen))padded = append(padded, bs...)broken := [][]byte{};for i := 0; i < len(padded) / 64; i++ {broken = append(broken, padded[i * 64: i * 64 + 63])}//主循環(huán)for _, chunk := range broken {w := []uint32{}for i := 0; i < 16; i++ {w = append(w, binary.BigEndian.Uint32(chunk[i * 4:i * 4 + 4]))}w = append(w, make([]uint32, 48)...)//W消息區(qū)塊處理for i := 16; i < 64; i++ {s0 := rightRotate(w[i - 15], 7) ^ rightRotate(w[i - 15], 18) ^ (w[i - 15] >> 3)s1 := rightRotate(w[i - 2], 17) ^ rightRotate(w[i - 2], 19) ^ (w[i - 2] >> 10)w[i] = w[i - 16] + s0 + w[i - 7] + s1}a := h0b := h1c := h2d := h3e := h4f := h5g := h6h := h7//應(yīng)用SHA256壓縮函數(shù)更新a,b,...,hfor i := 0; i < 64; i++ {S1 := rightRotate(e, 6) ^ rightRotate(e, 11) ^ rightRotate(e, 25)ch := (e & f) ^ ((^e) & g)temp1 := h + S1 + ch + k[i] + w[i]S0 := rightRotate(a, 2) ^ rightRotate(a, 13) ^ rightRotate(a, 22)maj := (a & b) ^ (a & c) ^ (b & c)temp2 := S0 + majh = gg = ff = ee = d + temp1d = cc = bb = aa = temp1 + temp2}h0 = h0 + ah1 = h1 + bh2 = h2 + ch3 = h3 + dh4 = h4 + eh5 = h5 + fh6 = h6 + gh7 = h7 + h}hashBytes := [][]byte{iToB(h0), iToB(h1), iToB(h2), iToB(h3), iToB(h4), iToB(h5), iToB(h6), iToB(h7)}hash := []byte{}hashArray := [32]byte{}for i := 0; i < 8; i ++ {hash = append(hash, hashBytes[i]...)}copy(hashArray[:], hash[0:32])return hashArray }func iToB(i uint32) []byte {bs := make([]byte, 4)binary.BigEndian.PutUint32(bs, i)return bs }//循環(huán)右移函數(shù) func rightRotate(n uint32, d uint) uint32 {return (n >> d) | (n << (32 - d)) }

總結(jié)

以上是生活随笔為你收集整理的SHA256算法原理及其实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。