Bootstrap

C语言实现一个简单的哈希算法

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 语言代码实现了一个简单的哈希算法。
    1. 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 位的操作,再进行或运算。
    2. ms_len函数:
      • 接收一个长整型 a 和一个 64 字节的字符数组 intput
      • 它将 a 的低 8 位存储到 intput 的最后 4 个字节中。通过创建一个掩码 p1 只保留低 8 位,然后使用位运算将 a 的低 8 位放到 intput 的相应位置。
    3. main 函数:
      • 首先初始化五个 32 位的哈希常量 H0H4
      • 然后提示用户输入一个消息,并读取输入的消息。
      • 对输入消息的长度进行判断,如果长度小于 57 字节,会对消息进行填充操作:
        • 调用 ms_len 函数处理消息长度信息存储在消息末尾。
        • 若长度为 56 字节,将消息后面 4 个字节置为 0;若长度小于 56 字节,在消息末尾添加一个 1 字节,后面填充 0 直到第 56 个字节。
      • 调用 creat_w 函数将处理后的消息转换为 w 数组。
      • 进行 80 轮的计算操作:
        • 每 20 轮根据不同的逻辑更新 kf 的值。
        • 进行一系列的移位和运算操作,更新 ABCDE 的值。
      • 最后将更新后的 ABCDE 累加到相应的哈希常量 H0H4 上。
      • 输出最终的哈希值。
;