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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

SHA256算法原理介绍以及实现

發布時間:2023/12/10 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SHA256算法原理介绍以及实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近在學習一些算法加解密方面的知識,之前對SHA256算法不是特別理解,看了許多其他大佬關于SHA256算法的詳解和實現過程,終于是稍微理解了一些,真的非常感謝,這里整合了這些材料,寫這篇學習筆記的目的是把自己學習SHA256算法的過程記錄下來,方便下次查看。當然,如果能給有需要的小伙伴提供一些思路啟發自然再好不過。

1.SHA算法概述

SHA(Secure Hash Algorithm安全散列算法)是一個密碼散列函數的家族,是FIPS(聯邦信息處理標準 Federal Information Processing Standards)
所認證的安全散列算法。能計算出一個數字消息所對應到的,長度固定的字符串(又稱消息摘要)的算法。

一個n位的哈希函數就是一個從任意長的消息到n位哈希值的映射,一個n位的加密哈希函數就是一個單向的、避免碰撞的n位哈希函數。這樣的函數是目前在數字簽名密碼保護當中極為重要的手段。

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

SHA-2,名稱來自于安全散列算法2(英語:Secure Hash Algorithm 2)的縮寫,一種密碼散列函數算法標準,由美國國家安全局研發,由美國國家標準與技術研究院(NIST)在2001年發布。屬于SHA算法之一,是SHA-1的后繼者。其下又可再分為六個不同的算法標準,包括了:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。
這些變體除了生成摘要的長度 、循環運行的次數等一些微小差異外,算法的基本結構是一致的。

2.SHA256算法簡介

說到SHA256,其字面意思便是,對于任意長度的消息,SHA256都會產生一個256位的哈希值,稱作消息摘要。這個摘要相當于是個長度為32個字節的數組,共256位,通常由一個長度為64的十六進制字符串來表示,其中1個字節=8位,一個十六進制的字符的長度為4位。

SHA256對消息做Hash摘要,如下實例:

1122334455667788 //消息

該消息經過哈希函數SHA256得到的消息摘要為:

1DCE6604591EFB439D5E87418A1D00DBFD014327D8C4DEA862815714B76AE9A5 //Hash值

這里原來的8字節消息“1122334455667788”經SHA256算法運算后得到一個32字節的消息摘要,且對消息做細小的改變,生成的Hash都會發生巨大改變,跟原先的值完全不同,如下:

0122334455667788 //消息 2B85738907AB2C4C39DFFFDD5328A694F4DF04B75E6F482F832279C6BBFE8530 //Hash值

僅僅變換了一位的值,Hash值發生了巨大的改變。

3.SHA256算法原理細述

為了更好的理解SHA256的原理,這里首先將算法中可以單獨抽出的模塊,包括常量的初始化信息預處理使用到的邏輯運算分別進行介紹,甩開這些理解上的障礙后,一起來探索SHA256算法的主體部分,即消息摘要是如何計算的。

3.1常量初始化

SHA256算法中用到了8個哈希初值以及64個哈希常量,64個哈希常量參與到后面的哈希值計算。
SHA256算法的8個哈希初值為:

H1 := 0x6a09e667 H2 := 0xbb67ae85 H3 := 0x3c6ef372 H4 := 0xa54ff53a H5 := 0x510e527f H6 := 0x9b05688c H7 := 0x1f83d9ab H8 := 0x5be0cd19

初始哈希值H(1-8)取自自然數中前面8個質數(2,3,5,7,11,13,17,19)的平方根的小數部分, 并且取前面的32位. 下面舉個例子: [公式]小數部分約為0.414213562373095048, 而其中

于是, 質數2的平方根的小數部分取前32位就對應0x6a09e667。以此類推可得8個初始哈希值。

SHA256算法的64個哈希常量為:

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

與8個初始哈希值獲取的方式類似,64個哈希常量取自自然數中前面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…)的立方根的小數部分, 并且取前面的32位。

3.2信息預處理

SHA256算法中的預處理就是在想要Hash的消息后面補充需要的信息,使整個消息滿足指定的結構。

信息的預處理分為兩個步驟:附加填充比特附加長度

STEP1:附加填充比特

在報文末尾進行填充,使報文長度在對512取模以后的余數是448

