Table of Contents
哈希函式的基本介紹(SHA-256,MD-5等)
為什么要使用哈希函式?
確定性地加擾資料
輸入無關緊要,輸出大小相同
它們如何作業?
免責宣告
什么是MD5哈希?
SHA-2的作業原理(SHA-256)
什么是哈希函式?
SHA-2和SHA-256
SHA-256“ hello world”;步驟1 –預處理
步驟2 –初始化哈希值(h)
步驟3 –初始化舍入常數(k)
步驟4 –區塊回圈
步驟5 –建立郵件時間表(w)
步驟6 –壓縮
步驟7 –修改最終值
第8步-連接最終哈希
偽碼
Scrypt哈希的基本介紹
什么是Scrypt?
為什么不使用密碼直接加密?
加密屬性
什么是BCrypt?
OWASP - 開放式Web應用程式安全專案
相關文章
Hash,一般翻譯做散列、雜湊,或音譯為哈希,是把任意長度的輸入(又叫做預映射pre-image)通過散列演算法變換成固定長度的輸出,該輸出就是散列值,這種轉換是一種壓縮映射,也就是,散列值的空間通常遠小于輸入的空間,不同的輸入可能會散列成相同的輸出,所以不可能從散列值來確定唯一的輸入值,簡單的說就是一種將任意長度的訊息壓縮到某一固定長度的訊息摘要的函式,
哈希函式根據選擇的演算法回傳輸入資料的128位,160位,256位或512位哈希,

