MD5算法实现解读
c语言md5加密函数

c语言md5加密函数摘要:1.引言2.MD5 加密算法简介3.C 语言实现MD5 加密函数4.示例代码及运行结果5.总结正文:1.引言随着信息技术的不断发展,数据安全已成为越来越受到关注的问题。
在众多的加密算法中,MD5 算法是一种广泛应用的摘要算法,它能够将任意长度的输入数据转化为固定长度的输出,通常为128 位二进制数。
在C 语言中,如何实现MD5 加密函数呢?本文将详细介绍C 语言中MD5 加密函数的实现方法。
2.MD5 加密算法简介MD5(Message-Digest 5)算法是一种基于Hash 函数的摘要算法,由美国计算机科学家Ronald Rivest 于1991 年提出。
它的主要作用是将不同长度的输入数据转化为固定长度的输出,即128 位二进制数。
MD5 算法的输入数据可以是任意长度,但输出总是128 位。
由于其算法复杂度高、碰撞抵抗能力强等特点,MD5 算法被广泛应用于数据完整性校验、数字签名等领域。
3.C 语言实现MD5 加密函数下面我们将给出一个C 语言实现的MD5 加密函数示例。
这个示例代码是基于OpenSSL 库的,因此在使用前需要先安装OpenSSL 库。
以下是代码实现:```c#include <stdio.h>#include <string.h>#include <openssl/md5.h>// 计算MD5 加密void md5_encrypt(const char *input, char *output) {MD5_CTX md5;MD5_Init(&md5);MD5_Update(&md5, input, strlen(input));MD5_Final(output, &md5);}int main() {char input[] = "Hello, world!";char output[MD5_DIGEST_LENGTH];printf("原始数据:%s", input);md5_encrypt(input, output);printf("MD5 加密后的数据:");for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {printf("%02x", output[i]);}printf("");return 0;}```这段代码首先引入了必要的头文件,然后定义了一个名为`md5_encrypt`的函数,用于计算输入字符串的MD5 加密。
MD5算法实验报告

MD5算法实验报告实验报告:MD5算法的原理与应用一、实验目的本实验旨在通过研究MD5(Message-Digest Algorithm 5)算法的原理和应用,了解其工作原理和实现过程,并掌握其具体应用技巧。
二、实验内容1.了解MD5算法的基本原理和特点;2.分析MD5算法的具体实现过程;3.实现一个简单的MD5加密程序,并进行测试;4.掌握MD5算法的应用技巧。
三、实验原理1. 输入任意长度的数据,输出固定长度的Hash值,通常为128位;2. 安全性较高,Hash值的变化能较好地反映原始数据的变化;3. 不可逆性:无法通过Hash值反推出原始数据;4. Hash值相同的概率很低,冲突概率较小。
1.数据填充:对输入数据进行填充,使其长度满足一定要求;2.划分数据:将填充后的数据划分为多个512位的数据块;3.初始化变量:设置四个32位的变量,作为初始值;4.处理数据块:对每个数据块进行处理,分为四轮,每轮包括四个步骤,即置换、模运算、加法和循环左移操作。
5. 输出结果:将四个32位变量连接起来,即得到最终的128位Hash值。
四、实验过程1.学习MD5算法的原理和实现细节;2. 使用Python编程语言实现一个简单的MD5加密程序,并进行测试。
实验代码如下:```import hashlibdef md5_encrypt(source):md5 = hashlib.md5md5.update(source.encode('utf-8'))return md5.hexdigestif __name__ == '__main__':source_str = input("请输入要加密的字符串:")encrypted_str = md5_encrypt(source_str)print("加密后的字符串为:", encrypted_str)```五、实验结果与分析通过上述实验代码,可以输入一个字符串,程序将会对该字符串进行MD5加密,并将加密结果输出。
MD5算法原理及其实现

MD5算法原理及其实现MD5(Message Digest Algorithm 5)是一种常用的哈希函数,它可以将输入数据通过一系列的计算步骤转换成固定长度的输出,通常为128位。
MD5算法是由美国密码学家、计算机安全专家罗纳德·李维斯特(Ronald Rivest)设计的,它在1992年成为了国际标准,常用于数据的完整性校验以及密码存储等应用场景。
1.填充消息:先将待处理的消息填充至长度为448(模512)的倍数,填充规则为在消息末尾添加一个1,然后添加若干个0,最后添加一个64位的原始消息长度。
这样可以确保消息的长度满足要求。
2.初始化缓冲区:将一个128位的缓冲区(A、B、C、D)初始化为特定的初始值(常数)。
3.消息分组:将填充后的消息分成若干个512位(16个32位字)的消息块。
4.处理消息块:对每个消息块进行相同的操作,操作包括四轮循环迭代(步骤5~8)。
5.轮函数1:将A、B、C、D的值作为输入,通过逻辑函数(与、或、非、异或)、非线性函数F以及循环左移操作,生成新的A、B、C、D的值。
6.轮函数2:将D、A、B、C的值作为输入,通过逻辑函数、非线性函数G以及循环左移操作,生成新的D、A、B、C的值。
7.轮函数3:将C、D、A、B的值作为输入,通过逻辑函数、非线性函数H以及循环左移操作,生成新的C、D、A、B的值。
8.轮函数4:将B、C、D、A的值作为输入,通过逻辑函数、非线性函数I以及循环左移操作,生成新的B、C、D、A的值。
9.更新缓冲区:将处理完的消息块的结果与当前的缓冲区值相加,得到新的缓冲区值。
10.重复第4~9步,直到处理完所有消息块。
11.输出哈希值:将最终的缓冲区值A、B、C、D按照指定顺序连接起来,得到128位的哈希值。
```MD5 (message)1.将消息填充为512位的块2.初始化缓冲区3.划分消息块4.遍历消息块进行处理5.初始化变量6.进行4轮循环迭代7.轮函数操作:逻辑运算、非线性函数、循环左移8.更新缓冲区9.输出哈希值```总的来说,MD5算法采用了位运算、逻辑运算以及非线性函数等操作,通过对消息的分组以及四轮的循环迭代处理,最终生成128位的消息摘要。
MD5加密概述原理以及实现

MD5加密概述原理以及实现MD5(Message Digest Algorithm 5)是一种常用的哈希函数,用于将任意长度的数据转换为固定长度的哈希值。
在网络传输和数据存储中,MD5广泛用于校验数据完整性,验证密码以及防止篡改等场景。
1.哈希值固定长度:无论输入数据的长度是多少,MD5算法生成的哈希值都是128位(16字节)的二进制数字。
2.唯一性:在理论上,MD5生成的哈希值应该是唯一的。
也就是说,不同的输入数据生成的哈希值不会相同。
3.不可逆性:MD5是一种单向函数,即无法通过从哈希值反向推导出原始数据。
只能通过对比不同数据的哈希值来判断其是否相同。
MD5算法的实现过程可以分为以下几个步骤:1.填充数据:将输入数据按字节切分成512位的数据段,并在数据段末尾填充一定数量的0,使其长度能被512整除。
2.初始化缓冲区:定义四个32位的缓冲区(A、B、C、D),作为算法计算的中间结果。
3.处理数据段:对每个数据段进行相同的处理流程,包括四轮的循环压缩和变换操作。
4.输出结果:将最后一次处理后的缓冲区内容按顺序连接起来,形成128位的MD5哈希值。
具体的实现细节如下:1.填充数据:如果输入数据的长度不能被512整除,就在末尾填充一个1和若干个0,使得填充后的长度满足对512取余等于448、之后,再在末尾追加64位的原始数据长度,以二进制形式表示。
2.初始化缓冲区:将四个32位的缓冲区(A、B、C、D)初始化为固定的初始值。
3.处理数据段:将每个数据段分为16个32位的子块,对每个子块进行以下四轮的循环压缩和变换操作。
-第一轮循环:通过对字节数组进行位运算,将每个子块与缓冲区中的四个值进行一系列的逻辑运算,然后更新缓冲区的值。
-第二轮循环:将第一轮循环得到的缓冲区值重新排列并加上一个常量,然后再进行一系列的逻辑运算。
-第三轮循环:将第二轮循环得到的缓冲区值再次进行一系列的逻辑运算。
-第四轮循环:将第三轮循环得到的缓冲区值再次进行一系列的逻辑运算。
MD5加密算法详解

MD5加密算法详解MD5(Message Digest Algorithm 5)是一种常见的哈希算法,用于将任意长度的信息转换为固定长度(通常为128位)的输出。
它是MD4算法的改进版本,由Ron Rivest在1991年设计。
MD5算法在密码学和数据完整性检查方面被广泛应用。
1.算法概述:MD5算法的输入是任意长度的消息,输出是一个128位(32个字符)的消息摘要。
这个摘要是唯一的,即使消息只有微小的变化,它的摘要也会有较大的差异。
MD5具有以下特点:-可逆性:MD5是单向散列函数,即不能从摘要中恢复原始消息。
这意味着无法通过知道MD5摘要的人来确定原始消息,所以MD5算法通常用于验证消息的完整性。
-高度可靠性:MD5算法能够快速计算,且其输出分布均匀,几乎每个消息都有不同的摘要。
-高速性:MD5算法的计算速度非常快,在软件和硬件上都可以轻松实现。
2.算法步骤:MD5算法的核心包括四个基本步骤:填充、初始化、循环操作和输出。
下面是详细的步骤说明:-填充:首先将消息进行填充,使其长度(以比特位为单位)满足对512求余等于448、填充的格式为一个1后面跟随若干个0,然后是64位的原始消息长度。
-初始化:使用4个固定的32位字作为初始变量(A、B、C、D),这些变量用于存储中间摘要和最终摘要。
-循环操作:MD5算法使用了64个循环运算来处理填充后的消息。
在每个循环中,输入消息的一部分被处理,并按照一系列算法步骤进行变换,然后将变换的结果添加到当前状态变量中。
-输出:循环运算结束后,将中间变量连接起来形成最终的128位摘要。
最终的结果可以表示为一个32位的十六进制数。
3.安全性:尽管MD5算法在之前被广泛应用于检验文件完整性和密码验证等领域,但现在已经不再被认为是安全的。
主要原因有:-容易受到碰撞攻击:由于MD5算法的输出空间相对较小(只有128位),因此存在相同摘要的不同输入。
这使得攻击者可以通过找到相同摘要的两个不同输入来冒充验证身份或篡改数据。
MD5原理及定义算法

MD5原理及定义算法MD5(Message-Digest Algorithm 5)是一种广泛使用的密码散列函数,用于产生数字指纹,以确保数据的完整性和一致性。
它是由美国密码学家Ronald Rivest于1991年设计的,并在RFC 1321中被正式定义。
MD5算法主要通过将任意长度的输入数据转换成128位固定长度的输出,实现数据的不可逆变换。
它的主要原理可以分为以下几个步骤:1.填充:首先,MD5算法会将输入数据以512位(64字节)为单位进行分块处理,并对每个分块进行填充。
填充的目的是确保输入数据长度是512位的整数倍,并在最后一个分块中添加一些额外的信息,以表示数据的原始长度。
2.初始化:MD5算法使用一个128位的缓冲区作为内部状态,并将其初始化为指定的初始值。
这个初始值是由32位整数的平方根的前32位小数部分的二进制形式组成。
这个初始值起到了混淆的作用,使得算法对不同的输入数据产生不同的输出结果。
3.迭代运算:MD5算法通过对每个分块进行四轮迭代运算来混合和置换数据。
每轮迭代都包括四个单元操作,分别是“加法、非线性函数、环移位和级联”。
这些操作在每轮迭代中不断改变缓冲区的值,使其对输入数据产生复杂的影响。
4.输出:当所有分块都被处理完毕后,MD5算法将最终结果从缓冲区中提取出来,得到一个128位的输出值。
这个输出值通常以16进制字符串的形式表示,作为数据的唯一指纹。
然而,MD5算法并不是无懈可击的。
由于其设计的时候主要考虑了速度和效率,而忽略了安全性,使得它在现代密码学领域已经变得相对不安全。
主要的安全问题包括碰撞攻击和预映像攻击。
碰撞攻击是指找到两个不同的输入数据生成相同MD5哈希值的过程。
由于MD5输出的128位长度相对较小,所以在空间中找到碰撞是可行的。
预映像攻击则是指从给定的输出值逆推出对应的输入数据。
这些攻击都利用了MD5算法的一些弱点和漏洞。
鉴于MD5的安全性问题,现在已经不推荐在安全领域中使用该算法,尤其是对于密码存储和校验等应用场景。
MD5算法简介及编程实现

实验三MD5算法实验目的:1.了解哈希函数的概念和功能,以及一些典型的哈希函数2.进一步理解MD5算法的概念及结构,掌握MD5算法对数据的处理过程3.通过编程模拟MD5算法的处理步骤实验内容:一.MD5算法概述MD5算法是一种消息摘要算法(Message Digest Algorithm),此算法以任意长度的信息(message)作为输入进行计算,产生一个128-bit(16-byte)的指纹或报文摘要(fingerprint or message digest)。
两个不同的message产生相同message digest的几率相当小,从一个给定的message digest逆向产生原始message更是困难,因此MD5算法适合用在数字签名应用中。
MD5实现简单,在32位的机器上运行速度也相当快,当然实际应用也不仅仅局限于数字签名。
MD5算法的处理步骤:第一步:增加填充增加padding使得数据长度(bit为单位)模512为448。
如果数据长度正好是模512为448,增加512个填充bit,也就是说填充的个数为1-512。
第一个bit为1,其余全部为0。
(即第一个字节为0x80)第二步:补足长度将数据长度转换为64bit的数值,如果长度超过64bit所能表示的数据长度的范围,值保留最后64bit,增加到前面填充的数据后面,使得最后的数据为512bit的整数倍。
也就是32bit的16倍的整数倍。
在RFC1321中,32bit称为一个word。
第三步:初始化变量:用到4个变量,分别为A、B、C、D,均为32bit长。
初始化为:A: 0x01234567B: 0x89abcdefC: 0xfedcba98D: 0x76543210第四步:数据处理首先定义4个辅助函数:F(X,Y,Z) = XY v not(X) ZG(X,Y,Z) = XZ v Y not(Z)H(X,Y,Z) = X xor Y xor ZI(X,Y,Z) = Y xor (X v not(Z))其中:XY表示按位与,X v Y表示按位或,not(X)表示按位取反。
加密系列MD5加密和解密算法详解代码示例

加密系列MD5加密和解密算法详解代码示例MD5加密算法是一种广泛应用的密码加密算法,它将任意长度的数据映射为固定长度的128位哈希值。
MD5加密算法是不可逆的,即通过密文无法还原得到原始数据。
MD5加密算法的实现可以通过编写代码来完成。
下面是一个示例的MD5加密算法的代码:```import hashlibdef md5_encrypt(data):md5 = hashlib.md5md5.update(data.encode('utf-8'))return md5.hexdigestif __name__ == '__main__':data = input("请输入需要加密的数据:")encrypted_data = md5_encrypt(data)print("加密结果为:", encrypted_data)```以上代码实现了一个简单的MD5加密算法。
首先导入了`hashlib`模块,该模块提供了一系列用于数据加密的算法,包括MD5算法。
`md5_encrypt`函数接收一个字符串作为输入数据,并将其转换为字节流形式,然后使用`hashlib.md5`方法创建了一个MD5对象。
接着,通过调用MD5对象的`update`方法将输入数据添加到加密流程中。
最后,通过调用MD5对象的`hexdigest`方法获得加密后的结果,并将其返回。
在`if __name__ == '__main__'`下方的代码段中,首先获取用户输入的数据,然后调用`md5_encrypt`函数对其进行加密,并将结果打印到控制台。
下面是MD5解密算法的示例代码:```import hashlibdef md5_decrypt(encrypted_data):md5 = hashlib.md5md5.update(encrypted_data.encode('utf-8'))return md5.hexdigestif __name__ == '__main__':encrypted_data = input("请输入需要解密的数据:")decrypted_data = md5_decrypt(encrypted_data)print("解密结果为:", decrypted_data)```以上代码实现了一个简单的MD5解密算法。
常用哈希算法原理及实现方式

常用哈希算法原理及实现方式哈希算法是一种广泛应用于计算机科学和信息安全领域的算法。
它具有快速、高效、安全的特点,在文件校验、密码验证等方面都有着广泛的应用。
哈希算法的底层原理和实现方式有很多种,下面将对几种常用的哈希算法进行简要介绍。
一、MD5算法MD5算法是一种广泛使用的哈希算法,它可以将任意长度的消息进行压缩,生成一个固定长度的哈希值。
MD5算法的核心思想是将输入消息分成固定长度的块,对每个块进行迭代处理,并且每个处理过程都包含非常复杂的逻辑运算。
最终,MD5算法将每个块的结果合并,生成128位的哈希值。
MD5算法的实现方式可以使用各种编程语言进行编写。
例如,在C语言中,可以使用OpenSSL库提供的MD5函数来实现。
二、SHA算法SHA算法是一种用于加密和安全校验的哈希算法。
SHA算法的原理与MD5算法类似,但其哈希值长度更长,密钥空间更大,安全性更高。
SHA算法有多个版本,其中最常用的是SHA-1和SHA-256。
SHA-1是一种产生160位哈希值的算法,而SHA-256则可以产生256位的哈希值。
SHA-1算法的实现方式也比较简单,可以使用Java、C++等语言的库来实现。
例如,在Java中,可以使用java.security.MessageDigest类提供的SHA-1函数来计算消息的哈希值。
三、Keccak算法Keccak算法是一种新颖的哈希算法,由比利时密码学家Joan Daemen和Gilles Van Assche开发而成。
该算法基于一种称为“海绵”概念的结构,可以实现高度可变的哈希值长度和高强度的安全性。
Keccak算法目前的标准版本是SHA-3,它可以产生不同长度的哈希值,可以抵抗各种类型的攻击,例如长度扩展攻击和碰撞攻击等。
Keccak算法的实现方法与其他哈希算法略有不同。
它需要使用一个称为“求和”的函数,将消息分块后按位异或操作,再进行轮迭代,最终得到哈希值。
四、BLAKE2算法BLAKE2算法是一种由Jean-Philippe Aumasson、Samuel Neves 和Zooko Wilcox-O'Hearn等人联合开发的哈希算法。
MD5实验报告范文

MD5实验报告范文实验报告:MD5算法的原理、实验过程及结果分析1.实验目的MD5(Message-Digest Algorithm 5)是一种常用的哈希算法,主要用于对消息进行完整性校验和数字签名等应用。
本实验旨在探究MD5算法的原理及实现过程,并通过实验验证其正确性和有效性。
2.实验原理MD5算法主要包括以下步骤:(1)填充消息首先,将消息进行填充,使其长度能够被512位整除。
填充方式为在消息末尾添加一个'1',然后添加若干个'0',以确保消息末尾有64位的原始消息长度。
(2)初始化缓冲区(3)消息分组将填充后的消息按512位分组,每组包含16个32位的子分组。
(4)循环压缩函数对每个分组进行四轮循环操作,共64轮。
每一轮包含四个步骤:F 函数、G函数、H函数和I函数。
每个函数分别对A、B、C、D进行操作,并根据当前轮数选择不同的方式对数据进行置换和变换。
(5)累加结果每轮循环后,计算出的A、B、C、D将与缓冲区中的原始值进行累加。
(6)输出结果经过64轮循环后,得到的缓冲区即为MD5的输出结果。
3.实验过程(1)理论分析根据MD5算法的原理,我们可以分析MD5的输入为任意长度的消息,输出为固定长度(128位)的哈希值。
MD5算法具有较高的计算效率和较好的抗碰撞性能。
(2)实验步骤a.编写MD5算法的编程代码,包括填充消息、初始化缓冲区、消息分组、循环压缩函数等步骤。
b.准备不同长度的测试消息,包括短消息和长消息。
c.分别对不同长度的消息进行哈希计算,并记录计算时间。
d.比较计算结果与预设结果是否一致。
4.实验结果分析经过实验,我们得到了如下结果:(1)对于短消息(长度小于512位),MD5能够在较短时间内完成计算,且计算结果与预设结果一致。
(2)对于长消息(长度大于512位),MD5的计算时间随着消息长度的增加而增加,但计算结果始终保持一致和正确。
5.结论与总结MD5算法是一种常用的哈希算法,具有较高计算效率和较好的抗碰撞性能。
MD5算法原理及代码实现

MD5算法原理及代码实现MD5(Message Digest Algorithm 5)是一种被广泛使用的消息摘要算法,它是MD家族中的第五个版本。
MD5算法能将任意长度的输入数据转换为一个128位(16字节)的散列值,通常表示为32个十六进制数。
1. 填充(Padding):为了使输入消息的位数对512求余数等于448,填充是必要的。
例如,如果输入消息的位数是L,填充后的消息长度为K* 512 + 448,其中K是一个非负整数。
填充后的消息被分为512位(64字节)的块。
2. 初始化(Initialization):算法对四个32位的缓冲区A、B、C、D进行初始化,通常初始化为常量。
这些缓冲区用于保存中间计算结果。
3. 循环(Iteration):通过进行四轮循环的操作,将每个512位的块以及前一个块的连续散列结果作为输入,产生新的散列结果。
每轮循环包括四个步骤:数据的复制、数据的变换、数据的交换以及数据的加法。
4. 输出(Output):将最后一轮循环的输出结果根据顺序连接起来,形成128位的散列值。
下面是一个简单的MD5算法的代码示例,使用Python语言实现:```pythonimport hashlibdef md5(message):md5_hash = hashlib.md5md5_hash.update(message.encode('utf-8'))return md5_hash.hexdigest#测试message = "Hello, world!"md5_value = md5(message)print("MD5 hash value:", md5_value)```在上述代码中,我们首先导入了Python标准库中的hashlib模块,该模块提供了MD5算法的实现。
然后,我们定义了一个名为md5的函数,它接受一个字符串形式的消息作为输入,并返回该消息的MD5散列值。
md5算法实验总结

MD5(Message Digest Algorithm 5)是一种常见的哈希函数,用于产生数字指纹(digest)以及对数据进行完整性验证。
以下是对MD5算法实验的总结:
1. MD5算法的原理:
- MD5算法将任意长度的输入数据转换为128位的输出,通常表示为32个十六进制数字。
- MD5算法的核心是对输入数据进行分组、填充、循环处理和合并等步骤,最终生成128位的摘要。
2. 实验步骤:
- 选择一个字符串或文件作为输入数据。
- 使用MD5算法对输入数据进行处理,生成对应的128位摘要。
- 可以使用现成的MD5算法库或工具,也可以自行编写MD5算法的实现。
3. 实验结果:
- 实验结果将会得到一个128位的十六进制数字,即为MD5摘要。
- 不同的输入数据将会生成不同的MD5摘要,即使输入数据只有微小的变化。
4. 应用场景:
- MD5算法常用于验证数据的完整性,比如下载文件后对文件进行MD5校验,以确保文件未被篡改。
- 在密码存储中,MD5算法曾经被广泛使用,但由于其存在碰撞(collision)风险和加密性能问题,现在不再推荐将MD5用于密码存储。
总的来说,MD5算法是一种常见的哈希算法,用于生成数据的数字指纹。
然而,由于其已知的安全性问题,现在已经不再被推荐用于安全敏感的场景。
在实际应用中,
可以考虑使用更安全的哈希算法,比如SHA-256等。
MD5算法的设计与实现

MD5算法的设计与实现MD5(Message Digest Algorithm 5)是一种常用的哈希算法,用于对任意长度的数据进行加密和校验。
MD5算法由美国密码学家罗纳德·李维斯特(Ronald Rivest)于1991年提出,目前仍广泛应用于数据完整性校验、密码存储等领域。
1.不可逆性:MD5算法是单向的,无法通过哈希值逆向推导出原始数据。
这意味着即使知道哈希值,也无法还原出原始数据。
2.高度离散性:MD5算法对输入数据的任意细微更改都会产生完全不同的哈希值。
这意味着即使数据只有一点点改变,其哈希值也会完全不同。
3.快速性:MD5算法的计算速度相对较快,能够在短时间内对大量数据进行哈希计算。
1.填充数据:对输入数据进行填充,使其长度恰好为512的倍数。
填充时,在数据末尾添加一个1,后面补0至满足长度要求。
2.填充长度:将填充后的数据长度(以比特位为单位)表示为64位二进制数,并添加到填充数据的末尾。
3.初始化状态:定义四个32位的寄存器A、B、C、D,并初始化为特定的常量值。
4.分组处理:将填充后的数据分成若干个512位的分组,每次处理一个分组。
5.循环操作:对每个分组进行四轮循环操作,每轮操作包括四个步骤。
a.F函数:根据当前轮数选择不同的非线性函数,并将寄存器A、B、C、D的值传入。
b.G函数:根据当前轮数选择不同的线性函数,并将寄存器A、B、C、D的值传入。
c.H函数:根据当前轮数选择不同的线性函数,并将寄存器A、B、C、D的值传入。
d.I函数:根据当前轮数选择不同的线性函数,并将寄存器A、B、C、D的值传入。
6.更新寄存器:根据循环操作的结果更新寄存器A、B、C、D的值。
7.输出结果:将最终的寄存器值按顺序连接起来,得到128位的哈希值。
1.碰撞攻击:由于MD5算法的哈希值只有128位,因此存在不同的输入数据生成相同的哈希值的可能性,这被称为碰撞。
攻击者可以通过特定的方法找到两个不同的输入数据,生成相同的哈希值,从而绕过数据完整性校验。
MD5加密算法原理及实现

MD5加密算法原理及实现MD5消息摘要算法,属Hash算法⼀类。
MD5算法对输⼊任意长度的消息进⾏运⾏,产⽣⼀个128位的消息摘要。
以下所描述的消息长度、填充数据都以位(Bit)为单位,字节序为⼩端字节。
算法原理1、数据填充对消息进⾏数据填充,使消息的长度对512取模得448,设消息长度为X,即满⾜X mod 512=448。
根据此公式得出需要填充的数据长度。
填充⽅法:在消息后⾯进⾏填充,填充第⼀位为1,其余为0。
2、添加消息长度在第⼀步结果之后再填充上原消息的长度,可⽤来进⾏的存储长度为64位。
如果消息长度⼤于264,则只使⽤其低64位的值,即(消息长度对 264取模)。
在此步骤进⾏完毕后,最终消息长度就是512的整数倍。
3、数据处理准备需要⽤到的数据:4个常数:A = 0x67452301, B = 0x0EFCDAB89, C = 0x98BADCFE, D = 0x10325476;4个函数: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));把消息分以512位为⼀分组进⾏处理,每⼀个分组进⾏4轮变换,以上⾯所说4个常数为起始变量进⾏计算,重新输出4个变量,以这4个变量再进⾏下⼀分组的运算,如果已经是最后⼀个分组,则这4个变量为最后的结果,即MD5值。
具体计算的实现较为复杂,建议查阅相关书籍,下⾯给出在C++上的实现代码。
代码实现#MD5.h1 #ifndef MD5H2#define MD5H3 #include <math.h>4 #include <Windows.h>56void ROL(unsigned int &s, unsigned short cx); //32位数循环左移实现函数7void ltob(unsigned int &i); //B\L互转,接受UINT类型8 unsigned int* MD5(const char* mStr); //接⼝函数,并执⾏数据填充,计算MD5时调⽤此函数910#endif#MD5.cpp1 #include "MD5.h"23/*4组计算函数*/4 inline unsigned int F(unsigned int X, unsigned int Y, unsigned int Z)5 {6return (X & Y) | ((~X) & Z);7 }8 inline unsigned int G(unsigned int X, unsigned int Y, unsigned int Z)9 {10return (X & Z) | (Y & (~Z));11 }12 inline unsigned int H(unsigned int X, unsigned int Y, unsigned int Z)13 {14return X ^ Y ^ Z;15 }16 inline unsigned int I(unsigned int X, unsigned int Y, unsigned int Z)17 {18return Y ^ (X | (~Z));19 }20/*4组计算函数结束*/2122/*32位数循环左移实现函数*/23void ROL(unsigned int &s, unsigned short cx)24 {25if (cx > 32)cx %= 32;26 s = (s << cx) | (s >> (32 - cx));27return;28 }2930/*B\L互转,接收UINT类型*/31void ltob(unsigned int &i)32 {33 unsigned int tmp = i;//保存副本34byte *psour = (byte*)&tmp, *pdes = (byte*)&i;35 pdes += 3;//调整指针,准备左右调转36for (short i = 3; i >= 0; --i)37 {38 CopyMemory(pdes - i, psour + i, 1);39 }40return;41 }4243/*44MD5循环计算函数,label=第⼏轮循环(1<=label<=4),lGroup数组=4个种⼦副本,M=数据(16组32位数指针)45种⼦数组排列⽅式: --A--D--C--B--,即 lGroup[0]=A; lGroup[1]=D; lGroup[2]=C; lGroup[3]=B;46*/47void AccLoop(unsigned short label, unsigned int *lGroup, void *M)48 {49 unsigned int *i1, *i2, *i3, *i4, TAcc, tmpi = 0; //定义:4个指针; T表累加器;局部变量50 typedef unsigned int(*clac)(unsigned int X, unsigned int Y, unsigned int Z); //定义函数类型51const unsigned int rolarray[4][4] = {52 { 7, 12, 17, 22 },53 { 5, 9, 14, 20 },54 { 4, 11, 16, 23 },55 { 6, 10, 15, 21 }56 };//循环左移-位数表57const unsigned short mN[4][16] = {58 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },59 { 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12 },60 { 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2 },61 { 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 }62 };//数据坐标表63const unsigned int *pM = static_cast<unsigned int*>(M);//转换类型为32位的Uint64 TAcc = ((label - 1) * 16) + 1; //根据第⼏轮循环初始化T表累加器65 clac clacArr[4] = { F, G, H, I }; //定义并初始化计算函数指针数组6667/*⼀轮循环开始(16组->16次)*/68for (short i = 0; i < 16; ++i)69 {70/*进⾏指针⾃变换*/71 i1 = lGroup + ((0 + i) % 4);72 i2 = lGroup + ((3 + i) % 4);73 i3 = lGroup + ((2 + i) % 4);74 i4 = lGroup + ((1 + i) % 4);7576/*第⼀步计算开始: A+F(B,C,D)+M[i]+T[i+1] 注:第⼀步中直接计算T表*/77 tmpi = (*i1 + clacArr[label - 1](*i2, *i3, *i4) + pM[(mN[label - 1][i])] + (unsigned int)(0x100000000UL * abs(sin((double)(TAcc + i)))));78 ROL(tmpi, rolarray[label - 1][i % 4]);//第⼆步:循环左移79 *i1 = *i2 + tmpi;//第三步:相加并赋值到种⼦80 }81return;82 }8384/*接⼝函数,并执⾏数据填充*/85 unsigned int* MD5(const char* mStr)86 {87 unsigned int mLen = strlen(mStr); //计算字符串长度88if (mLen < 0) return0;89 unsigned int FillSize = 448 - ((mLen * 8) % 512); //计算需填充的bit数90 unsigned int FSbyte = FillSize / 8; //以字节表⽰的填充数91 unsigned int BuffLen = mLen + 8 + FSbyte; //缓冲区长度或者说填充后的长度92 unsigned char *md5Buff = new unsigned char[BuffLen]; //分配缓冲区93 CopyMemory(md5Buff, mStr, mLen); //复制字符串到缓冲区9495/*数据填充开始*/96 md5Buff[mLen] = 0x80; //第⼀个bit填充197 ZeroMemory(&md5Buff[mLen + 1], FSbyte - 1); //其它bit填充0,另⼀可⽤函数为FillMemory98 unsigned long long lenBit = mLen * 8ULL; //计算字符串长度,准备填充99 CopyMemory(&md5Buff[mLen + FSbyte], &lenBit, 8); //填充长度100/*数据填充结束*/101102/*运算开始*/103 unsigned int LoopNumber = BuffLen / 64; //以16个字为⼀分组,计算分组数量104 unsigned int A = 0x67452301, B = 0x0EFCDAB89, C = 0x98BADCFE, D = 0x10325476;//初始4个种⼦,⼩端类型105 unsigned int *lGroup = new unsigned int[4]{ A, D, C, B}; //种⼦副本数组,并作为返回值返回106for (unsigned int Bcount = 0; Bcount < LoopNumber; ++Bcount) //分组⼤循环开始107 {108/*进⼊4次计算的⼩循环*/109for (unsigned short Lcount = 0; Lcount < 4;)110 {111 AccLoop(++Lcount, lGroup, &md5Buff[Bcount * 64]);112 }113/*数据相加作为下⼀轮的种⼦或者最终输出*/114 A = (lGroup[0] += A);115 B = (lGroup[3] += B);116 C = (lGroup[2] += C);117 D = (lGroup[1] += D);118 }119/*转换内存中的布局后才能正常显⽰*/120 ltob(lGroup[0]);121 ltob(lGroup[1]);122 ltob(lGroup[2]);123 ltob(lGroup[3]);124 delete[] md5Buff; //清除内存并返回125return lGroup;126 }再给出调⽤实例(以win32控制台应⽤程序为例):#main.cpp1 #include <iostream>2 #include <string.h>3 #include <stdlib.h>4 #include "MD5.h"56int main(int argc, char **argv)7 {8char tmpstr[256], buf[4][10];9 std::cout << "请输⼊要加密的字符串:";10 std::cin >> tmpstr;11 unsigned int* tmpGroup = MD5(tmpstr);12 sprintf_s(buf[0], "%8X", tmpGroup[0]);13 sprintf_s(buf[1], "%8X", tmpGroup[3]);14 sprintf_s(buf[2], "%8X", tmpGroup[2]);15 sprintf_s(buf[3], "%8X", tmpGroup[1]);16 std::cout <<"MD5:"<< buf[0] << buf[1] << buf[2] << buf[3] << std::endl; 1718 delete[] tmpGroup;19return0; //在此下断点才能看到输出的值20 }注:以上代码在VS2013上编译通过。
基于51单片机MD5算法实现