填充是這樣進行的:先補第一個比特為1,然后都補0,直到長度滿足對512取模后余數是448。

需要注意的是,信息必須進行填充,也就是說,即使長度已經滿足對512取模后余數是448,補位也必須要進行,這時要填充512個比特。

因此,填充是至少補一位,最多補512位。

**例:**以信息“abc”為例顯示補位的過程。
a,b,c對應的ASCII碼分別是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

為什么是448?

因為在第一步的預處理后,第二步會再附加上一個64bit的數據,用來表示原始報文的長度信息。而448+64=512,正好拼成了一個完整的結構。

STEP2:附加長度值

附加長度值就是將原始數據(第一步填充前的消息)的長度信息補到已經進行了填充操作的消息后面。

SHA256用一個64位的數據來表示原始消息的長度。

因此,通過SHA256計算的消息長度必須要小于$ 2^64 $,當然絕大多數情況這足夠大了。

長度信息的編碼方式為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 00000018

3.3邏輯運算

SHA256散列函數中涉及的操作全部是邏輯的位運算

包括如下的邏輯函數:

這里的一些運算:

邏輯運算含義
按位“與”
?按位“與”
按位“異或”
Sn循環右移n個bit
Rn右移n個bit

3.4邏輯運算

現在來介紹SHA256算法的主體部分,即消息摘要是如何計算的。

首先:將消息分解成512-bit大小的塊

假設消息M可以被分解為n個塊,于是整個算法需要做的就是完成n次迭代,n次迭代的結果就是最終的哈希值,即256bit的數字摘要。

一個256-bit的摘要的初始值H0,經過第一個數據塊進行運算,得到H1,即完成了第一次迭代

H1經過第二個數據塊得到H2,……,依次處理,最后得到Hn,Hn即為最終的256-bit消息摘要

將每次迭代進行的映射用$ Map(H_{i-1}) = H_{i} $表示,于是迭代可以更形象的展示為:

圖中256-bit的Hi被描述8個小塊,這是因為SHA256算法中的最小運算單元稱為“字”(Word),一個字是32位。

此外,第一次迭代中,映射的初值設置為前面介紹的8個哈希初值,如下圖所示:

下面開始介紹每一次迭代的內容,即映射$ Map(H_{i-1}) = H_{i} $的具體算法

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(H_{i-1}) = H_{i} $ 包含了64次加密循環

即進行64次加密循環即可完成一次迭代

每次加密循環可以由下圖描述:

由上圖可知,ABCDEFGH這8個字(word)在按照一定的規則進行更新,規則如下:

原數據塊為ABCDEFGH,則一次循環為:

A'=H+Σ1(E)+Ch(E,F,G)+M(t)+K(t)+Ma(A,B,C)+Σ0(A)B'=AC'=BD'=CE'=D+H+Σ1(E)+Ch(E,F,G)+M(t)+K(t)F'=EG'=FH'=G

其中深藍色方塊是事先定義好的非線性邏輯函數,上文已經做過鋪墊
紅色田字方塊代表 mod $ 2^{32} $ addition,即將兩個數字加在一起,如果結果大于$ 2^{32} ,你必須除以 2^{32} $并找到余數。當然,如果我們之定義了數據為32位即四字節,就不必去刻意取余,前面的循環表示A’-H’便是如此。

ABCDEFGH一開始的初始值分別為$ H_{i-1}(0),H_{i-1}(1),…,H_{i-1}(7) $。

Kt是第t個密鑰,對應我們上文提到的64個常量。

Wt是本區塊產生第t個word。原消息被切成固定長度512-bit的區塊,對每一個區塊,產生64個word,通過重復運行循環n次對ABCDEFGH這八個字循環加密。

最后一次循環所產生的八個字合起來即是第i個塊對應到的散列字符串$ H_{i} $。

4.SHA256算法實現

4.1邏輯函數

