C语言实现一个简单的哈希算法
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 函数 creat_w 用于将输入字符串转换为一个 80 元素的无符号长整型数组 w
// 先将输入字符串的前 16 个元素以每 4 个字节为一组,转换为无符号长整型存储在 w 的前 16 个位置
// 然后使用特定规则生成 w 的 16 到 79 的元素
void creat_w(char input[64], unsigned long w[80])
{
int i, j;
unsigned long temp, temp1;
// 将输入字符串的前 16 个元素转换为无符号长整型存储在 w 的前 16 个位置
for (i = 0; i < 16; i++)
{
j = 4 * i;
// 进行字节拼接,将 4 个字节拼接为一个无符号长整型
w[i] = ((long)input[j]) << 24 | ((long)input[1 + j]) << 16 | ((long)input[2 + j]) << 8 | ((long)input[3 + j]) << 0;
}
// 根据前 16 个元素的结果,使用异或和移位操作生成后续元素
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;
}
}
// 函数 ms_len 用于将一个长整型的低 8 位存储到输入字符串的最后 4 个字节中
char ms_len(long a, char intput[64])
{
unsigned long temp3, p1;
int i, j;
temp3 = 0;
// 创建一个掩码 p1,低 8 位为 1,其余为 0
p1 = ~(~temp3 << 8);
// 将长整型 a 的低 8 位存储到输入字符串的最后 4 个字节中
for (i = 0; i < 4; i++)
{
j = 8 * i;
intput[63 - i] = (char)((a & (p1 << j)) >> j);
}
return '0';
}
int main(int argc, char *argv[])
{
// 初始化五个 32 位的哈希常量
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];
char input[64];
long x;
int n;
// 提示用户输入消息
printf("input message:\n");
scanf("%s", input);
// 获取输入消息的长度
n = strlen(input);
// 对输入消息进行处理
if (n < 57)
{
x = n * 8;
// 调用 ms_len 函数处理消息长度信息
ms_len(x, input);
if (n == 56)
{
// 若长度为 56,将后面 4 个字节置为 0
for (i = n; i < 60; i++)
input[i] = 0;
}
else
{
// 若长度小于 56,在消息末尾添加一个 1 字节,后面填充 0 直到第 56 个字节
input[n] = (char)128;
for (i = n + 1; i < 60; i++)
input[i] = 0;
}
}
// 调用 creat_w 函数生成 w 数组
creat_w(input, w);
printf("\n");
A = H0;
B = H1;
C = H2;
D = H3;
E = H4;
// 进行 80 轮的计算操作
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 = H0 + A;
H1 = H1 + B;
H2 = H2 + C;
H3 = H3 + D;
H4 = H4 + E;
// 输出最终的哈希值
printf("\noutput hash value:\n");
printf("%lx%lx%lx%lx%lx", H0, H1, H2, H3, H4);
getchar();
}
input message:
我喜欢你,韵韵output hash value:
fc03946f57039adb4744c6d5e74a9a78efbcf1dc78ebce0137ae77ff95bcc7d43eaffe733260b460
代码解释:
- 整体上,这段 C 语言代码实现了一个简单的哈希算法。
- creat_w函数:
- 该函数接收一个 64 字节的输入字符串
input
和一个 80 元素的无符号长整型数组w
。 - 首先,将
input
的前 16 个元素以每 4 个字节为一组,使用位运算将它们拼接成无符号长整型存储在w
的前 16 个元素中。 - 然后,对于
w
的第 16 到 79 个元素,使用前 16 个元素通过异或和移位操作生成,具体为w[i] = w[i - 16] ^ w[i - 14] ^ w[i - 8] ^ w[i - 3]
,并且对结果进行左移 1 位和右移 31 位的操作,再进行或运算。
- 该函数接收一个 64 字节的输入字符串
- ms_len函数:
- 接收一个长整型
a
和一个 64 字节的字符数组intput
。 - 它将
a
的低 8 位存储到intput
的最后 4 个字节中。通过创建一个掩码p1
只保留低 8 位,然后使用位运算将a
的低 8 位放到intput
的相应位置。
- 接收一个长整型
- main 函数:
- 首先初始化五个 32 位的哈希常量
H0
到H4
。 - 然后提示用户输入一个消息,并读取输入的消息。
- 对输入消息的长度进行判断,如果长度小于 57 字节,会对消息进行填充操作:
- 调用
ms_len
函数处理消息长度信息存储在消息末尾。 - 若长度为 56 字节,将消息后面 4 个字节置为 0;若长度小于 56 字节,在消息末尾添加一个 1 字节,后面填充 0 直到第 56 个字节。
- 调用
- 调用
creat_w
函数将处理后的消息转换为w
数组。 - 进行 80 轮的计算操作:
- 每 20 轮根据不同的逻辑更新
k
和f
的值。 - 进行一系列的移位和运算操作,更新
A
、B
、C
、D
、E
的值。
- 每 20 轮根据不同的逻辑更新
- 最后将更新后的
A
、B
、C
、D
、E
累加到相应的哈希常量H0
到H4
上。 - 输出最终的哈希值。
- 首先初始化五个 32 位的哈希常量
- creat_w函数: