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;
}