基于51单片机MD5算法实现MD5算法是一种广泛使用的密码散列函数,其输出为128位的散列值。
这种算法在计算简单、辅助和速度方面的优点使其被广泛应用于许多领域,如密码学、数据完整性验证和数字签名等。
在本文中,我们将基于51单片机实现MD5算法。
首先,我们需要了解MD5算法的基本原理。
MD5算法主要包括四个步骤:填充、初始向量、处理和输出。
在填充步骤中,我们将输入消息的长度进行填充,以保证其长度是64的倍数。
在初始向量步骤中,我们初始化了4个32位的寄存器:A、B、C和D。
在处理步骤中,我们通过对输入消息进行分组,并进行一系列的位运算来生成散列值。
最后,在输出步骤中,我们将A、B、C、D寄存器的内容连接起来,形成128位的散列值。
在51单片机中,我们可以使用C语言来实现MD5算法。
首先,我们需要定义一些辅助函数来处理字节和位的运算。
以下是一些关键函数的实现示例:-`F`函数:根据输入的X、Y和Z值进行位运算,并返回结果。
-`G`函数:根据输入的X、Y和Z值进行位运算,并返回结果。
-`H`函数:根据输入的X、Y和Z值进行位运算,并返回结果。
-`I`函数:根据输入的X、Y和Z值进行位运算,并返回结果。
- `shift_left`函数:将输入值向左循环移动给定的位数。
-`FF`函数等:定义了一系列的辅助函数来进行特定的位运算。
接下来,我们需要实现MD5算法的核心函数。
以下是MD5算法的一般实现示例:1.初始化MD缓冲区,包括A、B、C、D寄存器的初始值。
2.对输入消息进行填充,并将其分成512位的块。
3.对每个块执行一系列的位运算,包括旋转、移位、与、或等操作。
4.将寄存器的内容连接起来,形成128位的散列值。
在51单片机中实现MD5算法需要注意的是内存和处理速度的限制。
因为51单片机的存储容量较低,因此对于大型输入消息,可能需要进行分块处理和多次运算。
此外,由于单片机处理速度较低,可能需要优化代码以提高执行效率。
MD5实现加密解密

MD5实现加密解密MD5(Message Digest Algorithm 5),中文名为消息摘要算法5,是一种常用的哈希函数。
它接收输入消息并返回一个固定长度的哈希值,通常是128位(16字节)。
MD5算法的实现过程比较简单,可以分为四个步骤:填充,添加长度,初始化参数,以及循环处理。
下面将具体介绍每个步骤的实现过程。
首先,填充。
MD5以512位(64字节)为块进行处理,如果输入消息的长度不足512位,就需要进行填充。
填充的规则是在消息的末尾加上一个1,然后再加上若干个0,直到消息的长度(包含填充位)等于448位(即消息长度模512等于448)。
填充位的长度加上消息长度再加上64位长度的原始消息长度(以二进制形式表示)即为消息的总长度。
添加长度。
在填充之后,还需要再加上64位的原始消息长度。
这个长度被分成两个32位的部分,分别加在填充后的消息的最后64位中,低位字节在前,高位字节在后。
初始化参数。
MD5算法使用一些固定的参数进行计算,这些参数被称为初始链接值。
初始链接值是一个包含四个32位整数的数组,并被赋予一些特定的常数。
循环处理。
MD5算法通过四轮迭代和一系列的位运算对每个块进行处理。
每轮迭代使用一个4x4的矩阵实现算法。
在每一轮迭代中,通过选择函数、逻辑函数和位移操作将输入块与初始链接值相关联,然后输出一个新的链接值,并将其与下一个输入块相关联。
经过四轮迭代后,最后一个块的计算结果就是MD5哈希值。
在MD5实现的过程中,一般会通过不断地调用填充、添加长度、初始化参数和循环处理这四个步骤,对连续的消息块进行处理。
最终的处理结果即为输入消息的MD5哈希值。
MD5算法在信息安全领域有着广泛的应用。
它可以用于数据完整性校验、密码的验证、文件的一致性校验等方面。
但是需要注意的是,由于MD5算法存在一定的弱点,如碰撞攻击,因此在一些对安全性要求较高的场景中,应该使用更安全的哈希函数,如SHA-256在进行MD5加密解密的实现时,可以使用现有的MD5算法库,将需要加密或解密的数据传入函数进行处理。
MD5算法详解

