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

【安全算法之sha1】sha1摘要运算的c语言源码实现概述头文件定义c语言版本的实现源码测试用例github仓库更多参考链接
概述大家都知道摘要算法在安全领域,也是一个特别重要的存在,而sha1是其中比较常见的一种摘要算法,它的特点就是计算复杂度较低,不等长的数据原文输入,可以得出等长的摘要值,这个值是固定为20字节。正是由于这种特殊性,很多重要的数据完整性校验领域,都可以看到sha1的影子。
今天给大家带来sha1的c源码版本实现,欢迎大家深入学习和讨论。
头文件定义头文件定义如下,主要定义了sha1的上下文结构体,以及导出的三个api:
#ifndef __sha1_h__#define __sha1_h__#include #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 #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] 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 (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 0x5a827999 p(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 0x6ed9eba1 p(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 0x8f1bbcdc p(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 0xca62c1d6 p(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 f ctx->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] 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] state[2], digest, 8); put_uint32_be(ctx->state[3], digest, 12); put_uint32_be(ctx->state[4], digest, 16);}测试用例针对sha1导出的三个接口,我编写了以下测试用例:
#include #include #include sha1.h#include convert.hint 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]) 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] 【安全算法之概述】一文带你简要了解常见常用的安全算法


【蓝桥杯嵌入式】第七章 串口发送数据
DC/DC转换厂商:陕西亚成微电子有限公司简介
C++中常用的复合数据类型在Vivado Hls中的应用方法
基于AT73C500/501专用芯片组的电参量测量模块
stm32怎么用
【安全算法之SHA1】SHA1摘要运算的C语言源码实现
一直进展缓慢的“携号转网”最近终于有了眉目
快讯:飞凯光电半导体制造先进材料项目签约太仓港区
小米癫狂:双曲面+5.7寸+骁龙,“最美旗舰”降至冰点价!
双极晶体管的结构配置及电路总结
浅谈大语言模型在医疗领域的应用
尘埃落定后中兴通讯股价攀新高 中兴通讯8月28日举行2018年第二次临时股东大会
如何将DHT11温度和湿度传感器与树莓派连接
Linear推出4通道电压输出16位和12 位DAC系列
自制电源和电话滤波器
人工智能大时代即将到来,为何存储器需求越来越高?
三大运营商为什么同时砍掉多款4G套餐?
发展大模型,是否解决算力问题就够了?
华为Mate10什么时候上市?华为Mate10最新消息:华为Mate10较华为Mate9升级多少?高颜值高配置猜猜多少钱?
verilog中阻塞赋值和非阻塞赋值