【密码学】基于 SM3 算法的 HMAC 快速实现
基于 SM3 算法的 HMAC 快速實現
Presented by R.G.
如不想閱讀詳細實現原理,請直接閱 讀SM3hmac快速上手(使用手冊) 部分,本文所有的代碼文件見我的github倉庫RG_SM3hmac,歡迎關注~
注:
-
本README有少量數學公式需要LaTeX支持,github貌似沒有原生支持LaTeX,若您在閱讀本README時無法正確顯示數學公式,請安裝支持LaTeX顯示的瀏覽器插件,我推薦 MathJax Plugin for Github 插件
-
注:如果你的github無法看到圖片的話,請參考我的這篇文章
解決Github無法顯示圖片以及README無法顯示圖片
目錄大綱
文章目錄
- 目錄大綱
- 作品內容摘要
- 作品功能與性能說明
- 設計原理與實現方案
- SM3 算法流程圖
- SM3 算法描述
- HMAC 算法流程圖
- HMAC 算法描述
- 具體代碼實現
- SM3hmac快速上手(使用手冊)
- RandMsgGen.py 使用方法
- SampleTest 文件夾
- SM3hmac.c 文件介紹(項目主體代碼)
- sm3hmac.out 文件
- 運行與測試環境
- 運行結果(代碼性能見「系統測試與結果」)
- 技術指標
- 系統測試與結果
- 測試方案
- 功能測試
- 性能測試
- 測試數據與結果
- 應用前景
- 登錄身份認證
- 項目總結
作品內容摘要
? 本作品致力于快速實現基于我國政府采用的由國家密碼管理局發布的 SM3 密碼 散列函數標準的 HMAC 哈希運算消息認證碼。
作品主要包含一個歡迎界面和以下三個功能模塊:SM3 文檔示例、樣例測試、 自定義。
-
歡迎界面:歡迎用戶,引導用戶進行功能選擇,以及一些使用提示。
-
SM3 文檔示例:校驗本程序生成的《SM3 密碼雜湊算法》標準文檔所提供的2 個樣例的雜湊值,同時給出樣例的 HMAC 值。
-
樣例測試:選取1K-100MB八個不同量級的消息文件,計算對應HMAC以及其生成時間和速率。
-
自定義:用戶自定義消息輸入,對用戶輸入的消息計算HMAC值。
為了提高程序計算 HMAC 的性能,減少程序計算用時、提升計算速率,本作品 由純 C 語言編寫完成,并在 Linux 環境下運行測試。
? 同時,為了進一步提升程序執行速度,在用 C 編寫相應功能模塊時,將 SM3 的 主要幾個運算函數均寫成宏函數。此外,采取了使用 register 關鍵字定義部分變量、 拆解小循環 for、移位代替乘除法運算、使用復合賦值表達式、把頻繁使用的指針 型參數拷貝到本地變量、使用并行代碼等一系列編寫優化方式,以此提升程序運行 性能。
? 測試顯示: 本程序對消息的HMAC計算基本維持在毫秒級別,計算速率維持在 72MBps左右。對10MB以下消息進行HMAC運算基本可以忽略計算延時,對于百KB量級 的消息計算速率最佳。
關鍵詞: HMAC、SM3、哈希摘要、消息驗證碼、快速實現
作品功能與性能說明
作品設計目標: 快速實現基于 SM3 哈希函數的 HMAC 哈希運算消息認證碼
作品內容及其作用:
| SampleTest | 存儲 1K-100MB 樣例消息文件以及測試結果截圖的文件夾 |
| RandMsgGen.py | 生成足夠隨機的樣例消息文件 |
| SM3hmac.c | 作品主程序 |
| sm3hmac.out | Linux 下 gcc 編譯 SM3hmac.c 生成的可執行文件 |
| README.md | README 文件,作品說明以及使用說明 |
作品功能: 作品程序 SM3hmac 主要包含一個歡迎界面和以下三個功能模塊: SM3 文檔示例、樣例測試、自定義。
- 歡迎界面:歡迎用戶,引導用戶進行功能選擇,以及一些使用提示。
- SM3 文檔示例:校驗本程序生成的《SM3 密碼雜湊算法》標準文檔所提供的 2 個樣例的雜湊值,同時給出樣例的 HMAC 值。
- 樣例測試:選取 1K-100MB 八個不同量級的消息文件,計算對應 HMAC 以及其生成時間和速率。
- 自定義:用戶自定義消息輸入,對用戶輸入的消息計算 HMAC 值。
下面是作品主要功能模塊的框架圖:
作品性能: 通過對 1KB-100MB 共計 8 個樣例消息文件的測試,得出測試數據與相應分析圖。由測試結果可知,本程序對消息的 HMAC 計算基本維持在毫秒級 別,計算速率維持在 72MBps 左右。對 10MB 以下消息進行 HMAC 運算基本可以忽 略計算延時,對于百 KB 量級的消息計算速率最佳。
設計原理與實現方案
SM3 算法流程圖
SM3 算法描述
初始值
- IV =7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e
常量
Tj={79cc45190≤j≤157a879d8a16≤j≤63T_{j}=\left\{\begin{array}{ll}79 c c 4519 & 0 \leq j \leq 15 \\ 7 a 879 d 8 a & 16 \leq j \leq 63\end{array}\right. Tj?={79cc45197a879d8a?0≤j≤1516≤j≤63?
布爾函數
FFj(X,Y,Z)={X⊕Y⊕Z0≤j≤15(X∧Y)∨(X∧Z)∨(Y∧Z)16≤j≤63GGj(X,Y,Z)={X⊕Y⊕Z0≤j≤15(X∧Y)∨(?X∧Z)16≤j≤63\begin{array}{l}F F_{j}(X, Y, Z)=\left\{\begin{array}{ll}X \oplus Y \oplus Z & 0 \leq j \leq 15 \\ (X \wedge Y) \vee(X \wedge Z) \vee(Y \wedge Z) & 16 \leq j \leq 63\end{array}\right. \\ G G_{j}(X, Y, Z)=\left\{\begin{array}{ll}X \oplus Y \oplus Z & 0 \leq j \leq 15 \\ (X \wedge Y) \vee(\neg X \wedge Z) & 16 \leq j \leq 63\end{array}\right.\end{array} FFj?(X,Y,Z)={X⊕Y⊕Z(X∧Y)∨(X∧Z)∨(Y∧Z)?0≤j≤1516≤j≤63?GGj?(X,Y,Z)={X⊕Y⊕Z(X∧Y)∨(?X∧Z)?0≤j≤1516≤j≤63??
式中 X,Y,Z為字。
置換函數
P0(X)=X⊕(X?9)⊕(X?17)P1(X)=X⊕(X?15)⊕(X?23)\begin{array}{l}P_{0}(X)=X \oplus(X \lll 9) \oplus(X \lll 17) \\ P_{1}(X)=X \oplus(X \lll 15) \oplus(X \lll 23)\end{array} P0?(X)=X⊕(X?9)⊕(X?17)P1?(X)=X⊕(X?15)⊕(X?23)?
式中X為字。
算法概述
對長度為L (L<264L < 2^{64}L<264) 比特的消息m,SM3雜湊算法經過填充和迭代壓縮,生成雜湊值,雜湊值長度為256比特。
填充
-
假設消息 m 的長度為 L 比特。首先將比特“1”添加到消息的末尾,再添加 k 個“0”,k 是滿足L + 1 + k ≡ 448 mod 512的最小的非負整數。然后再 加一個 64 位比特串,該比特串是長度 L 的二進制表示。填充后的消息 m′ 的 比特長度為 512 的倍數。
迭代壓縮
-
迭代過程:
將填充后的消息 m′ 按 512 比特進行分組: m′ = B(0)B(1)...B(n?1)其中n=(l+k+65)/512。
對 m′按下列方式迭代:
FOR i=0 TO n-1V(i+1) =CF(V(i),B(i)) ENDFOR其中 CF 是壓縮函數,V (0) 為 256 比特初始值 IV,B(i)為填充后的消息分組, 迭代壓縮的結果 為 V (n)。
-
消息擴展:
將消息分組 B(i)按以下方法擴展生成 132 個字W0, W1,..., W67, W0′,W1′,... , W‘63,用于壓縮函數 CF:
-
將消息分組 B(i)劃分為 16 個字 W0, W1,…, W15。
- FOR j=16 TO 67Wj ← P1(Wj?16 ⊕Wj?9 ⊕(Wj?3 ? 15))⊕(Wj?13 ? 7)⊕Wj?6 ENDFOR
- FOR j=0 TO 63 Wj′= Wj ⊕Wj+4 ENDFOR
-
-
壓縮函數:
-
令 A,B,C,D,E,F,G,H 為字寄存器,SS1,SS2,TT1,TT2 為中間變量,壓縮函數 V i+1=CF (V (i), B(i)), 0 ≤ i ≤ n?1。計算過程描述如下:
ABCDEFGH ← V (i) FOR j=0 TO 63 SS1←((A?12)+E+(T_j ?j))?7 SS2 ← SS1⊕(A ? 12)TT1 ← FF_j (A, B, C) + D + SS2 + Wj′ TT2 ← GG_j (E, F, G) + H + SS1 + WjD←C C←B?9 B←A A←TT1 H←GG ← F ? 19 F←EE ← P0(TT2) ENDFOR V(i+1) ←ABCDEFGH⊕V(i)其中,?為循環左移,字的存儲為大端(big-endian)格式
-
雜湊值
ABCDEFGH ← V (n)輸出 256 比特的雜湊值 y = ABCDEFGH
HMAC 算法流程圖
HMAC 算法描述
在 HMAC 的定義中用到一個密碼散列函數和一個密鑰 Key。本作品使用的 SM3 作 為對明文進行分組循環壓縮的散列函數,明文分組長度為 64(byte),散列函 數的輸出長度為 32(byte)。認證密鑰 K 為隨機生成。
再定義兩個不同的固定字符串 iPad 和 oPad 如下(“i”和“o”表示內部和外 部):
- iPad=一個字節(byte)的 0x36 重復 64 次;
- oPad=一個字節(byte)的 0x5C 重復 64 次
操作步驟如下:
以輸入 Message 為例,作如下操作:
H(K XOR oPad,H(K XOR iPad,Message))
其中 H() 為哈希函數,也就是我們上面的SM3
具體代碼實現
參見:https://github.com/RGNil/RG_SM3hmac
SM3hmac快速上手(使用手冊)
RandMsgGen.py 使用方法
在 python3.7 環境下,輸入python RandMsgGen.py運行此腳本,生成相應規模的隨機消息文件,默認生成在SampleTest文件夾,默認的大小是1MB
如需改變生成的文件大小量級,可改變RandMsgGen.py中的chrAmount值,該值用于控制隨機生成的消息字符個數
更多細節,請參見 RandMsgGen.py 源碼
SampleTest 文件夾
SampleTest文件夾存儲了由 RandMsgGen.py 形成的 1KB、10KB、50KB、100KB、1MB、10MB、50MB、100MB共計8個量級的測試用例,分別命名為msg1k.txt、msg10k.txt、msg50k.txt、msg100k.txt、msg1M.txt、msg10M.txt、msg50M.txt、msg100M.txt。(注:考慮到txt文件UTF-8編碼下的文件頭等相關信息的影響,實際生成的文件大小稍有偏差,但仍能滿足量級)
注:由于github普通上傳的單個文件大小不能超過50MB,這里沒有把msg50M.txt、msg100M.txt上傳進去
同時,此文件夾存儲了測試結果數據的截圖,例如 100k文件測試結果截圖
SM3hmac.c 文件介紹(項目主體代碼)
該文件是本作品的核心源碼,集成了SM3哈希函數的實現、基于SM3的HMAC計算函數的實現以及對以上功能的測試函數。
該文件在Linux環境下,使用gcc -o sm3hmac.out SM3hmac.c命令編譯,生成Linux可執行文件sm3hmac.out
sm3hmac.out 文件
該文件是由 SM3hmac.c 文件編譯生成的Linux可執行文件。可以在Linux環境下,進入該文件路徑,然后使用 ./sm3hmac.out 命令直接運行。
運行與測試環境
程序源碼SM3hmac.c由純C語言編寫完成,在Windows 10下的VMware Workstation Pro 15的虛擬Ubuntu19.0.4下運行。通過Gcc編譯成Linux可執行文件sm3hmac.out執行以下測試。
運行結果(代碼性能見「系統測試與結果」)
校驗本程序生成的《SM3 密碼雜湊算法》標準文檔所提供的 2 個樣例的雜湊 值,同時給出樣例的 HMAC 值:
100MB 量級的消息文件其對應 HMAC 以及其生成時間和速率的測試運行結果:
對用戶選擇消息文件進行HMAC計算:
技術指標
? 本作品實現基于我國政府采用的由國家密碼管理局發布的SM3密碼散列函數標準的HMAC哈希運算消息認證碼。
Hash函數部分完全根據國家密碼管理局發布的《SM3密碼雜湊算法》標準文檔編寫完成,同時對標準所給出的示例做了校驗測試,本程序對標準所提供的示例消息計算出的雜湊值與標準雜湊值相同。
此外,本程序采用的HMAC算法完全依據RFC2104標準實現,并對樣例測試結果值進行了正確性驗證。驗證方法是:利用Go語言現有的crypto/hmac庫,以及 蘇州同濟區塊鏈研究院有限公司 的基于Go語言的國密SM3算法庫,兩者結合運算得到HMAC值,驗證本程序對相同樣例消息的計算結果。
對于程序計算HMAC值的性能評價,采用計算用時(單位:s)、計算速率(MBps)兩個指標來衡量。
測試樣例選取多種大小不同的消息文件進行讀取與哈希運算,對消息的HMAC計算基本維持在毫秒級別,計算速率維持在72MBps左右。
詳細分析見系統測試部分。
系統測試與結果
測試方案
本程序的測試主要分為兩部分:第一部分,測試SM3的Hash函數是否能生成正確雜湊值;第二部分,測試樣例消息文檔生成的HMAC是否正確,同時測試其生成時間以及速度。
第一部分的測試,根據國家密碼管理局發布的《SM3密碼雜湊算法》標準文檔所提供的2個樣例,計算所生成的雜湊值是否和標準所給的雜湊值相同,相同則說明本程序的Hash函數部分準確無誤。
第二部分的測試,要求所選用的消息具有一定隨機性,且能滿足絕大部分場景的消息使用。因此,采用了如下方法進行測試。
考慮到系統的普適性與兼容性,本次測試從Unicode字符集中挑選部分常用的字符形成測試字符集。選取的測試字符以及整體測試字符集如下:
測試用例字符集
| 基本拉丁字母集 | 0020-007F | 95 |
| 國際音標擴展集 | 0250-02AF | 95 |
| 希臘字母及科普特字母集 | 0370-03FF | 143 |
| 常用標點集 | 2000-206F | 111 |
| 貨幣符號集 | 20A0-20CF | 47 |
| 數字形式集 | 2150-218F | 63 |
| 數學運算符集 | 2200-22FF | 255 |
| 雜項工業符號集 | 2300-23FF | 255 |
| 帶圈或括號的字母數字集 | 2460-24FF | 159 |
| 制表符集 | 2500-257F | 127 |
| 印刷符號集 | 2700-27BF | 191 |
| 雜項數學符號集 | 27C0-27eF | 47 |
| 中日韓相關字符集 | 31C0-9FFF | 28223 |
根據選定的測試字符集,采用python的random庫,隨機從測試字符集中選取字符,形成1KB、10KB、50KB、100KB、1MB、10MB、50MB、100MB共計8個量級的測試用例,分別命名為msg1k.txt、msg10k.txt、msg50k.txt、msg100k.txt、msg1M.txt、msg10M.txt、msg50M.txt、msg100M.txt。(注:考慮到txt文件UTF-8編碼下的文件頭等相關信息的影響,實際生成的文件大小稍有偏差,但仍能滿足量級)
具體如何生成測試樣例,請參見作品中的RandMsgGen.py文件,所有的測試樣例都由該文件生成,且測試樣例足夠隨機,包含常用的字母、數字、中文以及一些特殊字符。下面是部分msg1M.txt的截圖:
用生成的8個不同量級大小的隨機txt文本,作為消息的模擬,以此作為程序的消息輸入,運算消息的HMAC值,并調用C庫函數clock()計算HMAC生成時間以及速率。
為了確定所生成的HMAC值是否正確,我們搜尋了已有的資源,決定使用Go語言現有的crypto/hmac庫,以及 蘇州同濟區塊鏈研究院有限公司 的基于Go語言的國密SM3算法庫,兩者結合運算得到HMAC值,作為本程序結果正確性的輔助驗證。
功能測試
本節主要對作品程序的三大功能模塊進行了功能完整性測試。
SM3hmac主要包含一個歡迎界面和以下三個功能模塊:SM3文檔示例、樣例測試、自定義。
- 歡迎界面:歡迎用戶,引導用戶進行功能選擇,以及一些使用提示。
- SM3文檔示例:校驗本程序生成的《SM3密碼雜湊算法》標準文檔所提供的2個樣例的雜湊值,同時給出樣例的HMAC值。
- 樣例測試:選取1K-100MB八個不同量級的消息文件,計算對應HMAC以及其生成時間和速率。
- 自定義:用戶自定義消息輸入,對用戶輸入的消息計算HMAC值。
下面是以上所列舉的功能的完整性測試:
SM3文檔示例
對比國家密碼管理局發布的《SM3密碼雜湊算法》標準文檔所提供的2個樣例可知,計算所生成的雜湊值和標準所給的雜湊值相同。
樣例測試
以下是50KB和1MB的運行測試:
50KB樣例運行結果:
利用Go庫生成的50KB樣例文件的HMAC:
可見,本程序運算所得結果與調用Go庫運算結果一致
1MB樣例運行結果:
利用Go庫生成的1MB樣例文件的HMAC:
可見,本程序運算所得結果與調用Go庫運算結果一致
其余6個量級的文檔測試均和Go運算結果一致,此處略去截圖
自定義:
直接輸入消息測試:
指定消息文件測試:
性能測試
本節是程序的性能測試,本程序主要關注于快速實現基于我國政府采用的由國家密碼管理局發布的SM3密碼散列函數標準的HMAC哈希運算消息認證碼。對于程序的性能,我們采用程序計算HMAC所消耗的時間以及相應速率作為衡量指標。
考慮到測試的有效性以及真實性,我們將給出測試所用平臺的相應軟硬件配置。此外,為了力求測試結果的準確性,我們采取了一下方法:
- 多個不同量級的文件測試程序在面對不同大小的消息時的運算性能
- 隨機化測試文件的內容,保證消息內容不具規律性
- 每個量級文件采取多組測試,求平均時間以及速率作為最終性能指標
下面是部分測試截圖,詳細的測試報告將在 測試數據與結果 一節呈現
程序源碼SM3hmac.c由純C語言編寫完成,在Windows 10下的VMware Workstation Pro 15的虛擬Ubuntu19.0.4下運行。通過Gcc編譯成Linux可執行文件sm3hmac.out執行以下測試。
測試文件:msg1k.txt 文件量級:1KB
測試文件:msg10k.txt 文件量級:10KB
測試文件:msg100k.txt 文件量級:100KB
測試文件:msg10M.txt 文件量級:10MB
測試文件:msg100M.txt 文件量級:100MB
測試數據與結果
下面是1K-100MB共計8個消息樣例的測試結果,每個樣例分別代表一個數量級的消息大小,為了消除測試數據的偶然性,提高測試數據準確性,對每個消息量級各測5組數據,最后求出平均值,得到平均計算用時和平均計算速率兩個指標。
以下是測試數據詳情(所有測試數據的截圖可在作品文件清單的SampleTest文件夾的測試結果截圖文件夾中):
測試數據分析圖:
由以上測試數據與相應分析圖可知,本程序對消息的HMAC計算基本維持在毫秒級別,計算速率維持在72MBps左右。對10MB以下消息進行HMAC運算基本可以忽略計算延時,對于百KB量級的消息計算速率最佳。
鑒于在網絡環境下,一次性傳輸消息的量級很少達到10MB,超過10MB可以采取分組計算的方式,本程序的性能還是極其可觀的。
應用前景
登錄身份認證
當客戶端向服務器發送請求時,黑客可以截獲客戶端發送的數據。在許多場合,如:網上購物、應用登錄等,發送的請求中會包含用戶密碼、銀行卡密碼等私人敏感信息,嚴重威脅到了用戶的隱私、財產安全。HMAC哈希消息驗證碼,通過對用戶發送數據進行HMAC運算后再發送請求的方式,防止數據暴露。
HMAC登錄身份認證流程如下:
①客戶端向服務端發送登錄請求。
②服務端返回一個隨機數作為密鑰,并在會話記錄中保存這個隨機值。
③客戶端先使用密鑰對用戶私密信息進行HMAC運算,再將數據發送給服務器。
④服務器讀取數據庫中對應用戶的密碼,使用存儲的隨機值(密鑰)對從數據庫中獲取的密碼進行相同的HMAC運算。
⑤服務器比較客戶端HMAC運算生成值與服務器HMAC運算生成值,如果匹配成功則返回成功響應,否則返回失敗響應。
項目總結
本作品以C語言實現的SM3為基礎,進而實現HMAC哈希認證的快速實現,由于主題對交互與應用沒有明確要求,故所有操作以快速實現為主要目的。快速實現主要包括對SM3算法中的操作的宏定義、減少函數調用,以增加適當的空間復雜度來降低時間復雜度等。此外,采取了使用register關鍵字定義部分變量、拆解小循環for、移位代替乘除法運算、使用復合賦值表達式、把頻繁使用的指針型參數拷貝到本地變量、使用并行代碼等一系列編寫優化方式,進一步提升程序運行性能。
測試樣例選取多種大小不同的文件進行讀取與哈希運算,對消息的HMAC計算基本維持在毫秒級別,計算速率維持在72MBps左右。對10MB以下消息進行HMAC運算基本可以忽略計算延時,對于百KB量級的消息計算速率最佳。
初步預設的應用場景為涉及身份認證、用戶登錄等方面,通過服務器端生成隨機salt,在服務器端與客戶端分別對用戶的key進行HMAC運算操作,對運算結果進行比對從而確認用戶身份。
如果有幫到可愛的你的話,希望小可愛你能反手一個贊👍哦,關注我的都是大可愛哦!
總結
以上是生活随笔為你收集整理的【密码学】基于 SM3 算法的 HMAC 快速实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vdbench数据校验翻译
- 下一篇: ICEM 二维块的拉伸