首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> C 語言入門

SHA-1 安全哈希算法 C 語言實現:從 RFC 3174 到工程級代碼的完整解析

     編輯:C 語言入門

算法背景與特性

SHA-1(Secure Hash Algorithm 1)是 FIPS PUB 180-1 標準化的密碼學哈希函數,輸入任意長度(< 264 位)消息,產出 160 位(20 字節)消息摘要。核心特性:

  • 單向性:不可從摘要逆推原文
  • 抗碰撞:理論碰撞概率 2-80,但 2017 年 Google 宣布實際碰撞攻擊(SHAttered),新項目禁用 SHA-1,改用 SHA-256/3
  • 雪崩效應:輸入微小變化導致摘要劇烈變化

填充與分組處理流程

  1. 填充:消息後追加 0x80(10000000),再補 0x00 直到長度 ≡ 448 mod 512
  2. 附加長度:最後 64 位存儲原始消息比特長度(大端序)
  3. 分組:填充後消息按 512 位(64 字節)分組,每組經壓縮函數處理
  4. 鏈式處理:每組輸出作為下組初始向量(IV),首組 IV 為固定常數

核心數據結構

typedef struct {
    uint32_t Intermediate_Hash[5];  // 5 個 32 位字 = 160 位摘要
    uint32_t Length_Low, Length_High;  // 64 位比特長度
    uint16_t Message_Block_Index;      // 當前填充位置
    uint8_t Message_Block[64];         // 512 位緩衝區
    int Computed;   // 摘要是否已計算
    int Corrupted;  // 上下文是否損壞
} SHA1Context;

四大核心函數流程

1. SHA1Reset:初始化上下文

context->Intermediate_Hash[0] = 0x67452301;
context->Intermediate_Hash[1] = 0xEFCDAB89;
context->Intermediate_Hash[2] = 0x98BADCFE;
context->Intermediate_Hash[3] = 0x10325476;
context->Intermediate_Hash[4] = 0xC3D2E1F0;  // 標準 IV(大端序)

2. SHA1Input:流式輸入數據

  • 逐字節填入 Message_Block
  • 累加比特長度(Length_Low += 8,進位到 Length_High)
  • 緩衝區滿 64 字節 → 調用 SHA1ProcessMessageBlock
  • 長度溢出(> 264-1)標記 Corrupted

3. SHA1ProcessMessageBlock:壓縮函數核心

處理 512 位塊,擴展為 80 個 32 位字 W[0..79]:

// 前 16 字直接取自塊(大端序組裝)
for (t=0; t<16; t++)
    W[t] = (block[4*t]<<24) | (block[4*t+1]<<16) | (block[4*t+2]<<8) | block[4*t+3];

// 後 64 字由前序字循環左移異或產生
for (t=16; t<80; t++)
    W[t] = ROTL(1, W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);

然後 80 輪主迴路,分 4 階段,每階段 20 輪,使用不同非線性函數 f 和常數 K:

輪次函數 f(B,C,D)常數 K
0-19(B∧C) ∨ (¬B∧D)0x5A827999
20-39B ⊕ C ⊕ D0x6ED9EBA1
40-59(B∧C) ∨ (B∧D) ∨ (C∧D)0x8F1BBCDC
60-79B ⊕ C ⊕ D0xCA62C1D6

每輪更新 5 個工作變量 A,B,C,D,E,最終加回 Intermediate_Hash。

4. SHA1PadMessage:最終填充與輸出

  • 若剩餘空間 < 8 字節(無法放長度),先處理當前塊,再新建塊
  • 寫入 0x80、補零、寫入 64 位大端長度
  • 調用 ProcessMessageBlock 完成最後一塊
  • 清理敏感緩衝區

5. SHA1Result:提取摘要

>2] >> (8 * (3 - (i & 3)));

字節序處理:跨平台正確性關鍵

SHA-1 規範要求大端序(網絡序):

  • 消息塊裝載:W[t] = (b0<<24) | (b1<<16) | (b2<<8) | b3
  • 長度存儲:高 32 位在前,低 32 位在後,各自大端
  • 摘要輸出:高位字節在前

小端機器(x86、ARM)必須顯式轉換,不可直接強轉指針,否則摘要錯誤。

驗證向量(NIST FIPS 180-1)

輸入重複次數期望摘要(十六進制)
"abc"1A9 99 3E 36 47 06 81 6A BA 3E 25 71 78 50 C2 6C 9C D0 D8 9D
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"184 98 3E 44 1C 3B D2 6E BA AE 4A A1 F9 51 29 E5 E5 46 70 F1
"a"1,000,00034 AA 97 3C D4 C4 DA A4 F6 1E EB 2B DB AD 27 31 65 34 01 6F

工程化封裝建議

  1. 流式 API:Init → Update(data, len) × n → Final(digest),支持大文件/網絡流
  2. 錯誤碼枚舉:SHA_SUCCESS, SHA_NULL_PTR, SHA_INPUT_TOO_LONG, SHA_STATE_ERROR
  3. 線程安全:上下文結構體無靜態變量,天然可重入
  4. 敏感數據清零:Final 後務必 memset(ctx, 0, sizeof(*ctx))
  5. 編譯選項:-std=c99 -Wall -Wextra -O2 -D_POSIX_C_SOURCE=200809L

現代替代方案

鉴于 SHA-1 已被攻破,生產環境請使用:

  • SHA-256:openssl/sha.h 提供 SHA256_Init/Update/Final
  • BLAKE2/3:更快、更安全、API 相似
  • 硬件加速:ARMv8 SHA 指令、Intel SHA-NI、專用加密引擎

本實現嚴格遵循 RFC 3174,代碼結構清晰、邊界處理完善,適合教學研究與舊系統維護。新項目請直接選用 SHA-2 族或更現代算法。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved