日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【安全算法之SHA1】SHA1摘要运算的C语言源码实现

發布時間:2023/12/15 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【安全算法之SHA1】SHA1摘要运算的C语言源码实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【安全算法之SHA1】SHA1摘要運算的C語言源碼實現

  • 概述
  • 頭文件定義
  • C語言版本的實現源碼
  • 測試用例
  • github倉庫
  • 更多參考鏈接

概述

大家都知道摘要算法在安全領域,也是一個特別重要的存在,而SHA1是其中比較常見的一種摘要算法,它的特點就是計算復雜度較低,不等長的數據原文輸入,可以得出等長的摘要值,這個值是固定為20字節。正是由于這種特殊性,很多重要的數據完整性校驗領域,都可以看到SHA1的影子。
今天給大家帶來SHA1的C源碼版本實現,歡迎大家深入學習和討論。

頭文件定義

頭文件定義如下,主要定義了SHA1的上下文結構體,以及導出的三個API:

#ifndef __SHA1_H__ #define __SHA1_H__#include <stdint.h>#define SHA1_DIGEST_LEN 20 // SHA1 outputs a 20 byte digesttypedef struct _sha1_ctx_t {uint32_t total[2]; /*!< number of bytes processed */uint32_t state[5]; /*!< intermediate digest state */uint8_t buffer[64]; /*!< data block being processed */ } sha1_ctx_t;void crypto_sha1_init(sha1_ctx_t *ctx); void crypto_sha1_update(sha1_ctx_t *ctx, const uint8_t *data, uint32_t len); void crypto_sha1_final(sha1_ctx_t *ctx, uint8_t *digest);#endif // __SHA1_H__

C語言版本的實現源碼

下面是SHA1的C語言版本實現,主要也是圍繞導出的3個API:

#include <string.h> #include "sha1.h"/** 32-bit integer manipulation macros (big endian)*/ #ifndef GET_UINT32_BE #define GET_UINT32_BE(n, b, i) \{ \(n) = ((uint32_t)(b)[(i)] << 24) | ((uint32_t)(b)[(i) + 1] << 16) | \((uint32_t)(b)[(i) + 2] << 8) | ((uint32_t)(b)[(i) + 3]); \} #endif#ifndef PUT_UINT32_BE #define PUT_UINT32_BE(n, b, i) \{ \(b)[(i)] = (uint8_t)((n) >> 24); \(b)[(i) + 1] = (uint8_t)((n) >> 16); \(b)[(i) + 2] = (uint8_t)((n) >> 8); \(b)[(i) + 3] = (uint8_t)((n)); \} #endifstatic const uint8_t sha1_padding[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };static void local_sha1_process(sha1_ctx_t *ctx,const uint8_t data[64]) {uint32_t temp, W[16], A, B, C, D, E;GET_UINT32_BE(W[0], data, 0);GET_UINT32_BE(W[1], data, 4);GET_UINT32_BE(W[2], data, 8);GET_UINT32_BE(W[3], data, 12);GET_UINT32_BE(W[4], data, 16);GET_UINT32_BE(W[5], data, 20);GET_UINT32_BE(W[6], data, 24);GET_UINT32_BE(W[7], data, 28);GET_UINT32_BE(W[8], data, 32);GET_UINT32_BE(W[9], data, 36);GET_UINT32_BE(W[10], data, 40);GET_UINT32_BE(W[11], data, 44);GET_UINT32_BE(W[12], data, 48);GET_UINT32_BE(W[13], data, 52);GET_UINT32_BE(W[14], data, 56);GET_UINT32_BE(W[15], data, 60);#define S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))#define R(t) \(temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ W[(t - 14) & 0x0F] ^ \W[t & 0x0F], \(W[t & 0x0F] = S(temp, 1)))#define P(a, b, c, d, e, x) \{ \e += S(a, 5) + F(b, c, d) + K + x; \b = S(b, 30); \}A = ctx->state[0];B = ctx->state[1];C = ctx->state[2];D = ctx->state[3];E = ctx->state[4];#define F(x, y, z) (z ^ (x & (y ^ z))) #define K 0x5A827999P(A, B, C, D, E, W[0]);P(E, A, B, C, D, W[1]);P(D, E, A, B, C, W[2]);P(C, D, E, A, B, W[3]);P(B, C, D, E, A, W[4]);P(A, B, C, D, E, W[5]);P(E, A, B, C, D, W[6]);P(D, E, A, B, C, W[7]);P(C, D, E, A, B, W[8]);P(B, C, D, E, A, W[9]);P(A, B, C, D, E, W[10]);P(E, A, B, C, D, W[11]);P(D, E, A, B, C, W[12]);P(C, D, E, A, B, W[13]);P(B, C, D, E, A, W[14]);P(A, B, C, D, E, W[15]);P(E, A, B, C, D, R(16));P(D, E, A, B, C, R(17));P(C, D, E, A, B, R(18));P(B, C, D, E, A, R(19));#undef K #undef F#define F(x, y, z) (x ^ y ^ z) #define K 0x6ED9EBA1P(A, B, C, D, E, R(20));P(E, A, B, C, D, R(21));P(D, E, A, B, C, R(22));P(C, D, E, A, B, R(23));P(B, C, D, E, A, R(24));P(A, B, C, D, E, R(25));P(E, A, B, C, D, R(26));P(D, E, A, B, C, R(27));P(C, D, E, A, B, R(28));P(B, C, D, E, A, R(29));P(A, B, C, D, E, R(30));P(E, A, B, C, D, R(31));P(D, E, A, B, C, R(32));P(C, D, E, A, B, R(33));P(B, C, D, E, A, R(34));P(A, B, C, D, E, R(35));P(E, A, B, C, D, R(36));P(D, E, A, B, C, R(37));P(C, D, E, A, B, R(38));P(B, C, D, E, A, R(39));#undef K #undef F#define F(x, y, z) ((x & y) | (z & (x | y))) #define K 0x8F1BBCDCP(A, B, C, D, E, R(40));P(E, A, B, C, D, R(41));P(D, E, A, B, C, R(42));P(C, D, E, A, B, R(43));P(B, C, D, E, A, R(44));P(A, B, C, D, E, R(45));P(E, A, B, C, D, R(46));P(D, E, A, B, C, R(47));P(C, D, E, A, B, R(48));P(B, C, D, E, A, R(49));P(A, B, C, D, E, R(50));P(E, A, B, C, D, R(51));P(D, E, A, B, C, R(52));P(C, D, E, A, B, R(53));P(B, C, D, E, A, R(54));P(A, B, C, D, E, R(55));P(E, A, B, C, D, R(56));P(D, E, A, B, C, R(57));P(C, D, E, A, B, R(58));P(B, C, D, E, A, R(59));#undef K #undef F#define F(x, y, z) (x ^ y ^ z) #define K 0xCA62C1D6P(A, B, C, D, E, R(60));P(E, A, B, C, D, R(61));P(D, E, A, B, C, R(62));P(C, D, E, A, B, R(63));P(B, C, D, E, A, R(64));P(A, B, C, D, E, R(65));P(E, A, B, C, D, R(66));P(D, E, A, B, C, R(67));P(C, D, E, A, B, R(68));P(B, C, D, E, A, R(69));P(A, B, C, D, E, R(70));P(E, A, B, C, D, R(71));P(D, E, A, B, C, R(72));P(C, D, E, A, B, R(73));P(B, C, D, E, A, R(74));P(A, B, C, D, E, R(75));P(E, A, B, C, D, R(76));P(D, E, A, B, C, R(77));P(C, D, E, A, B, R(78));P(B, C, D, E, A, R(79));#undef K #undef Fctx->state[0] += A;ctx->state[1] += B;ctx->state[2] += C;ctx->state[3] += D;ctx->state[4] += E; }/** SHA-1 process init*/ void crypto_sha1_init(sha1_ctx_t *ctx) {memset(ctx, 0, sizeof(sha1_ctx_t));ctx->total[0] = 0;ctx->total[1] = 0;ctx->state[0] = 0x67452301;ctx->state[1] = 0xEFCDAB89;ctx->state[2] = 0x98BADCFE;ctx->state[3] = 0x10325476;ctx->state[4] = 0xC3D2E1F0; }/** SHA-1 process buffer*/ void crypto_sha1_update(sha1_ctx_t *ctx, const uint8_t *input,uint32_t ilen) {uint32_t fill;uint32_t left;if (ilen == 0) {return;}left = ctx->total[0] & 0x3F;fill = 64 - left;ctx->total[0] += (uint32_t)ilen;ctx->total[0] &= 0xFFFFFFFF;if (ctx->total[0] < (uint32_t)ilen) {ctx->total[1]++;}if (left && ilen >= fill) {memcpy((void *)(ctx->buffer + left), input, fill);local_sha1_process(ctx, ctx->buffer);input += fill;ilen -= fill;left = 0;}while (ilen >= 64) {local_sha1_process(ctx, input);input += 64;ilen -= 64;}if (ilen > 0) {memcpy((void *)(ctx->buffer + left), input, ilen);} }/** SHA-1 final digest*/ void crypto_sha1_final(sha1_ctx_t *ctx, uint8_t *digest) {uint32_t last, padn;uint32_t high, low;uint8_t msglen[8];high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);low = (ctx->total[0] << 3);PUT_UINT32_BE(high, msglen, 0);PUT_UINT32_BE(low, msglen, 4);last = ctx->total[0] & 0x3F;padn = (last < 56) ? (56 - last) : (120 - last);crypto_sha1_update(ctx, sha1_padding, padn);crypto_sha1_update(ctx, msglen, 8);PUT_UINT32_BE(ctx->state[0], digest, 0);PUT_UINT32_BE(ctx->state[1], digest, 4);PUT_UINT32_BE(ctx->state[2], digest, 8);PUT_UINT32_BE(ctx->state[3], digest, 12);PUT_UINT32_BE(ctx->state[4], digest, 16); }

測試用例

針對SHA1導出的三個接口,我編寫了以下測試用例:

#include <stdio.h> #include <string.h>#include "sha1.h" #include "convert.h"int log_hexdump(const char *title, const unsigned char *data, int len) {char str[160], octet[10];int ofs, i, k, d;const unsigned char *buf = (const unsigned char *)data;const char dimm[] = "+------------------------------------------------------------------------------+";printf("%s (%d bytes):\r\n", title, len);printf("%s\r\n", dimm);printf("| Offset : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF |\r\n");printf("%s\r\n", dimm);for (ofs = 0; ofs < (int)len; ofs += 16) {d = snprintf( str, sizeof(str), "| %08X: ", ofs );for (i = 0; i < 16; i++) {if ((i + ofs) < (int)len) {snprintf( octet, sizeof(octet), "%02X ", buf[ofs + i] );} else {snprintf( octet, sizeof(octet), " " );}d += snprintf( &str[d], sizeof(str) - d, "%s", octet );}d += snprintf( &str[d], sizeof(str) - d, " " );k = d;for (i = 0; i < 16; i++) {if ((i + ofs) < (int)len) {str[k++] = (0x20 <= (buf[ofs + i]) && (buf[ofs + i]) <= 0x7E) ? buf[ofs + i] : '.';} else {str[k++] = ' ';}}str[k] = '\0';printf("%s |\r\n", str);}printf("%s\r\n", dimm);return 0; }int main(int argc, const char *argv[]) {const char *data = "C1D0F8FB4958670DBA40AB1F3752EF0D";const char *digest_exp_str = "B36BFDB04A31F6C55E0D592B8F2D3219FBC2424D";uint8_t digest_calc[SHA1_DIGEST_LEN];uint8_t digest_exp_hex[SHA1_DIGEST_LEN];sha1_ctx_t ctx;const char *p_calc = data;uint8_t data_bytes[128];uint16_t len_bytes;char data_str[128];if (argc > 1) {p_calc = argv[1];}utils_hex_string_2_bytes(data, data_bytes, &len_bytes);log_hexdump("data_bytes", data_bytes, len_bytes);utils_bytes_2_hex_string(data_bytes, len_bytes, data_str);printf("data_str: %s\n", data_str);if (!strcmp(data, data_str)) {printf("hex string - bytes convert OK\n");} else {printf("hex string - bytes convert FAIL\n");}crypto_sha1_init(&ctx);crypto_sha1_update(&ctx, (uint8_t *)p_calc, strlen(p_calc));crypto_sha1_final(&ctx, digest_calc);utils_hex_string_2_bytes(digest_exp_str, digest_exp_hex, &len_bytes);if (len_bytes == sizeof(digest_calc) && !memcmp(digest_calc, digest_exp_hex, sizeof(digest_calc))) {printf("SHA1 digest test OK\n");log_hexdump("digest_calc", digest_calc, sizeof(digest_calc));} else {log_hexdump("digest_calc", digest_calc, sizeof(digest_calc));log_hexdump("digest_exp", digest_exp_hex, sizeof(digest_exp_hex));printf("SHA1 digest test FAIL\n");}return 0; }

測試用例比較簡單,就是對字符串C1D0F8FB4958670DBA40AB1F3752EF0D進行SHA1運算,期望的摘要結果的hexstring是B36BFDB04A31F6C55E0D592B8F2D3219FBC2424D,這個期望值是用算法工具算出來的。
先用API接口算出摘要值,再與期望值比較,這里有個hexstringtobyte的轉換,如果比較一致則表示API計算OK;反之,接口計算失敗。
同時,也歡迎大家設計提供更多的測試案例代碼。

github倉庫

以上代碼和測試用例,及編譯運行等,可以參考我的github倉庫,有詳細的流程介紹,歡迎大家交流討論。如果有幫助到你的話,記得幫忙點亮一顆星哦。

更多參考鏈接

[1] 【安全算法的github倉庫】
[2] 【安全算法之概述】一文帶你簡要了解常見常用的安全算法
[3] 【安全算法之base64】base64加解密的C語言源碼實現
[4] 【安全算法之MD5】MD5摘要運算的C語言源碼實現
[5] 【安全算法之SHA1】SHA1摘要運算的C語言源碼實現
[6] 【安全算法之SHA224】SHA224摘要運算的C語言源碼實現
[7] 【安全算法之SHA256】SHA256摘要運算的C語言源碼實現
[8] 【安全算法之SHA384】SHA384摘要運算的C語言源碼實現
[9] 【安全算法之SHA512】SHA512摘要運算的C語言源碼實現

總結

以上是生活随笔為你收集整理的【安全算法之SHA1】SHA1摘要运算的C语言源码实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。