常见的加密算法原理与实现:MD5加密

一、基本介绍

MD5加密算法,其全称是Message-Digest Algorithm 5,通常被称为信息摘要算法,所谓的信息摘要就是把明文内容按一定规则生成一段哈希(hash)值,即得到这段明文内容的信息摘要。利用MD5可以基于任意长度的明文字符串生成128位的哈希值,结果唯一且不可逆,因此MD5经常被用于防止信息被篡改、数字签名、以及对明文进行加密等场景。

二、加密原理

MD5算法加密的过程分为三步:处理原文,设置初始值,加密运算。

2.1、处理原文

由于MD5是将信息以512位为一组分组来进行处理,所以首先要计算原文长度(bit)对512的求余结果,如果不等于448,就需要对原文进行填充,使其求余结果等于448。

具体填充方法是第一位为1,余下统一填充为0,填充完后,信息的长度就为N512+448(bit)。之后用剩余的64位(512-448=64位)存储填充前信息的长度,这样处理后的信息长度就是N512+448+64,即512*(N+1)。

其实从这一步来看,好像大部分加密算法都涉及到对转为二进制后的信息的按位填充,以使其满足后续分组处理信息加密的需求。

2.2、设置初始值

MD5的哈希结果长度为128位,按每32位分成一组共4组。这4组结果是由4个初始值A、B、C、D经过不断演变得到。官方定义的A、B、C、D的标准初始值如下(16进制):

A: 01234567
B: 89abcdef
C: fedcba98
D: 76543210

2.3、加密运算

在具体加密过程中,会进行N次循环,N就是在第一步处理原文后的分组个数,假设处理后原文长度为1024,那N就是2,即总共循环两次。

在每次循环内,会将每组的512位信息细分成16个小组,每组长度为32位。进行四轮总计64次运算,每一轮即每十六次运算都会用同一个函数进行处理。运算过程中会用到一组非线性函数如下,&是与运算,|是或运算,~是非运算,^是异或运算:

F(X, Y, Z) =(X&Y) | ((~X) & Z)
G(X, Y, Z) =(X&Z) | (Y & (~Z))
H(X, Y, Z) =X^Y^Z
I(X, Y, Z)=Y^(X|(~Z))

在每次子循环中F、G、H、I 交替使用,第一个16次使用F,第二个16次使用G,第三个16次使用H,第四个16次使用I。

设Mj表示消息的第j个子分组(j的范围:0~15,也就是前面分的16组信息),这里的s,t都是常量,<<<s代表左移s位

FF(a,b,c,d,Mj,s,Ki),表示a=b+((a+F(b,c,d)+Mj+Ki)<<<s)
GG(a,b,c,d,Mj,s,Ki),表示a=b+((a+G(b,c,d)+Mj+Ki)<<<s)
HH(a,b,c,d,Mj,s,Ki),表示a=b+((a+H(b,c,d)+Mj+Ki)<<<s)
II(a,b,c,d,Mj,s,Ki),表示a=b+((a+I(b,c,d)+Mj+Ki)<<<s)

s在四轮循环中的值如下:

s[ 0..15] := {
    7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22 }
s[16..31] := {
    5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20 }
s[32..47] := {
    4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4
  • 15
    点赞
  • 134
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
MD5加密算法是一种常用的哈希函数,它可以将任意长度的消息压缩成一个128位的消息摘要。MD5算法实现原理是将消息分成512位的块,每个块再分成16个32位的子块,然后通过一系列的位运算和非线性函数,对每个子块进行处理,最终得到一个128位的消息摘要。 以下是一个使用C语言实现MD5算法的代码示例: ```c #include <stdio.h> #include <string.h> #include <stdint.h> #define ROTLEFT(a, b) ((a << b) | (a >> (32 - b))) #define F(x, y, z) ((x & y) | (~x & z)) #define G(x, y, z) ((x & z) | (y & ~z)) #define H(x, y, z) (x ^ y ^ z) #define I(x, y, z) (y ^ (x | ~z)) static const uint32_t K[] = { 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 }; static const uint32_t INIT[] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 }; void md5_transform(uint32_t state[4], const uint8_t block[64]) { uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; memcpy(x, block, 64); for (int i = 0; i < 64; i++) { uint32_t f, g; if (i < 16) { f = F(b, c, d); g = i; } else if (i < 32) { f = G(b, c, d); g = (5 * i + 1) % 16; } else if (i < 48) { f = H(b, c, d); g = (3 * i + 5) % 16; } else { f = I(b, c, d); g = (7 * i) % 16; } uint32_t temp = d; d = c; c = b; b = b + ROTLEFT((a + f + K[i] + x[g]), 7); a = temp; } state[0] += a; state[1] += b; state[2] += c; state[3] += d; } void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t *digest) { uint32_t state[4]; uint32_t bitlen[2] = {0, 0}; state[0] = INIT[0]; state[1] = INIT[1]; state[2] = INIT[2]; state[3] = INIT[3]; size_t new_len = ((((initial_len + 8) / 64) + 1) * 64) - 8; uint8_t *msg = calloc(new_len + 64, 1); memcpy(msg, initial_msg, initial_len); msg[initial_len] = 128; uint32_t bits_len = 8 * initial_len; memcpy(msg + new_len, &bits_len, 4); for (int i = 0; i < new_len; i += 64) { md5_transform(state, msg + i); } memcpy(digest, state, 16); free(msg); } int main() { char *msg = "hello, world!"; uint8_t digest[16]; md5((uint8_t *) msg, strlen(msg), digest); for (int i = 0; i < 16; i++) { printf("%02x", digest[i]); } printf("\n"); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值