SHA-1(Secure Hash Algorithm 1)是一种密码学哈希函数,由美国国家安全局(NSA)设计并由美国国家标准与技术研究院(NIST)发布。它于1993年首次推出,是SHA家族中最早的成员之一,生成一个160位(20字节)的哈希值。
SHA-1算法主要包括以下几个步骤:
消息填充:将输入数据扩展到一个比特长度为64比特的整数倍的长度,并在数据末尾附加一个1比特的“1”,然后是若干个“0”,最后附加一个64比特的数,用于表示原始消息的长度。
初始化缓冲区:SHA-1使用五个32位寄存器(A、B、C、D、E)作为缓冲区,初始值为特定的常量。
处理消息块:将消息分成512比特的块,每块依次进行80轮的复杂操作。在每一轮中,使用逻辑函数、非线性函数、位操作和常量,将消息块与缓冲区中的数据进行混合。
生成哈希值:所有消息块处理完成后,缓冲区中的内容被连接起来,生成160位的哈希值。
尽管SHA-1曾是一个广泛应用的哈希算法,但随着时间的推移,研究人员发现了它的安全性问题:
//// Created by shug on 2024/8/24.//#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdint.h> typedef struct { uint32_t state[5]; // ABCDE五个状态变量 uint32_t count[2]; // 计数器,表示已经处理的位数 uint8_t buffer[64]; // 输入缓冲区} SHA1_CTX; void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]);void SHA1_Init(SHA1_CTX *context);void SHA1_Update(SHA1_CTX *context, const uint8_t *data, uint32_t len);void SHA1_Final(uint8_t digest[20], SHA1_CTX *context);void SHA1_Encode(uint8_t *output, uint32_t *input, uint32_t len);void SHA1_Decode(uint32_t *output, const uint8_t *input, uint32_t len);void SHA1_memcpy(uint8_t *output, const uint8_t *input, uint32_t len);void SHA1_memset(uint8_t *output, int value, uint32_t len); #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) #define F0(b, c, d) ((b & c) | (~b & d))#define F1(b, c, d) (b ^ c ^ d)#define F2(b, c, d) ((b & c) | (b & d) | (c & d)) #define FF0(a, b, c, d, e, w) { \ e += ROTATE_LEFT(a, 5) + F0(b, c, d) + w + 0x5A827999; \ b = ROTATE_LEFT(b, 30); \} #define FF1(a, b, c, d, e, w) { \ e += ROTATE_LEFT(a, 5) + F1(b, c, d) + w + 0x6ED9EBA1; \ b = ROTATE_LEFT(b, 30); \} #define FF2(a, b, c, d, e, w) { \ e += ROTATE_LEFT(a, 5) + F2(b, c, d) + w + 0x8F1BBCDC; \ b = ROTATE_LEFT(b, 30); \} #define FF3(a, b, c, d, e, w) { \ e += ROTATE_LEFT(a, 5) + F1(b, c, d) + w + 0xCA62C1D6; \ b = ROTATE_LEFT(b, 30); \} // 初始化SHA1上下文void SHA1_Init(SHA1_CTX *context) { context->count[0] = context->count[1] = 0; context->state[0] = 0x67452301; context->state[1] = 0xEFCDAB89; context->state[2] = 0x98BADCFE; context->state[3] = 0x10325476; context->state[4] = 0xC3D2E1F0;} // 更新SHA1上下文void SHA1_Update(SHA1_CTX *context, const uint8_t *data, uint32_t len) { uint32_t i, j; j = (context->count[0] >> 3) & 63; if ((context->count[0] += len << 3) < (len << 3)) { context->count[1]++; } context->count[1] += (len >> 29); if ((j + len) > 63) { SHA1_memcpy(&context->buffer[j], data, (i = 64 - j)); SHA1_Transform(context->state, context->buffer); for (; i + 63 < len; i += 64) { SHA1_Transform(context->state, &data[i]); } j = 0; } else { i = 0; } SHA1_memcpy(&context->buffer[j], &data[i], len - i);} // 最终生成SHA1哈希值void SHA1_Final(uint8_t digest[20], SHA1_CTX *context) { uint8_t finalcount[8]; uint32_t i; for (i = 0; i < 8; i++) { finalcount[i] = (uint8_t)((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); } SHA1_Update(context, (uint8_t *)"\200", 1); while ((context->count[0] & 504) != 448) { SHA1_Update(context, (uint8_t *)"\0", 1); } SHA1_Update(context, finalcount, 8); SHA1_Encode(digest, context->state, 20); SHA1_memset((uint8_t *)context, 0, sizeof(*context));} // SHA1的核心变换函数void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]) { uint32_t a, b, c, d, e, t, w[80]; SHA1_Decode(w, buffer, 64); for (t = 16; t < 80; t++) { w[t] = ROTATE_LEFT(w[t-3] ^ w[t-8] ^ w[t-14] ^ w[t-16], 1); } a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; for (t = 0; t < 20; t++) { FF0(a, b, c, d, e, w[t]); t++; FF0(e, a, b, c, d, w[t]); t++; FF0(d, e, a, b, c, w[t]); t++; FF0(c, d, e, a, b, w[t]); t++; FF0(b, c, d, e, a, w[t]); } for (; t < 40; t++) { FF1(a, b, c, d, e, w[t]); t++; FF1(e, a, b, c, d, w[t]); t++; FF1(d, e, a, b, c, w[t]); t++; FF1(c, d, e, a, b, w[t]); t++; FF1(b, c, d, e, a, w[t]); } for (; t < 60; t++) { FF2(a, b, c, d, e, w[t]); t++; FF2(e, a, b, c, d, w[t]); t++; FF2(d, e, a, b, c, w[t]); t++; FF2(c, d, e, a, b, w[t]); t++; FF2(b, c, d, e, a, w[t]); } for (; t < 80; t++) { FF3(a, b, c, d, e, w[t]); t++; FF3(e, a, b, c, d, w[t]); t++; FF3(d, e, a, b, c, w[t]); t++; FF3(c, d, e, a, b, w[t]); t++; FF3(b, c, d, e, a, w[t]); } state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; SHA1_memset((uint8_t *)w, 0, sizeof(w));} // 编码,将32位整数转换为字节序列void SHA1_Encode(uint8_t *output, uint32_t *input, uint32_t len) { uint32_t i, j; for (i = 0, j = 0; j < len; i++, j += 4) { output[j] = (uint8_t)((input[i] >> 24) & 0xff); output[j + 1] = (uint8_t)((input[i] >> 16) & 0xff); output[j + 2] = (uint8_t)((input[i] >> 8) & 0xff); output[j + 3] = (uint8_t)(input[i] & 0xff); }} // 解码,将字节序列转换为32位整数void SHA1_Decode(uint32_t *output, const uint8_t *input, uint32_t len) { uint32_t i, j; for (i = 0, j = 0; j < len; i++, j += 4) { output[i] = ((uint32_t)input[j] << 24) | ((uint32_t)input[j + 1] << 16) | ((uint32_t)input[j + 2] << 8) | ((uint32_t)input[j + 3]); }} // 内存拷贝void SHA1_memcpy(uint8_t *output, const uint8_t *input, uint32_t len) { uint32_t i; for (i = 0; i < len; i++) { output[i] = input[i]; }} // 内存设置void SHA1_memset(uint8_t *output, int value, uint32_t len) { uint32_t i; for (i = 0; i < len; i++) { output[i] = (uint8_t)value; }} // 打印哈希值void SHA1_Print(uint8_t digest[20]) { for (int i = 0; i < 20; i++) { printf("%02x", digest[i]); } printf("\n");} int main(int argc, char *argv[]) { SHA1_CTX context; uint8_t digest[20]; uint8_t *string = (uint8_t *)"hello world"; SHA1_Init(&context); SHA1_Update(&context, string, strlen((char *)string)); SHA1_Final(digest, &context); printf("SHA1 (\"%s\") = ", string); SHA1_Print(digest); return 0;}