表示要散列的字串值的運算式,該運算式可以回傳任何內置或不同的資料型別,唯一型別被視為其源資料型別,如果值為數字或日期時間,則在評估函式之前,將其隱式轉換為VARCHAR,如果值為XML,則在對函式求值之前執行隱式的XMLSERIALIZE到CLOB(2G)CCSID 1208,
| 功能名稱 | 演算法 | 結果大小 | 回傳值數 | 結果長度 | HASH函式中使用的對應演算法值 |
|---|---|---|---|---|---|
| HASH_MD5 | MD5 | 128位 | 2^128 | 16 | 0 |
| HASH_SHA1 | SHA1 | 160位 | 2^160 | 20 | 1 |
| HASH_SHA256 | SHA-256 | 256位 | 2^256 | 32 | 2 |
| HASH_SHA512 | SHA-512 | 512位 | 2^512 | 64 | 3 |
空格會影響哈希;帶有尾隨空格的固定長度字串將產生與沒有尾隨空格的可變長度字串不同的結果,運算式的CCSID 可以使比較相等的字串生成不同的結果值,
SHA1和MD5演算法均已發現安全漏洞,您可以在適用的法規遵從性檔案中找到可接受的哈希演算法,例如美國國家標準技術研究院(NIST)特殊出版物800-131A,
語法替代:具有單個引數的HASH函式類似于HASH_MD5,可以為HASH指定第二個引數,以指示要使用的演算法,演算法值顯示在表1中,第二個引數可以是一個運算式,該運算式必須回傳任何內置數字,字串或圖形字串資料型別的值,在評估函式之前,將字串引數轉換為整數,HASH的結果資料型別為VARBINARY,如果只有一個引數,則結果的length屬性為16,如果第二個引數由整數常量指定,則結果的length屬性為表1中所示的結果長度,,否則,結果的length屬性為64,如果任一引數可以為null,則結果可以為null,如果任何一個引數為null,則結果為null值,
例子
使用MD5演算法生成哈希資料,
VALUES HEX(HASH_MD5('ABCDEFGHIJKLMNOPQRSTUVWXYZ'))
回傳以下值:
5156BECBC019E3F0F9520B143435427E
使用SHA1演算法生成哈希資料,
VALUES HEX(HASH_SHA1('ABCDEFGHIJKLMNOPQRSTUVWXYZ'))
回傳以下值:
55324E3DD1FA95040F65709D193E82575237EF86
使用SHA-256演算法生成哈希資料,
VALUES HEX(HASH_SHA256('ABCDEFGHIJKLMNOPQRSTUVWXYZ'))
回傳以下值:
011F7AD1ECD8E5A4CC8533D1ECD497DC5D95E848B14F8BCFD56A73D7F41843E2
使用SHA-512演算法生成哈希資料,
VALUES HEX(HASH_SHA512('ABCDEFGHIJKLMNOPQRSTUVWXYZ'))
回傳以下值:
D8AC4B838921A83C4207B62B8B63628F8FBE836EB012167310331FFC070FC977D224F39148
8806CB1FE2AA9C8C739E5104CAD1C4C6E97967DA6223D657CD9295
哈希函式的基本介紹(SHA-256,MD-5等)
https://dev.to/wagslane/very-basic-intro-to-hash-functions-sha-256-md-5-etc-399j
這將是哈希函式的基本介紹,我將假定我的大多數讀者都在這里,以了解為什么使用哈希函式以及它們為什么起作用的基本概念,我的目標是從一般意義上解釋它,我將省略證明和實作細節,而將重點放在高級原則上,
為什么要使用哈希函式?
哈希函式在整個Internet上使用,以安全地存盤密碼,查找重復記錄,快速存盤和檢索資料等等,例如,Qvault使用哈希將主密碼擴展為專用加密密鑰,
- https://en.wikipedia.org/wiki/Hash\_function#Uses
- https://en.wikipedia.org/wiki/Hash_function#Uses
我想關注散列函式的幾個重要功能,可以說是最重要的功能,
- 哈希函式確定性地加擾資料
- 無論輸入如何,哈希函式的輸出始終具有相同的大小
- 無法從加擾資料中檢索原始資料(單向功能)
確定性地加擾資料
想想一個魔方,
我從無雜亂無章的多維資料集開始,如果我開始隨機扭曲,到最后,我將得到的東西與我剛開始的東西幾乎沒有任何相似之處,另外,如果我要重新開始并做完全相同的一系列動作,我將能夠反復獲得完全相同的結果,即使結果may_出現_random,也完全不是,這就是確定性*的意思,
確定性對于安全存盤密碼很重要,例如,假設我的密碼是“ iLoveBitcoin”
我可以使用哈希函式對其進行加擾:
iLoveBitcoin→“ 2f5sfsdfs5s1fsfsdf98ss4f84sfs6d5fs2d1fdf15”
現在,如果有人要查看加密版本,他們將不知道我的原始密碼!這很重要,因為這意味著作為網站開發人員,我只需要存盤用戶密碼的哈希(加密資料)即可進行驗證,當用戶注冊時,我對密碼進行哈希處理并將其存盤在資料庫中,當用戶登錄時,我只是對他們鍵入的內容進行哈希處理,然后比較兩個哈希值,由于給定的輸入始侄訓產生相同的哈希,因此每次都有效,
如果網站以純文本形式(而不是散列的形式)存盤密碼,則將嚴重違反安全性,如果有人要入侵該站點的資料庫并找到所有使用純文本密碼存盤的電子郵件,則他們可以使用這些組合并在其他網站上嘗試使用,
輸入無關緊要,輸出大小相同
如果我對單個單詞進行哈希處理,則輸出將具有一定的大小(對于SHA-256,則為特定的哈希函式,大小為256位),如果我對一本書進行哈希處理,輸出將是相同大小,
這是另一個重要功能,因為它可以節省我們的計算時間,一個經典的例子是使用哈希作為資料映射中的鍵,資料映射是計算機科學中用于存盤資料的簡單結構,