MD5算法详解前⾯⼀篇,带⼤家对加密算法进⾏了鸟瞰,本篇主要谈md5算法的实现。
MD5:Message-Digest Algorithm 5(信息摘要5),确保信息的完整性。
其算法是1992年公开的,那时我才⼏岁,鉴于⼤家对md5都很熟悉,且程序中经常应⽤,我就不再介绍了。
我简单的介绍下设计者。
其⼈是罗纳德·李维斯特,美国密码学家,后来发明了⾮对称秘钥RSA 算法,因这个算法的在信息安全中的突破与重要性⽽获得了2002年的图灵奖。
好了,接下来⼀起看算法步骤以及源代码:1、填充在MD5算法中,⾸先需要对信息进⾏填充,使其位长对512求余的结果等于448,并且填充必须进⾏,使其位长对512求余的结果等于448。
因此,信息的位长(Bits Length)将被扩展⾄N*512+448,N为⼀个⾮负整数,N可以是零。
理解:位长,就是位数。
⽐如⼀个“wbq”,字符串是三个字节存储,⼀个字节8bit,所以位长就是24。
⽤数学语⾔可能更简洁:设M为位长,当且仅当 M%512==448时,才可以处理。
换另⼀种表⽰⽅式,M=N*512+448 ,N>=0填充的⽅法如下:1) 在信息的后⾯填充⼀个1和⽆数个0,直到满⾜上⾯的条件时才停⽌⽤0对信息的填充。
2) 在这个结果后⾯附加⼀个以64位⼆进制表⽰的填充前信息长度(单位为Bit),如果⼆进制表⽰的填充前信息长度超过64位,则取低64位。
经过这两步的处理,M=N*512+448+64=(N+1)*512,即长度恰好是512的整数倍。
这样做的原因是为满⾜后⾯处理中对信息长度的要求。
经过两步处理后,信息变成了这样,如下图所⽰:64位,8个字节,⽤来表⽰原始信息的位长。
1private static UInt32[] MD5_Append(byte[] input)2 {3int zeros = 0;4int ones = 1;5int size = 0;6int n = input.Length;7int m = n % 64;8if (m < 56)9 {10 zeros = 55 - m;11 size = n - m + 64;12 }13else if (m == 56)14 {15 zeros = 0;16 ones = 0;17 size = n + 8;18 }19else20 {21 zeros = 63 - m + 56;22 size = n + 64 - m + 64;23 }2425 ArrayList bs = new ArrayList(input);26if (ones == 1)27 {28 bs.Add((byte)0x80); // 0x80 = $1000000029 }30for (int i = 0; i < zeros; i++)31 {32 bs.Add((byte)0);33 }3435 UInt64 N = (UInt64)n * 8;36byte h1 = (byte)(N & 0xFF);37byte h2 = (byte)((N >> 8) & 0xFF);3839byte h3 = (byte)((N >> 16) & 0xFF);40byte h4 = (byte)((N >> 24) & 0xFF);41byte h5 = (byte)((N >> 32) & 0xFF);42byte h6 = (byte)((N >> 40) & 0xFF);43byte h7 = (byte)((N >> 48) & 0xFF);44byte h8 = (byte)(N >> 56);45 bs.Add(h1);46 bs.Add(h2);47 bs.Add(h3);48 bs.Add(h4);49 bs.Add(h5);50 bs.Add(h6);51 bs.Add(h7);52 bs.Add(h8);53byte[] ts = (byte[])bs.ToArray(typeof(byte));5455/* Decodes input (byte[]) into output (UInt32[]). Assumes len is56 * a multiple of 4.57*/58 UInt32[] output = new UInt32[size / 4];59for (Int64 i = 0, j = 0; i < size; j++, i += 4)60 {61 output[j] = (UInt32)(ts[i] | ts[i + 1] << 8 | ts[i + 2] << 16 | ts[i + 3] << 24);62 }63return output;64 }说明,补多少0,如何补?第7⾏,求余。
MD5算法简介及两种实现方法(使用WindowsAPI函数)

MD5简介MD5的全称是Message-Digest Algorithm 5(信息-摘要算法),在90年代初由MIT Laboratory for Computer Science和RSA Data Security Inc的Ronald L. Rivest开发出来,经MD2、MD3和MD4发展而来。
它的作用是让大容量信息在用数字签名软件签署私人密匙前被"压缩"成一种保密的格式。
MD5算法的描述和C语言源代码在Internet RFCs 1321中有详细的描述(/rfc/rfc1321.txt),这是一份最权威的文档,由Ronald L. Rivest 在1992年8月向IEFT提交。
我们先来看看RFC文档中对MD5的描述:This document describes the MD5 message-digest algorithm(摘要). The algorithm takes as input a message of arbitrary length(任意长度)and produces as output a 128-bit "fingerprint" or "message digest" of the input. It is conjectured that it is computationally infeasible(不可实行的)to produce two messages having the same message digest, or to produce any message having a given prespecified target message digest. The MD5 algorithm is intended for digital signature applications, where a large file must be "compressed" in a secure manner before being encrypted with a private (secret) key under a public-key cryptosystem such as RSA.从上面的RFC描述中,可以总结出MD5摘要算法两个最重要的特性:1、不可逆,无法由结果退出输入2、two messages不可能拥有相同的摘要信息,保证一对一正是这两个特性保证了MD5在数字签名中的应用,将一个需要签名的大文件转换为等价的128bit的摘要信息,再用私钥对128bit的摘要信息进行加密。
基于51单片机MD5算法实现

基于51单片机MD5算法实现MD5(Message-Digest Algorithm 5)是一种广泛使用的加密算法,用于确保数据完整性和安全性。
在本文中,我们将介绍如何基于51单片机实现MD5算法。
MD5算法的实现需要以下几个步骤:初始化、填充消息、分组处理和生成摘要。
首先,我们需要初始化MD5算法的参数。
MD5算法使用4个32位寄存器(A、B、C和D)来保存中间计算结果。
以及一个64位计数器来记录已处理的消息位数。
此外,还需要定义一个常量表,用于生成每个消息块的32位运算常数。
接下来,我们将把待处理的消息填充到512位的消息块中。
在填充消息之前,我们需要根据消息的长度对其进行填充。
填充规则如下:首先,在消息的末尾添加一个数值为1的位,然后添加若干个0,直到消息的长度满足对512取模等于448的条件。
最后,将消息的长度以64位二进制表示并添加到消息的末尾。
然后,我们需要将填充后的消息块分为16个32位的子块。
每个子块将依次进行一系列的处理。
处理过程可分为4轮,每轮都包含16个操作步骤。
每个步骤的结果将作为下一个步骤的输入。
在每轮处理的过程中,会对子块中的每个字做相应的处理运算,包括逻辑运算和位移运算。
其中,逻辑运算包括与运算、或运算和异或运算;位移运算包括循环左移和循环右移。
最后,将最终的四个32位寄存器的内容按照从低位到高位的顺序连接起来,即为MD5算法的输出结果。
为了在51单片机上实现MD5算法,我们需要先了解51单片机的特点和功能。
51单片机是一种常用的8位单片机,具有低功耗、高性能和易于编程的特点。
它可以实现大部分基本的运算和控制功能,并且具有丰富的通信接口和存储器。
我们可以利用51单片机的GPIO口和定时器功能来实现MD5算法的各种操作。
首先,我们将利用51单片机的GPIO口来实现MD5算法的初始化操作和消息填充操作。
通过设置GPIO口的输入输出状态来实现不同的操作。
然后,我们可以利用51单片机的定时器功能来实现MD5算法的分组处理操作。
C语言实现MD5算法

C语言实现MD5算法1.理解MD5算法原理:-MD5算法是一种常用的哈希函数,用于将任意长度的消息转换为固定长度的哈希值,通常为128位。
-MD5算法主要包括四个循环运算和四个非线性函数,通过迭代运算将输入的消息分块处理并输出最终的哈希值。
2.定义MD5算法所需的常量和函数:-定义一个64个元素的常数列表,用于在算法运算中使用。
-定义四个非线性的F,G,H,I函数,用于在循环运算中使用。
3.定义MD5算法所需的全局变量:-定义一个128位的缓冲区保存最终输出的哈希值。
-定义一个64位的计数指示器,记录输入消息的长度。
-定义四个32位的寄存器变量A、B、C、D,用于循环运算过程中保存中间结果。
4.实现MD5算法的主要函数:- 实现Padding函数,将输入消息按照MD5算法的规则进行填充,使其长度满足对512位的整数倍。
-实现FF,GG,HH,II四个函数,用于在每个循环运算中进行非线性转换。
-实现MD5算法的核心循环函数,将输入消息分块处理,并对每个分块进行四轮循环运算,更新寄存器变量的值。
-实现MD5算法的输出函数,将最终运算得到的寄存器变量的值按照一定顺序连接起来,得到最终的128位哈希值。
5.实现MD5算法的入口函数:- 在main函数中,读取输入消息,并调用MD5算法的相关函数,得到最终的哈希值。
-打印输出哈希值。
以下为C语言实现MD5算法的伪代码:```c//定义MD5算法所需的常量和函数const uint32_t s[64] = { ... }; // 常数表const uint32_t k[64] = { ... }; // F,G,H,I函数对应的逻辑常数uint32_t F(uint32_t x, uint32_t y, uint32_t z) { ... } // F 函数uint32_t G(uint32_t x, uint32_t y, uint32_t z) { ... } // G 函数uint32_t H(uint32_t x, uint32_t y, uint32_t z) { ... } // H 函数uint32_t I(uint32_t x, uint32_t y, uint32_t z) { ... } // I 函数//定义MD5算法所需的全局变量uint32_t buffer[4]; // 128位缓冲区uint64_t count = 0; // 输入消息的长度uint32_t A, B, C, D; // 寄存器变量// 实现Padding函数void padding(char* message) { ... }//实现FF,GG,HH,II四个函数void FF(...) { ... }void GG(...) { ... }void HH(...) { ... }void II(...) { ... }//实现MD5算法的核心循环函数void MD5Block(uint32_t* block) { ... }//实现MD5算法的输出函数void MD5Output(uint32_t* digest) { ... }//实现MD5算法的入口函数int maichar message[MAX_LENGTH];uint32_t digest[4];//读取输入消息gets(message);//填充输入消息padding(message);//分块处理for (uint32_t i = 0; i < count; i += 64)MD5Block(&message[i]);}//输出最终结果MD5Output(digest);//打印哈希值printf("%08x%08x%08x%08x", digest[0], digest[1], digest[2], digest[3]);return 0;```以上是一个简单的伪代码,实现了C语言下的MD5算法。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#defineS2314
#defineS2420
#defineS314
#defineS3211
#defineS3316
#defineS3423
#defineS416#defin NhomakorabeaS4210
#defineS4315
#defineS4421
staticvoidMD5Transform(UINT4[4],unsignedchar[64]);
/*FF,GG,HH,andIItransformationsforrounds1,2,3,and4.
Rotationisseparatefromadditiontopreventrecomputation.
*/
#defineFF(a,b,c,d,x,s,ac){/
(a)+=F((b),(c),(d))+(x)+(UINT4)(ac);/
/*md5.cpp*/
#include"stdafx.h"
/*ConstantsforMD5Transformroutine.*/
/*md5转换用到的常量,算法本身规定的*/
#defineS117
#defineS1212
#defineS1317
#defineS1422
#defineS215
#defineS229
md5
md5的介绍的文章网上很多,关于md5的来历,用途什么的这里就不再介绍了。这里主要介绍代码。代码明白了就什么都明白了。
////////////////////////////////////////////////////////////////////
/*md5.h*/
#ifndef_MD5_H_
(a)+=H((b),(c),(d))+(x)+(UINT4)(ac);/
(a)=ROTATE_LEFT((a),(s));/
(a)+=(b);/
}
#defineII(a,b,c,d,x,s,ac){/
(a)+=I((b),(c),(d))+(x)+(UINT4)(ac);/
(a)=ROTATE_LEFT((a),(s));/
};
/*
接下来的这几个宏定义是md5算法规定的,就是对信息进行md5加密都要做的运算。
据说有经验的高手跟踪程序时根据这几个特殊的操作就可以断定是不是用的md5
*/
/*F,G,HandIarebasicMD5functions.
*/
#defineF(x,y,z)(((x)&(y))|((~x)&(z)))
(a)=ROTATE_LEFT((a),(s));/
(a)+=(b);/
}
#defineGG(a,b,c,d,x,s,ac){/
(a)+=G((b),(c),(d))+(x)+(UINT4)(ac);/
(a)=ROTATE_LEFT((a),(s));/
(a)+=(b);/
}
#defineHH(a,b,c,d,x,s,ac){/
#defineG(x,y,z)(((x)&(z))|((y)&(~z)))
#defineH(x,y,z)((x)^(y)^(z))
#defineI(x,y,z)((y)^((x)|(~z)))
/*ROTATE_LEFTrotatesxleftnbits.
*/
#defineROTATE_LEFT(x,n)(((x)<<(n))|((x)>>(32-(n))))
/*存储原始信息的bits数长度,不包括填充的bits,最长为2^64bits,因为2^64是一个64位数的最大值*/
UINT4count[2];
/*inputbuffer*/
/*存放输入的信息的缓冲区,512bits*/
unsignedcharbuffer[64];
}MD5_CTX;
voidMD5Init(MD5_CTX*);
需要填充的bits的最大值为512=64*8。
*/
staticunsignedcharPADDING[64]={
0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
(a)+=(b);/
}
/*MD5initialization.BeginsanMD5operation,writinganewcontext.*/
/*初始化md5的结构*/
voidMD5Init(MD5_CTX*context)
{
/*将当前的有效信息的长度设成0,这个很简单,还没有有效信息,长度当然是0了*/
voidMD5Update(MD5_CTX*,unsignedchar*,unsignedint);
voidMD5Final(unsignedchar[16],MD5_CTX*);
#endif/*_MD5_H_*/
///////////////////////////////////////////////////////////////////////////
#define_MD5_H_
#defineR_memset(x,y,z)memset(x,y,z)
#defineR_memcpy(x,y,z)memcpy(x,y,z)
#defineR_memcmp(x,y,z)memcmp(x,y,z)
typedefunsignedlongUINT4;
typedefunsignedchar*POINTER;
staticvoidEncode(unsignedchar*,UINT4*,unsignedint);
staticvoidDecode(UINT4*,unsignedchar*,unsignedint);
/*
用于bits填充的缓冲区,为什么要64个字节呢?因为当欲加密的信息的bits数被512除其余数为448时,
/*MD5context.*/
typedefstruct{
/*state(ABCD)*/
/*四个32bits数,用于存放最终计算得到的消息摘要。当消息长度〉512bits时,也用于存放每个512bits的中间结果*/
UINT4state[4];
/*numberofbits,modulo2^64(lsbfirst)*/