安全雜湊算法(Secure Hash Algorithm,SHA-1)是數位簽名標準(DSS)中定義的數位簽名算法(DSA)核心組件。對於長度小於 2^64 位的訊息,SHA-1 會產生一個 160 位(20 位元組)的訊息摘要。這個摘要可用於驗證資料完整性:傳輸過程中若資料發生變化,重新計算的摘要將與原值不同。SHA-1 具備兩大核心特性:不可逆性(無法從摘要還原原始訊息)與抗碰撞性(極難找到兩個不同訊息產生相同摘要)。
網路上流傳著多種 SHA-1 C 語言實現版本。本文採用一個精簡版本(來源:CSDN 下載資源),並記錄在 Visual Studio 2005 環境下編譯、除錯的完整過程,解決常見的型別轉換、標頭檔缺失與函數回傳值等問題。
程式包含三大核心函數:
creat_w():將 64 位元組輸入擴展為 80 個 32 位元字(W 陣列)ms_len():將訊息長度(位元數)填入緩衝區尾端main():主迴圈執行 80 輪壓縮函數運算,輸出最終雜湊值編譯成功後,輸入測試字串 abcd,程式原始輸出包含中間運算過程與逗號分隔的雜湊值。修改步驟:
重新執行,輸出:81fe8bfe87576c3ecb22426f8e57847382917acf,與線上 SHA-1 工具驗證結果完全一致。
// SHA1.cpp : 定義控制台應用程式的進入點
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <wtypes.h>
void creat_w(unsigned char input[64], unsigned long w[80]) {
int i, j; unsigned long temp, temp1;
for (i = 0; i < 16; i++) {
j = 4 * i;
w[i] = ((long)input[j] << 24) | ((long)input[1+j] << 16) |
((long)input[2+j] << 8) | ((long)input[3+j] << 0);
}
for (i = 16; i < 80; i++) {
w[i] = w[i-16] ^ w[i-14] ^ w[i-8] ^ w[i-3];
temp = w[i] << 1;
temp1 = w[i] >> 31;
w[i] = temp | temp1;
}
}
char ms_len(long a, char intput[64]) {
unsigned long temp3, p1; int i, j;
temp3 = 0; p1 = ~(~temp3 << 8);
for (i = 0; i < 4; i++) {
j = 8 * i;
intput[63-i] = (char)((a & (p1 << j)) >> j);
}
return '0';
}
int _tmain(int argc, _TCHAR* argv[]) {
unsigned long H0 = 0x67452301, H1 = 0xefcdab89, H2 = 0x98badcfe,
H3 = 0x10325476, H4 = 0xc3d2e1f0;
unsigned long A, B, C, D, E, temp, temp1, temp2, temp3, k, f;
int i, flag; unsigned long w[80];
unsigned char input[64]; long x; int n;
printf("input message:\n");
scanf("%s", input);
n = strlen((LPSTR)input);
if (n < 57) {
x = n * 8;
ms_len(x, (char*)input);
if (n == 56)
for (i = n; i < 60; i++) input[i] = 0;
else {
input[n] = 128;
for (i = n+1; i < 60; i++) input[i] = 0;
}
}
creat_w(input, w);
A = H0; B = H1; C = H2; D = H3; E = H4;
for (i = 0; i < 80; i++) {
flag = i / 20;
switch (flag) {
case 0: k = 0x5a827999; f = (B & C) | (~B & D); break;
case 1: k = 0x6ed9eba1; f = B ^ C ^ D; break;
case 2: k = 0x8f1bbcdc; f = (B & C) | (B & D) | (C & D); break;
case 3: k = 0xca62c1d6; f = B ^ C ^ D; break;
}
temp1 = A << 5; temp2 = A >> 27; temp3 = temp1 | temp2;
temp = temp3 + f + E + w[i] + k;
E = D; D = C;
temp1 = B << 30; temp2 = B >> 2; C = temp1 | temp2;
B = A; A = temp;
}
H0 += A; H1 += B; H2 += C; H3 += D; H4 += E;
printf("\noutput hash value:\n");
printf("%lx%lx%lx%lx%lx", H0, H1, H2, H3, H4);
getch();
return 0;
}
本文完整呈現了從原始碼獲取、編譯錯誤診斷、型別修正到最終驗證的全過程。關鍵點在於:理解 VS 對 C 標準庫函數的型別檢查嚴格性、善用 IDE 的「Add Include」功能、處理有號/無號字元指標轉換、確保所有函數有正確回傳值。修正後的程式碼可直接在 Visual Studio 2005+ 環境編譯執行,產出標準 SHA-1 雜湊值。