當程式將資料存盤在映射中時,鍵和值將被賦予映射,當程式要訪問該值時,它可以將適當的鍵提供給映射并接收相應的值,資料映射之所以不錯,是因為它們可以立即找到資料,_鍵用作計算機可以立即找到的地址,而不是花費數小時來搜索數百萬條記錄,
因為鍵就像地址,所以不能太大,如果我想將書籍存盤在資料映射中,則可以對書籍的內容進行哈希處理并將哈希值用作鍵,作為程式員,我可以簡單地使用哈希來查找書中的內容,而不必嘗試按標題,作者等對數千條記錄進行排序,
它們如何作業?
這是撰寫本文的真正挑戰,我將使其保持極其簡單,并省略實際的實作細節,同時讓您基本了解計算機在處理某些資料時的實際作業,
讓我們來看一下我正在為這個演示動態撰寫的示例演算法 LANEHASH:
- 我們從一些要散列的資料開始
iLove位元幣
- 我將字母和數字轉換為1和0(計算機中的所有資料都存盤在1和0中,不同的1和0表示不同的字母)
iLoveBitcoin→100010100000101111
- 在這一點上,我們經歷了各種預定步驟來轉換我們的資料,這些步驟可以是任何步驟,重要的是,每當我們使用LANEHASH時,我們都需要使用相同的步驟,以便我們的演算法具有確定性,
- 我們將前四位從左側移到右側
1000 10100000101111→10100000101111 1000
- 我們隔著一點
1 0 1 0 0 0 0 0 1 0 1 1 1 1 1 0 0 0→110011110&000001100
- 我們將這兩部分轉換為以10為底的數字,以10為基數是我們在學校都學過的“正常”數字系統,(所有二進制資料實際上只是數字,您可以在其他地方在線查找如何將二進制輕松轉換為以10為基數)
110011110→414
000001100→12
- 我們將兩個數字相乘
414 * 12 = 4968
- 我們對該數字求平方
4968 ^ 2 = 24681024
- 我們將該數字轉換回二進制
24681024→1011110001001101001000000
- 我們從右側切掉9位以得到16位
1011110001001101 001000000 →1011110001001101
- 我們將二進制資料轉換回英語
1011110001001101→“ 8sj209dsns02k2”
如您所見,如果在開頭以相同的單詞開頭,那么在結尾始終將得到相同的輸出,但是,即使您只更改一個字母,結果也將發生巨大變化,
免責宣告
在我從英語轉換為二進制,以及從二進制轉換為英語的步驟中,我沒有遵循任何模式,不要讓那讓您感到困惑,有很多不同的方法可以將二進制資料轉換為英語,然后再轉換回英語,我只是不想在本文中對此感到困惑,以下是有關該主題的一些參考資料:
https://zh.wikipedia.org/wiki/ASCII
https://zh.wikipedia.org/wiki/Unicode
什么是MD5哈希?
https://www.md5hashgenerator.com/
通過采用任意長度的字串并將其編碼為128位指紋來創建MD5哈希,使用MD5演算法編碼相同的字串將始終導致相同的128位哈希輸出,當在資料庫(例如流行的MySQL)中存盤密碼,信用卡號或其他敏感資料時,MD5哈希通常與較小的字串一起使用,該工具提供了一種快速簡便的方法,可以從長度最多為256個字符的簡單字串中編碼MD5哈希,
MD5哈希還用于確保檔案的資料完整性,由于MD5哈希演算法始終為相同的給定輸入產生相同的輸出,因此用戶可以將源檔案的哈希值與目標檔案的新創建的哈希值進行比較,以檢查其是否完整且未修改,
MD5哈希不是加密的,它只是給定輸入的指紋,但是,這是單向事務,因此幾乎不可能對MD5哈希進行反向工程以檢索原始字串,
SHA-2的作業原理(SHA-256)
https://dev.to/wagslane/how-sha-2-works-step-by-step-sha-256-11ci
https://qvault.io/2020/07/08/how-sha-2-works-step-by-step-sha-256/
SHA-2(安全哈希演算法2)是SHA-256的一部分,是其中最流行的哈希演算法之一,在本文中,我們將盡可能簡單地分解演算法的每個步驟,并手工完成一個真實的示例,
SHA-2以其安全性(它沒有像SHA-1一樣崩潰)和速度而聞名,在未生成密鑰的情況下(例如挖礦位元幣),像SHA-2這樣的快速哈希演算法通常占據上風,
什么是哈希函式?
如果您想全面了解散列函式,請在此處閱讀,也就是說,為了前進,讓我們回顧一下哈希函式的三個主要目的:
- 確定性地加擾資料
- 接受任意長度的輸入并輸出固定長度的結果
- 不可逆地操縱資料,輸入不能從輸出派生
SHA-2和SHA-256
SHA-2是一種演算法,是有關如何對資料進行哈希處理的通用思想,SHA-256設定其他常量,這些常量定義SHA-2演算法的行為,這樣的常數之一就是輸出大小,“ 256”和“ 512”以位元為單位表示它們各自的輸出摘要大小,
讓我們逐步介紹一下SHA-256的示例,
SHA-256“ hello world”;步驟1 –預處理
將“ hello world”轉換為二進制:
01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
01110010 01101100 01100100
附加一個1:
01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
01110010 01101100 01100100 1
用0填充,直到資料為512的整數倍,然后減去64位(本例中為448位):
01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
01110010 01101100 01100100 10000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
在末尾附加64位,其中64位是big-endian整數,表示二進制原始輸入的長度,在我們的例子中,為88,或二進制為“ 1011000”,
01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
01110010 01101100 01100100 10000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 01011000
現在我們有了輸入,它將始終被512平均整除,
步驟2 –初始化哈希值(h)
現在,我們創建8個哈希值,這些是硬編碼的常數,代表前8個素數的平方根的小數部分的前32位:2、3、5、7、11、13、17、19
h0 := 0x6a09e667
h1 := 0xbb67ae85
h2 := 0x3c6ef372
h3 := 0xa54ff53a
h4 := 0x510e527f
h5 := 0x9b05688c
h6 := 0x1f83d9ab
h7 := 0x5be0cd19
步驟3 –初始化舍入常數(k)
與第2步類似,我們正在創建一些常量(在此處了解有關常量以及何時使用它們的更多資訊),這次有64個,每個值(0-63)是前64個素數(2 – 311)的立方根的小數部分的前32位,
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
步驟4 –區塊回圈
對于來自我們輸入的每個512位“塊”資料,將執行以下步驟,在我們的案例中,由于“ hello world”非常短,因此我們只有一個塊,在回圈的每次迭代中,我們將使哈希值h0-h7突變,這將是最終輸出,
步驟5 –建立郵件時間表(w)
將步驟1中的輸入資料復制到一個新陣列中,其中每個條目都是一個32位字:
01101000011001010110110001101100 01101111001000000111011101101111
01110010011011000110010010000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000001011000
再添加48個初始化為零的單詞,這樣我們就有了一個陣列w [0…63]
01101000011001010110110001101100 01101111001000000111011101101111
01110010011011000110010010000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000001011000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
...
...
00000000000000000000000000000000 00000000000000000000000000000000
使用以下演算法在陣列末尾修改零位索引:
對于我從W [16 ... 63]:
s0 =(w [i-15]右旋7)xor(w [i-15]右旋18)xor(w [i-15]右移3)
s1 =(w [i-2]右旋17)xor(w [i-2]右旋19)xor(w [i-2]右移10)
w [i] = w [i-16] + s0 + w [i-7] + s1
s0 = (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] + s1
讓我們做w [16]以便我們看一下它是如何作業的:
w[1] rightrotate 7:
01101111001000000111011101101111 -> 11011110110111100100000011101110
w[1] rightrotate 18:
01101111001000000111011101101111 -> 00011101110110111101101111001000
w[1] rightshift 3:
01101111001000000111011101101111 -> 00001101111001000000111011101101
s0 = 11011110110111100100000011101110 XOR 00011101110110111101101111001000 XOR 00001101111001000000111011101101
s0 = 11001110111000011001010111001011
w[14] rightrotate 17:
00000000000000000000000000000000 -> 00000000000000000000000000000000
w[14] rightrotate19:
00000000000000000000000000000000 -> 00000000000000000000000000000000
w[14] rightshift 10:
00000000000000000000000000000000 -> 00000000000000000000000000000000
s1 = 00000000000000000000000000000000 XOR 00000000000000000000000000000000 XOR 00000000000000000000000000000000
s1 = 00000000000000000000000000000000
w[16] = w[0] + s0 + w[9] + s1
w[16] = 01101000011001010110110001101100 + 11001110111000011001010111001011 + 00000000000000000000000000000000 + 00000000000000000000000000000000
// addition is calculated modulo 2^32
w[16] = 00110111010001110000001000110111
這使我們在訊息時間表(w)中留下了64個單詞:
01101000011001010110110001101100 01101111001000000111011101101111
01110010011011000110010010000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000000000000
00000000000000000000000000000000 00000000000000000000000001011000
00110111010001110000001000110111 10000110110100001100000000110001
11010011101111010001000100001011 01111000001111110100011110000010
00101010100100000111110011101101 01001011001011110111110011001001
00110001111000011001010001011101 10001001001101100100100101100100
01111111011110100000011011011010 11000001011110011010100100111010
10111011111010001111011001010101 00001100000110101110001111100110
10110000111111100000110101111101 01011111011011100101010110010011
00000000100010011001101101010010 00000111111100011100101010010100
00111011010111111110010111010110 01101000011001010110001011100110
11001000010011100000101010011110 00000110101011111001101100100101
10010010111011110110010011010111 01100011111110010101111001011010
11100011000101100110011111010111 10000100001110111101111000010110
11101110111011001010100001011011 10100000010011111111001000100001
11111001000110001010110110111000 00010100101010001001001000011001
00010000100001000101001100011101 01100000100100111110000011001101
10000011000000110101111111101001 11010101101011100111100100111000
00111001001111110000010110101101 11111011010010110001101111101111
11101011011101011111111100101001 01101010001101101001010100110100
00100010111111001001110011011000 10101001011101000000110100101011
01100000110011110011100010000101 11000100101011001001100000111010
00010001010000101111110110101101 10110000101100000001110111011001
10011000111100001100001101101111 01110010000101111011100000011110
10100010110101000110011110011010 00000001000011111001100101111011
11111100000101110100111100001010 11000010110000101110101100010110
步驟6 –壓縮
初始化變數a,b,c,d,e,f,g,h,并將它們分別設定為等于當前的哈希值,h0,h1,h2,h3,h4,h5,h6,h7
運行壓碩訓圈,壓碩訓圈將使a…h的值發生變化,壓碩訓圈如下:
我從0到63
S1 =(e右旋轉6)xor(e右旋轉11)xor(e右旋轉25)
ch =(e和f)xor((not e)和g)
temp1 = h + S1 + ch + k [i] + w [i]
S0 =(右旋轉2)xor(右旋轉13)xor(右旋轉22)
maj =(a和b)xor(a和c)xor(b和c)
temp2:= S0 + maj
h =克
g = f
e = d +溫度1
d = c
c = b
b = a
a = temp1 + temp2
S1 = (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 + maj
h = g
g = f
e = d + temp1
d = c
c = b
b = a
a = temp1 + temp2
讓我們進行第一次迭代,所有加法都是以2 ^ 32為模的:
a = 0x6a09e667 = 01101010000010011110011001100111
b = 0xbb67ae85 = 10111011011001111010111010000101
c = 0x3c6ef372 = 00111100011011101111001101110010
d = 0xa54ff53a = 10100101010011111111010100111010
e = 0x510e527f = 01010001000011100101001001111111
f = 0x9b05688c = 10011011000001010110100010001100
g = 0x1f83d9ab = 00011111100000111101100110101011
h = 0x5be0cd19 = 01011011111000001100110100011001
e rightrotate 6:
01010001000011100101001001111111 -> 11111101010001000011100101001001
e rightrotate 11:
01010001000011100101001001111111 -> 01001111111010100010000111001010
e rightrotate 25:
01010001000011100101001001111111 -> 10000111001010010011111110101000
S1 = 11111101010001000011100101001001 XOR 01001111111010100010000111001010 XOR 10000111001010010011111110101000
S1 = 00110101100001110010011100101011
e and f:
01010001000011100101001001111111
& 10011011000001010110100010001100 =
00010001000001000100000000001100
not e:
01010001000011100101001001111111 -> 10101110111100011010110110000000
(not e) and g:
10101110111100011010110110000000
& 00011111100000111101100110101011 =
00001110100000011000100110000000
ch = (e and f) xor ((not e) and g)
= 00010001000001000100000000001100 xor 00001110100000011000100110000000
= 00011111100001011100100110001100
// k[i] is the round constant
// w[i] is the batch
temp1 = h + S1 + ch + k[i] + w[i]
temp1 = 01011011111000001100110100011001 + 00110101100001110010011100101011 + 00011111100001011100100110001100 + 1000010100010100010111110011000 + 01101000011001010110110001101100
temp1 = 01011011110111010101100111010100
a rightrotate 2:
01101010000010011110011001100111 -> 11011010100000100111100110011001
a rightrotate 13:
01101010000010011110011001100111 -> 00110011001110110101000001001111
a rightrotate 22:
01101010000010011110011001100111 -> 00100111100110011001110110101000
S0 = 11011010100000100111100110011001 XOR 00110011001110110101000001001111 XOR 00100111100110011001110110101000
S0 = 11001110001000001011010001111110
a and b:
01101010000010011110011001100111
& 10111011011001111010111010000101 =
00101010000000011010011000000101
a and c:
01101010000010011110011001100111
& 00111100011011101111001101110010 =
00101000000010001110001001100010
b and c:
10111011011001111010111010000101
& 00111100011011101111001101110010 =
00111000011001101010001000000000
maj = (a and b) xor (a and c) xor (b and c)
= 00101010000000011010011000000101 xor 00101000000010001110001001100010 xor 00111000011001101010001000000000
= 00111010011011111110011001100111
temp2 = S0 + maj
= 11001110001000001011010001111110 + 00111010011011111110011001100111
= 00001000100100001001101011100101
h = 00011111100000111101100110101011
g = 10011011000001010110100010001100
f = 01010001000011100101001001111111
e = 10100101010011111111010100111010 + 01011011110111010101100111010100
= 00000001001011010100111100001110
d = 00111100011011101111001101110010
c = 10111011011001111010111010000101
b = 01101010000010011110011001100111
a = 01011011110111010101100111010100 + 00001000100100001001101011100101
= 01100100011011011111010010111001
整個計算又進行了63次,從而始終修改了變數ah,我們不會手工完成,但是我們將提供ender:
h0 = 6A09E667 = 01101010000010011110011001100111
h1 = BB67AE85 = 10111011011001111010111010000101
h2 = 3C6EF372 = 00111100011011101111001101110010
h3 = A54FF53A = 10100101010011111111010100111010
h4 = 510E527F = 01010001000011100101001001111111
h5 = 9B05688C = 10011011000001010110100010001100
h6 = 1F83D9AB = 00011111100000111101100110101011
h7 = 5BE0CD19 = 01011011111000001100110100011001
a = 4F434152 = 001001111010000110100000101010010
b = D7E58F83 = 011010111111001011000111110000011
c = 68BF5F65 = 001101000101111110101111101100101
d = 352DB6C0 = 000110101001011011011011011000000
e = 73769D64 = 001110011011101101001110101100100
f = DF4E1862 = 011011111010011100001100001100010
g = 71051E01 = 001110001000001010001111000000001
h = 870F00D0 = 010000111000011110000000011010000
步驟7 –修改最終值
在壓碩訓圈之后,但仍然在塊回圈中,我們通過將哈希值添加到變數ah中來修改哈希值,像往常一樣,所有加法都是模2 ^ 32,
h0 = h0 + a = 10111001010011010010011110111001
h1 = h1 + b = 10010011010011010011111000001000
h2 = h2 + c = 10100101001011100101001011010111
h3 = h3 + d = 11011010011111011010101111111010
h4 = h4 + e = 11000100100001001110111111100011
h5 = h5 + f = 01111010010100111000000011101110
h6 = h6 + g = 10010000100010001111011110101100
h7 = h7 + h = 11100010111011111100110111101001
第8步-連接最終哈希
最后但并非最不重要的一點是,將它們全部拍打!
digest = h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7
= B94D27B9934D3E08A52E52D7DA7DABFAC484EFE37A5380EE9088F7ACE2EFCDE9
做完了!我們已經仔細研究了SHA-256的每個步驟(沒有重復),🙂
偽碼
如果您想以偽代碼形式查看上面剛剛完成的所有步驟,那么直接來自WikiPedia:
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 0x61626380
Initialize 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 := 0x5be0cd19
Initialize 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, 0xc67178f2
Pre-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 bits
Process the message in successive 512-bit chunks:
break message into 512-bit chunks
for each chunk
create 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 array
Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array:
for i from 16 to 63
s0 := (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] + s1
Initialize working variables to current hash value:
a := h0
b := h1
c := h2
d := h3
e := h4
f := h5
g := h6
h := h7
Compression function main loop:
for i from 0 to 63
S1 := (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 + maj
h := g
g := f
f := e
e := d + temp1
d := c
c := b
b := a
a := temp1 + temp2
Add the compressed chunk to the current hash value:
h0 := h0 + a
h1 := h1 + b
h2 := h2 + c
h3 := h3 + d
h4 := h4 + e
h5 := h5 + f
h6 := h6 + g
h7 := h7 + h
Produce the final hash value (big-endian):
digest := hash := h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7
Scrypt哈希的基本介紹
https://dev.to/wagslane/very-basic-intro-to-the-scrypt-hash-7l5
這將是Scrypt哈希函式或更準確地說是KDF函式的基本介紹,我將假定我的大多數觀眾都在這里,以了解使用Scrypt的原因以及其作業原理的基礎,我的目標是從一般意義上解釋它,我將省略證明和實作細節,而將重點放在高級原則上,
在密碼學中,scrypt(發音為“ ess crypt” [1])是由Colin Percival創建的基于密碼的密鑰派生功能,最初用于Tarsnap在線備份服務,[2] 該演算法經過專門設計,使其需要大量記憶體,因此執行大規模自定義硬體攻擊的成本很高,IETF在2016年將scrypt演算法發布為RFC 7914,scrypt的簡化版本被許多加密貨幣用作作業量證明方案,首先由位于Tenebrix的名為ArtForz的匿名程式員實作,隨后不久又由Fairbrix和Litecoin實作,[3] -- https://en.wikipedia.org/wiki/Scrypt
什么是Scrypt?
Scrypt是一種設計緩慢的 哈希函式,其目的是獲取一些輸入資料,并為該資料創建指紋,但是要非常緩慢地進行,Qvault如何使用其真實案例的最佳示例之一,即,使用密碼并創建256位私有密鑰,
例如,假設您的密碼為password1234,通過使用scrypt,我們可以確定性地將其擴展為256位密鑰:
password1234- >
AwEEDA4HCwQFAA8D
AwwHDQwPDwUOBwoO
CQACAgUJBQ0JAAYN
BAMCDQ4JCQgLDwcG
DQMDDgMKAQsNBAkL
AwsACA ==
現在可以將該長256位密鑰用作私有密鑰,以使用AES-256密碼對資料進行加密和解密,
為什么不使用密碼直接加密?
大多數加密演算法,包括AES-256,都要求使用足夠長的密鑰,通過對密碼進行哈希處理,我們得到了更長且固定大小的密鑰,
此外,出于兩個原因,我們選擇使用scrypt演算法,而不是使用SHA-256之類的更快的哈希值:
- 慢一點
- 它使用記憶體以及CPU資源
我們想要慢速散列的原因是,攻擊者很難猜測用戶的密碼,如果攻擊者試圖強行闖入金庫,則意味著他們只是反復猜測密碼以進行破解,AES-256速度非常快,因此,攻擊者將能夠嘗試許多密碼在現代計算機上每秒傳輸一次,
由于攻擊者必須先對每個密碼運行一個scrypt哈希,然后才能嘗試對庫進行解密,因此攻擊變得如此緩慢,幾乎不可能猜出密碼,在功能相對強大的臺式計算機上,散列Qvault密碼大約需要1.5秒,因為我們將記憶體和計算要求設定得很高,
加密屬性
像所有散列函式一樣,scrypt具有以下屬性:
- 確定性的(每次相同的輸入都會產生相同的輸出)
- 固定尺寸的輸出
- 不可逆的(通過使用輸出,攻擊者無法找到輸入)
此外,Scrypt具有以下屬性:
- 計算昂貴且速度慢(計算機運行哈希需要很長時間)
- 記憶體密集型(可能使用數GB的RAM來運行哈希)
什么是BCrypt?
https://dev.to/sylviapap/bcrypt-explained-4k5c
BCrypt是由OpenBSD專案的Niels Provos和DavidMazières在1999年設計的一種哈希演算法,B代表...
如果您是初學者密碼學的專家,那么您來對地方了,也許您只是進入Rails并想添加用戶登錄/注銷功能,也許您真的很喜歡加密哈希演算法,我肯定是!如果您真的是一個初學者,那么一個名為Khan Academy的小型網站上有一些關于加密的特別出色的視頻,
這并不是真正的教程,但是在使用BCrypt時,請始終記住取消注釋Rails Gemfile中的gem,
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby '2.6.1'
...
# Use Active Model has_secure_password
# gem 'bcrypt', '~> 3.1.7'
gem 'bcrypt', '~> 3.1.7'
...
現在,您可以做一些很酷的事情:
# Encrypts password
my_password = BCrypt::Password.create('iLOVEdogs123')
=> "$2a$10$kypbnGGCpJ7UQlysnqzJG.6H.dUewn7UPVWA3Ip.E.8U4jlVnFNnu"
# Tests if input matches
my_password == 'iLOVEdogs123'
=> true
my_password == 'ilovedogs12'
=> false
# Not super important for this post, but this is why the above crypt begins with "$2a$"
my_password.version
=> "2a"
# "Cost" factor - how quickly the password is encrypted
my_password.cost
=> 10
現在,您可以使用BCrypt對應用程式執行很多操作-身份驗證,授權,登錄,注銷等!但是,已經有很多博客文章和有關如何撰寫代碼的有用檔案,我對幕后動作更感興趣,
Bcrypt是怎么加密的?
Bcrypt有四個變數:
- saltRounds: 正數,代表hash雜湊次數,數值越高越安全,默認10次,
- myPassword: 明文密碼字串,
- salt: 鹽,一個128bits隨機字串,22字符
- myHash: 經過明文密碼password和鹽salt進行hash,個人的理解是默認10次下 ,回圈加鹽hash10次,得到myHash
每次明文字串myPassword過來,就通過10次回圈加鹽salt加密后得到myHash, 然后拼接BCrypt版本號+salt鹽+myHash等到最終的bcrypt密碼 ,存入資料庫中,
這樣同一個密碼,每次登錄都可以根據自省業務需要生成不同的myHash, myHash中包含了版本和salt,存入資料庫,
bcrypt密碼圖解:(此部分來源:https://www.jianshu.com/p/2b131bfc2f10)

如Spring Security crypto 專案中實作的BCrypt方法加密:BCrypt.hashpw(myPassword, BCrypt.gensalt())
那即使黑客得到了bcrypt密碼,他也無法轉換明文,因為之前說了bcrypt是單向hash演算法;
OWASP - 開放式Web應用程式安全專案
開放式Web應用程式安全專案(OWASP,Open Web Application Security Project)是一個組織,它提供有關計算機和互聯網應用程式的公正、實際、有成本效益的資訊,其目的是協助個人、企業和機構來發現和使用可信賴軟體,
OWASP Top 10是針對開發人員和Web應用程式安全性的標準意識檔案,它代表了對Web應用程式最嚴重的安全風險的廣泛共識,
相關文章
- (非常)格的基本介紹
- (非常)橢圓曲線密碼學基礎介紹
- Bcrypt逐步
- 《哈希函式(Hash Functions - 散列函式)的基本介紹(SHA-2,SHA-256,MD-5等)》
- 《關于布隆過濾器的所有資訊:利用Hash實作的索引方案》
- 《(Very) Basic Intro to Hash Functions (SHA-256, MD-5, etc)》
- 《Scrypt哈希的基本介紹》
- 《BCrypt解釋》
- 《維基百科:scrypt》
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/170085.html
標籤:其他