typedef unsigned char BYTE; // 8位 typedef unsigned int WORD; // 32位數據,4字節表示一個字typedef struct {BYTE data[64]; // current 512-bit chunk of message data, just like a bufferWORD datalen; // sign the data length of current chunkunsigned long long bitlen; // the bit length of the total messageWORD state[8]; // store the middle state of hash abstract } SHA256_CTX; //邏輯函數如下 /* ∧:按位“與” !:按位“補” ⊕:按位“異或” Sn:循環右移n個bit Rn:右移n個bit */ #define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b)))) //循環右移 #define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) //Ma(x,y,z)=(x∧y)⊕(x∧z)⊕(y∧z) #define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22)) //Σ0(x)=S2(x)⊕S13(x)⊕S22(x) #define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25)) //Σ1(x)=S6(x)⊕S11(x)⊕S25(x) #define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3)) //σ0(x)=S7(x)⊕S18(x)⊕R3(x) #define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10)) //σ1(x)=S17(x)⊕S19(x)⊕R10(x)

4.2數據塊處理得到Hash值

//對一個長度為512bit的數據塊進行操作,將其轉換成Hash值 void sha256_transform(SHA256_CTX *ctx, const BYTE data[]) {//abcdefgh代表ABCDEFGH八個字,t1t2存放中間運算值WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];//這里的m表示的是64個字(一個字32位)// initialization for (i = 0, j = 0; i < 16; ++i, j += 4)m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);//將數據塊劃分成16個32bit的字,存放到m的前16個字中for ( ; i < 64; ++i)m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];//其余的字:16-63則按照公式Mt=σ1(M(t-2))+M(t-7)+σ0(M(t-15))+M(t-16)計算 //第一次迭代,映射初值設為8個哈希初值a = ctx->state[0];b = ctx->state[1];c = ctx->state[2];d = ctx->state[3];e = ctx->state[4];f = ctx->state[5];g = ctx->state[6];h = ctx->state[7];/*原數據塊為ABCDEFGH,則一次循環為:A'=H+Σ1(E)+Ch(E,F,G)+M(t)+K(t)+Ma(A,B,C)+Σ0(A)B'=AC'=BD'=CE'=D+H+Σ1(E)+Ch(E,F,G)+M(t)+K(t)F'=EG'=FH'=G*///64次加密循環for (i = 0; i < 64; ++i) {//這里就不必去除以2^32取余數了,因為a-t2長度均為32bit,和超出2^32,超出部分便會被舍棄t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];//SHA256要求的一個運算t2 = EP0(a) + MAJ(a,b,c);h = g;g = f;f = e;e = d + t1;d = c;c = b;b = a;a = t1 + t2;}//整合hashctx->state[0] += a;ctx->state[1] += b;ctx->state[2] += c;ctx->state[3] += d;ctx->state[4] += e;ctx->state[5] += f;ctx->state[6] += g;ctx->state[7] += h; } void sha256_final(SHA256_CTX *ctx, BYTE hash[]) {WORD i;i = ctx->datalen;// Pad whatever data is left in the buffer.if (ctx->datalen < 56) {ctx->data[i++] = 0x80; // pad 10000000 = 0x80while (i < 56)ctx->data[i++] = 0x00;}else {ctx->data[i++] = 0x80;while (i < 64)ctx->data[i++] = 0x00;sha256_transform(ctx, ctx->data);memset(ctx->data, 0, 56);}//將消息的總長度(以比特為單位)追加到填充并進行轉換//56-638個字節表示位長,按大端模式(低地址放高位)存放ctx->bitlen += ctx->datalen * 8;ctx->data[63] = ctx->bitlen;ctx->data[62] = ctx->bitlen >> 8;ctx->data[61] = ctx->bitlen >> 16;ctx->data[60] = ctx->bitlen >> 24;ctx->data[59] = ctx->bitlen >> 32;ctx->data[58] = ctx->bitlen >> 40;ctx->data[57] = ctx->bitlen >> 48;ctx->data[56] = ctx->bitlen >> 56;sha256_transform(ctx, ctx->data);// copying the final state to the output hash(use big endian).//hash[i]類型為Byte,stx->state[i]類型為WORD(4個Byte)for (i = 0; i < 4; ++i) {//取左高8位,按大端模式,hash[0]為低地址,應取高位,以此類推hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000FF;hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000FF;hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000FF;hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000FF;hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000FF;hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000FF;hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000FF;hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000FF;} }

5.參考

本篇學習筆記主要參考整合的資料如下:
SHA256算法原理詳解
基于STM32的C語言SHA256加密算法
一文讀懂SHA256算法原理及其實現

總結

以上是生活随笔為你收集整理的SHA256算法原理介绍以及实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。