MD5加密原理和C语言代码实现

目录


MD5加密原理和C语言代码实现

一、什么是MD5加密

MD5(Message Digest Algorithm 5)是一种常用的哈希函数,用于将任意长度的数据映射为固定长度的数据串(通常是128位)。MD5广泛用于安全领域和软件工程中,例如存储密码、数字签名等。
MD5的加密原理如下:

  • 1. 消息分块:将输入消息分成512位(64字节)的分块。
  • 2. 填充:如果消息长度不是512位的倍数,则在末尾填充比特,使其长度达到512位。填充的方式是在消息的末尾添加一个1和若干个0,然后再添加一个64位的原始消息长度(以比特为单位)。
  • 3. 初始化:初始化一个128位的缓冲区,作为结果的初始值。这些缓冲区包含四个32位寄存器:A、B、C和D。
  • 4. 处理分块:对每个512位的消息分块进行处理,使用一个循环结构,通过对缓冲区的操作来更新缓冲区的值。每个分块被拆分成16个32位字,进行64轮的操作,每轮操作都会更新缓冲区的值。
  • 5. 输出:最终得到的128位缓冲区的值即为MD5哈希值。

MD5的安全性已经受到了严重的威胁,因为存在诸多碰撞攻击,使得MD5不再适合用于安全领域。因此,在对安全性要求较高的场景中,建议使用更安全的哈希函数,如SHA-256等。

二、C语言实现例子

头文件

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

宏定义、全局变量和静态局部变量

#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c))))

// MD5算法中使用的常量
const uint32_t k[] = {
    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};

// 初始化MD5寄存器的值
const uint32_t initial_h[] = {
    0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
};

函数

/********************************************************************
 *
 *	name	 :	pad_data
 *	function :  MD5加密算法
 *	argument :
 *              @data    :需要加密字符串
 *              @len 	 :需要加密字符串的字节大小
 *              @bitlen	 :需要加密字符串的bit大小
 *	retval	 :  none
 *	author	 :  17666589210@163.com
 *	date	 :  2024/06/12
 * 	note	 :  none
 *
 * *****************************************************************/
// 对数据进行填充
void pad_data(uint8_t *data, size_t len, uint64_t bitlen) {
    // 填充一个1
    data[len++] = 0x80;

    // 填充0直到满足64字节的倍数
    while (len % 64 != 56) {
        data[len++] = 0x00;
    }

    // 在末尾追加数据长度(64位表示)
    for (int i = 0; i < 8; ++i) {
        data[len++] = (bitlen >> (i * 8)) & 0xFF;
    }
}

函数

/********************************************************************
 *
 *	name	 :	md5
 *	function :  MD5加密算法
 *	argument :
 *              @initial_msg    :需要加密字符串
 *              @initial_len 	:需要加密字符串的字节大小
 *              @hash	 		:缓冲区的地址
 *	retval	 :  none
 *	author	 :  17666589210@163.com
 *	date	 :  2024/06/12
 * 	note	 :  none
 *
 * *****************************************************************/
// MD5算法核心函数
void md5(uint8_t *initial_msg, size_t initial_len, uint32_t *hash) {
    uint8_t *msg = NULL;
    size_t new_len, offset;
    uint32_t w[64];
    uint32_t a, b, c, d, i, j, t;

    // 初始化寄存器
    hash[0] = initial_h[0];
    hash[1] = initial_h[1];
    hash[2] = initial_h[2];
    hash[3] = initial_h[3];

    // 对数据进行填充
    new_len = initial_len * 8 + 1 + 64;
    msg = (uint8_t*)malloc(new_len);
    memcpy(msg, initial_msg, initial_len);
    pad_data(msg, initial_len, initial_len * 8);

    // 处理数据
    for(offset = 0; offset < new_len; offset += 64) {
        // 将分组的数据填充到w数组中
        for (i = 0; i < 16; ++i) {
            w[i] = (msg[offset + i * 4 + 0] << 24) |
                   (msg[offset + i * 4 + 1] << 16) |
                   (msg[offset + i * 4 + 2] << 8) |
                   (msg[offset + i * 4 + 3]);
        }
        for (i = 16; i < 64; ++i) {
            w[i] = w[i-16] + LEFTROTATE(w[i-15], 7) + w[i-7] + LEFTROTATE(w[i-2], 15);
        }

        // 初始化临时变量
        a = hash[0];
        b = hash[1];
        c = hash[2];
        d = hash[3];

        // 主循环
        for (i = 0; i < 64; ++i) {
            if (i < 16) {
                t = (b & c) | ((~b) & d);
                j = i;
            } else if (i < 32) {
                t = (d & b) | ((~d) & c);
                j = (5 * i + 1) % 16;
            } else if (i < 48) {
                t = b ^ c ^ d;
                j = (3 * i + 5) % 16;
            } else {
                t = c ^ (b | (~d));
                j = (7 * i) % 16;
            }

            t = t + a + k[i] + w[j];
            a = d;
            d = c;
            c = b;
            b = b + LEFTROTATE(t, 12);
        }

        // 更新寄存器值
        hash[0] += a;
        hash[1] += b;
        hash[2] += c;
        hash[3] += d;
    }

    // 释放内存
    free(msg);
}

主函数

int main() {
    // 示例数据
    uint8_t initial_msg[] = "Hello, world!";
    size_t initial_len = strlen((char*)initial_msg);
    uint32_t hash[4];

    // 计算MD5散列值
    md5(initial_msg, initial_len, hash);
    printf("MD5 散列值为: ");
    for (int i = 0; i < 4; ++i) {
        printf("%02x", hash[i]);
    }
    printf("\n");

    return 0;
}
posted @ 2024-06-12 21:08  52017  阅读(686)  评论(0编辑  收藏  举报