C++加密函数MD5使用方法详解

一、MD5算法简介

MD5算法是一种广泛使用的密码散列函数,可以将任意长度的文本转换成128位(16字节)的哈希值。由于哈希值的长度固定,因此可以用来验证信息的完整性和一致性。MD5算法的产生是为了取代MD4算法(由于密码分析学的进步及用户的需求,MD4的安全性已经无法保证)。

MD5算法的核心思想是将输入的信息进行分组,并按照规定的方式进行处理,最后得到一个定长的输出。它的算法是基于位运算、模2的余数运算和逻辑运算等算法的组合

二、MD5算法实现过程

1. 填充

MD5算法处理的是二进制数据,但是输入的数据往往是以字节为单位的,所以需要将输入数据按照512位(64字节)为一组进行划分,并且需要将输入的数据进行填充。
填充规则如下:
(1)如果输入的数据的字节数是64的倍数,不需要填充;
(2)如果输入的数据的字节数不足64字节,需要在末尾填充一个1,其余补0,直到满足64字节;
(3)如果输入的数据的字节数超过64字节,需要在末尾填充一个1,其余补0,直到末尾64字节,然后将所有的64字节分组按照算法进行处理。

2. MD5算法处理

(1)初始化
定义4个32位的参数:A、B、C、D,用于存储中间状态。
每次处理512位时,先将A、B、C、D分别赋成如下值:

A = 0x67452301;
B = 0xefcdab89;
C = 0x98badcfe;
D = 0x10325476;

(2)处理512位
将512位数据划分成16组,每组32位。设当前处理的一组数据为X[i],则下一组数据为X[i+1]。

(3)四轮运算
分别进行4轮运算,每轮运算都将当前结果进行迭代,迭代方式如下:

1)轮 1:F(X,Y,Z) = (X & Y) | (~X & Z);
2)轮 2:G(X,Y,Z) = (X & Z) | (Y & ~Z);
3)轮 3:H(X,Y,Z) = X ^ Y ^ Z;
4)轮 4:I(X,Y,Z) = Y ^ (X | ~Z);

(4)更新中间状态
每轮运算后,都需要更新中间状态A、B、C、D。

A = A + F(B,C,D) + X[i] + T[i];
B = D;
C = B;
D = A;

(5)最终结果
处理完所有的数据块后,将A、B、C、D拼接为一个128位的hash值,即为MD5算法处理结果。

三、使用方法

1. 环境要求

在VS2015中实现,需要用到以下头文件:

#include 
#include 
#include 

由于MD5算法使用了位运算和逻辑运算,因此为了便于处理,可以使用uint32_t类型进行定义。

2. MD5算法代码实现

#include 
#include 
#include 
#include 
#include 

using namespace std;

typedef unsigned int uint32_t;

const uint32_t A = 0x67452301;
const uint32_t B = 0xefcdab89;
const uint32_t C = 0x98badcfe;
const uint32_t D = 0x10325476;

const uint32_t T[64] = { 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
        0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af,
        0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
        0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453,
        0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
        0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681,
        0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
        0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5,
        0x1fa27cf8, 0xc4ac5665, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
        0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0,
        0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 };

inline uint32_t leftrotate(uint32_t x, uint32_t n) {
    return x <> (32 - n);
}

uint32_t F(uint32_t X, uint32_t Y, uint32_t Z) {
    return (X & Y) | (~X & Z);
}

uint32_t G(uint32_t X, uint32_t Y, uint32_t Z) {
    return (X & Z) | (Y & ~Z);
}

uint32_t H(uint32_t X, uint32_t Y, uint32_t Z) {
    return X ^ Y ^ Z;
}

uint32_t I(uint32_t X, uint32_t Y, uint32_t Z) {
    return Y ^ (X | ~Z);
}

void md5(uint32_t* data, uint32_t len, uint32_t* digest) {
    uint32_t* X = new uint32_t[16];
    uint32_t a = A;
    uint32_t b = B;
    uint32_t c = C;
    uint32_t d = D;

    for (uint32_t i = 0; i < len; i += 16) {
        memcpy(X, data + i, 16 * sizeof(uint32_t));
        uint32_t aa = a;
        uint32_t bb = b;
        uint32_t cc = c;
        uint32_t dd = d;

        for (uint32_t 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 tmp = d;
            d = c;
            c = b;
            b = b + leftrotate(a + f + X[g] + T[i], 7);
            a = tmp;
        }
        a += aa;
        b += bb;
        c += cc;
        d += dd;
    }
    delete[] X;
    digest[0] = a;
    digest[1] = b;
    digest[2] = c;
    digest[3] = d;
}

int main() {
    string input = "hello world";
    uint32_t* data = new uint32_t[input.size() + 64];
    memcpy(data, input.c_str(), input.size());
    uint32_t len = ceil(8 * input.size() / 512) * 16;
    memset(data + input.size(), 0, (len - input.size()) * sizeof(uint32_t));
    data[input.size() / 4] |= 0x00000001 << (8 * input.size() % 32);
    uint32_t digest[4];
    md5(data, len, digest);
    delete[] data;

    printf("MD5 hash:\n");
    printf("%08x%08x%08x%08x\n", digest[0], digest[1], digest[2], digest[3]);
    return 0;
}

3. 示例

对字符串”hello world”进行MD5加密:

input: "hello world"
output: 5eb63bbbe01eeed093cb22bb8f5acdc3

完整代码如下:

#include
#include
#include
#include
#include

using namespace std;

typedef unsigned int uint32_t;

const uint32_t A = 0x67452301;
const uint32_t B = 0xefcdab89;
const uint32_t C = 0x98badcfe;
const uint32_t D = 0x10325476;

const uint32_t T[64] = { 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af,
0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453,
0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681,
0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5,
0x1fa27cf8, 0xc4ac5665, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0,
0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 };

inline uint32_t leftrotate(uint32_t x, uint32_t n) {
return x <> (32 - n);
}

uint32_t

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/249194.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝的头像小蓝
上一篇 2024-12-12 13:32
下一篇 2024-12-12 13:32

相关推荐

  • Python中引入上一级目录中函数

    Python中经常需要调用其他文件夹中的模块或函数,其中一个常见的操作是引入上一级目录中的函数。在此,我们将从多个角度详细解释如何在Python中引入上一级目录的函数。 一、加入环…

    编程 2025-04-29
  • Python中capitalize函数的使用

    在Python的字符串操作中,capitalize函数常常被用到,这个函数可以使字符串中的第一个单词首字母大写,其余字母小写。在本文中,我们将从以下几个方面对capitalize函…

    编程 2025-04-29
  • Python中set函数的作用

    Python中set函数是一个有用的数据类型,可以被用于许多编程场景中。在这篇文章中,我们将学习Python中set函数的多个方面,从而深入了解这个函数在Python中的用途。 一…

    编程 2025-04-29
  • Python中init方法的作用及使用方法

    Python中的init方法是一个类的构造函数,在创建对象时被调用。在本篇文章中,我们将从多个方面详细讨论init方法的作用,使用方法以及注意点。 一、定义init方法 在Pyth…

    编程 2025-04-29
  • 三角函数用英语怎么说

    三角函数,即三角比函数,是指在一个锐角三角形中某一角的对边、邻边之比。在数学中,三角函数包括正弦、余弦、正切等,它们在数学、物理、工程和计算机等领域都得到了广泛的应用。 一、正弦函…

    编程 2025-04-29
  • 单片机打印函数

    单片机打印是指通过串口或并口将一些数据打印到终端设备上。在单片机应用中,打印非常重要。正确的打印数据可以让我们知道单片机运行的状态,方便我们进行调试;错误的打印数据可以帮助我们快速…

    编程 2025-04-29
  • Python3定义函数参数类型

    Python是一门动态类型语言,不需要在定义变量时显示的指定变量类型,但是Python3中提供了函数参数类型的声明功能,在函数定义时明确定义参数类型。在函数的形参后面加上冒号(:)…

    编程 2025-04-29
  • Python定义函数判断奇偶数

    本文将从多个方面详细阐述Python定义函数判断奇偶数的方法,并提供完整的代码示例。 一、初步了解Python函数 在介绍Python如何定义函数判断奇偶数之前,我们先来了解一下P…

    编程 2025-04-29
  • Python实现计算阶乘的函数

    本文将介绍如何使用Python定义函数fact(n),计算n的阶乘。 一、什么是阶乘 阶乘指从1乘到指定数之间所有整数的乘积。如:5! = 5 * 4 * 3 * 2 * 1 = …

    编程 2025-04-29
  • Python符号定义和使用方法

    本文将从多个方面介绍Python符号的定义和使用方法,涉及注释、变量、运算符、条件语句和循环等多个方面。 一、注释 1、单行注释 # 这是一条单行注释 2、多行注释 “”” 这是一…

    编程 2025-04-29

发表回复

登录后才能评论