MD5算法的C语言实现

本文详细介绍了MD5信息摘要算法的原理和C语言实现,包括数据填充、分块、初始化、压缩循环等关键步骤,并提供了C语言源代码。通过对不同长度字符串的测试,验证了算法的正确性。
摘要由CSDN通过智能技术生成

算法原理概述

MD5信息摘要算法,( Message-Digest Algorithm 5),是一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值,用于确保信息传输完整一致。

MD5算法使用little-endian(小端模式,即低位字节存在内存低地址),输入任意不定长度信息,算法都首先将其以512-bit进行分组(不足补位),每个512-bit的分组都和四个32-bit的数据一起,进行4次大循环(共64次迭代),并更新这四个32-bit数据。当所有分组都经过上述操作后,最后得到的四个32-bit联合输出固定的128位信息摘要。


算法基本流程

算法的基本过程为:填充、分块、缓冲区初始化、循环压缩、得出结果。
在这里插入图片描述


总体结构

MD5算法的总体结构如上图所示,结构应该还算是比较清晰的。与上次的DES加密算法不同,MD5的主体只有一个压缩函数,我们只需要写好这个函数中的内容,其他都比较简单。

我认为最主要的关键点有两个:

  • 如何对于数据的填充和分块,特别是当输入是以一个文件而不是一个短字符串的形式时;
  • 如何进行算法中的64次迭代。

下面对于算法的流程进行一些简单的说明:

数据填充和分块

在长度为 K-bit 的原始消息数据尾部填充长度为 P-bit 的标识 100…0(一位1后面接若干位0),1 < P < 512(即至少要填充1个bit),使得填充后的消息位数为:K + P \equiv 448 (mod 512). 其中,如果当 K \equiv448 (mod 512) 时,需要P = 512。

再向上述填充好的消息尾部附加 K 值的低64位(即K mod 2^{64}), 最后得到一个总长度位数为K + P+ 64 \equiv 0 (mod 512) 的消息。

得到填充完毕后的消息以后,我们就可以将其恰好分为 L 个 512-bit 的分组。(同时每个分组也可以再细分成16个 32-bit 的小分组,在程序中我们可以使用一个数组保存起来,这在后续的压缩循环中会使用到)

初始化

初始化一个128-bit 的 MD 缓冲区,初始记为CV0,可以表示成4个32-bit 寄存器(A, B, C, D),后续的迭代始终在 MD 缓冲区进行,最后一步的128-bit 输出即为MD5算法的结果。

CV0的初始值为IV。寄存器(A, B, C, D) 置16进制初值作为初始向量IV,并采用小端存储(little-endian) 的存储结构(Intel x86系列CPU原本就采用Little Endian 方式存储):

  • A= 0x67452301
  • B= 0xEFCDAB89
  • C= 0x98BADCFE
  • D= 0x10325476
压缩循环

经过上述初始化步骤后,就可以开始执行算法的总体部分了,也就是压缩函数。

压缩函数每次都从CV(即上文提到的 128-bit 缓冲区)输入128位,从之前分好的消息分组中按顺序输入512位,完成4轮循环后,得到该轮压缩的128位结果,加到原来的缓冲区中,然后用下一分组继续上述步骤。(说具体一点,就是函数每次都从缓冲区(A, B, C, D)拿到四个数a, b, c, d,然后对于a, b, c, d进行压缩循环操作,把最后得到的结果a, b, c, d加到原来的(A, B, C, D)中,下一次函数

  • 2
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个用C语言实现MD5加密算法的示例: ```c #include <stdio.h> #include <string.h> #include <stdint.h> #define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c)))) void md5(uint8_t *initial_msg, size_t initial_len) { uint32_t h0, h1, h2, h3; uint8_t *msg = NULL; uint32_t *w = NULL; uint32_t a, b, c, d, i, f, g, temp; size_t new_len, offset; // 初始化变量 h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476; // 对消息进行预处理 new_len = ((((initial_len + 8) / 64) + 1) * 64); msg = (uint8_t *)malloc(new_len); memcpy(msg, initial_msg, initial_len); msg[initial_len] = 128; offset = initial_len + 1; while (offset < new_len - 8) { msg[offset] = 0; offset++; } uint64_t bits_len = (uint64_t)initial_len * 8; memcpy(msg + new_len - 8, &bits_len, 8); // 处理消息的每个块 for (offset = 0; offset < new_len; offset += 64) { w = (uint32_t *)(msg + offset); // 初始化散列值 a = h0; b = h1; c = h2; d = h3; // 主循环 for (i = 0; i < 64; i++) { if (i < 16) { f = (b & c) | ((~b) & d); g = i; } else if (i < 32) { f = (d & b) | ((~d) & c); g = (5 * i + 1) % 16; } else if (i < 48) { f = b ^ c ^ d; g = (3 * i + 5) % 16; } else { f = c ^ (b | (~d)); g = (7 * i) % 16; } temp = d; d = c; c = b; b = b + LEFTROTATE((a + f + k[i] + w[g]), r[i]); a = temp; } // 更新散列值 h0 += a; h1 += b; h2 += c; h3 += d; } // 释放内存 free(msg); // 输出散列值 printf("MD5 Hash: %08x%08x%08x%08x\n", h0, h1, h2, h3); } int main() { char *msg = "Hello, world!"; size_t len = strlen(msg); md5((uint8_t *)msg, len); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值