安全哈希算法(SHA1)用於數字簽名標準(DSS)中的 DSA。對 < 2^64 位消息生成 160 位摘要,驗證數據完整性。特性:不可逆、抗碰撞(不同消息極難產生相同摘要)。
typedef unsigned int u32;
typedef struct {
u32 h0,h1,h2,h3,h4;
u32 nblocks;
unsigned char buf[64];
int count;
} SHA1_CONTEXT;
void sha1_init(SHA1_CONTEXT *hd) { /* 初始化魔數 */ }
static void transform(SHA1_CONTEXT *hd, unsigned char *data) { /* 80 輪壓縮 */ }
static void sha1_write(SHA1_CONTEXT *hd, unsigned char *inbuf, size_t inlen) { /* 流式處理 */ }
static void sha1_final(SHA1_CONTEXT *hd) { /* 填充、長度追加、最終輸出 */ }
完整實現包含大端/小端適配、滾動移位優化(GCC x86 內聯彙編)、常量 K1-K4、邏輯函數 F1-F4、消息擴展宏 M(i)、輪函數宏 R() 等。
void GetFileSHA1(char *FileNameInPut) {
if (!FileNameInPut) { printf("Usage: \n"); return; }
FILE *fp; char buffer[4096]; size_t n;
SHA1_CONTEXT ctx; int i;
fopen_s(&fp, FileNameInPut, "rb");
if (!fp) { printf("打開文件失敗\n"); return; }
sha1_init(&ctx);
while ((n = fread(buffer, 1, sizeof buffer, fp))) sha1_write(&ctx, (unsigned char*)buffer, n);
if (ferror(fp)) { printf("讀取失敗\n"); return; }
sha1_final(&ctx); fclose(fp);
for (i=0; i<20; i++) printf("%02x", ctx.buf[i]);
}
char *GetFileSHA1(char *FileNameInPut, char *outSHA1, char *outError) {
if (!FileNameInPut) { if (outError) sprintf(outError, "FileNameInPut Is NULL"); return outSHA1; }
FILE *fp; char buffer[4096]; size_t n;
SHA1_CONTEXT ctx; int i;
fopen_s(&fp, FileNameInPut, "rb");
if (!fp) { if (outError) sprintf(outError, "打開文件失敗"); return outSHA1; }
sha1_init(&ctx);
while ((n = fread(buffer, 1, sizeof buffer, fp))) sha1_write(&ctx, (unsigned char*)buffer, n);
if (ferror(fp)) { if (outError) sprintf(outError, "讀取失敗"); return outSHA1; }
sha1_final(&ctx); fclose(fp);
for (i=0; i<20; i++) sprintf(outSHA1 + 2*i, "%02x", (unsigned char)ctx.buf[i]);
outSHA1[40] = '\0';
return outSHA1;
}
int main(int argc, char **argv) {
GetFileSHA1(*(argv+1)); printf("\r\n");
char sha1[41] = {0}, eror[256] = {0};
printf("%s\r\n", GetFileSHA1(*(argv+1), sha1, NULL));
if (strlen(eror)) printf("錯誤:%s\r\n", eror);
printf("%s\r\n", GetFileSHA1(*(argv+1), sha1, eror));
if (strlen(eror)) printf("錯誤:%s\r\n", eror);
getchar(); return 0;
}

fopen_s,Linux 需改用 fopen