Hash算法MD5 实验报告
南昌航空大学信息安全试验4-MD5加密的Java实现

南昌航空大学实验报告2014年3月27日课程名称:信息安全概论实验名称:MD5加密的Java实现班级:姓名:学号:指导老师评定:签名:一、实验目的通过实验了解MD5加密的原理,掌握Java语言MD5加密的实现。
二、实验原理1.哈希(Hash)函数的定义实现数字签名或计算消息的鉴别码。
以任意长度的消息作为输入,输出一个固定长度的二进制值,称为哈希值或消息摘要。
2.MD(Message Digest)消息摘要MD5对任意输入的消息计算一个128位的固定长度的值3.MD5的应用(1)用于校验下载的文件可用MD5校验工具软件计算,相当于文件的指纹,32位字母数字常用于软件下载网站网站:先计算文件的MD5值,然后和文件一起发布到网站上。
用户:下载文件后,计算文件的MD5值,和网站发布的MD5值核对。
(2)将用户密码加密后保存注册时:将用户的注册密码(P1)用MD5算法加密后(P2)保存到服务器数据库中;登录时:将用户的登录密码(P3)用MD5算法加密后(P4),与服务器数据库中的密文密码(P2)比较。
三、实验环境开发工具:JDK、Eclipse参考资料:JDK API文档java.security包MessageDigest类四、实验内容和任务使用Java语言编程,模拟注册和登录过程。
五、实验内容1.注册登录package t;import java.math.BigInteger;import java.security.MessageDigest;import java.util.Scanner;public class MD5{public static void main(String[]args){String password="";String account="";System.out.print("注册\n用户名:");Scanner inaccount=new Scanner(System.in);account=inaccount.nextLine();System.out.print("密码:");Scanner inpassword=new Scanner(System.in);password=inpassword.nextLine();password=makeMD5(password);String password2="";String account2="";System.out.print("\n\n登录\n用户名:");Scanner inaccount2=new Scanner(System.in);account2=inaccount2.nextLine();System.out.print("密码:");Scanner inpassword2=new Scanner(System.in);password2=inpassword2.nextLine();password2=makeMD5(password2);if(account.equals(account2)&&password.equals(password2)){System.out.println("登录成功!!!");System.out.println("密文:"+makeMD5(password));}else{System.out.println("登录失败!!!");}//System.out.println("密文:"+makeMD5(password));}public static String makeMD5(String password){MessageDigest md;try{//生成一个MD5加密计算摘要md=MessageDigest.getInstance("MD5");//计算md5函数md.update(password.getBytes());//digest()最后确定返回md5hash值,返回值为8为字符串。
md5实验报告

md5实验报告
# MD5实验报告
## 简介
MD5(Message-Digest Algorithm 5)是一种广泛使用的哈希函数,用于对任意
长度的信息产生一个128位的哈希值。
它由美国密码学家罗纳德·李维斯特(Ronald Rivest)设计,于1992年公开。
MD5算法的设计目标是在计算速度
上尽量保持优秀的性能,同时也要尽量保证安全性。
## 实验目的
本实验旨在通过对MD5算法的实验,了解其在信息安全领域的应用和特点。
## 实验过程
1. 选择一段文本作为输入数据。
2. 使用MD5算法对输入数据进行哈希运算,得到对应的128位哈希值。
3. 对比不同输入数据产生的哈希值,观察MD5算法的碰撞概率。
## 实验结果
经过实验,我们发现MD5算法在对不同输入数据进行哈希运算时,能够产生唯一的128位哈希值。
虽然MD5算法在碰撞概率上存在一定的问题,但在实际
应用中,仍然具有一定的安全性和可靠性。
## 结论
MD5算法作为一种广泛使用的哈希函数,在信息安全领域有着重要的应用价值。
然而,随着计算能力的提升和攻击技术的发展,MD5算法的安全性逐渐受到挑战。
因此,在实际应用中,我们需要谨慎选择合适的哈希算法,并结合其他安
全措施,以确保信息的安全性和完整性。
MD5实验报告(word文档良心出品)

一、MD5算法描述MD5算法是计算机安全领域广泛使用的一种散列算法之一,用以提供消息的完整性保护。
本次实验中,对于输入的任意长度的一段数据,输出唯一固定的128位MD5散列值。
MD噂法分为以下步骤:1 、初始化(填充)首先对于任意长度的消息,将其按照512 位进行分组,为保证每个分组都是512 位,需要对消息进行填充。
填充方法是先在消息末尾填一个1,再在后面填若干个0,使其长度I恰好满足I=448(mod512),然后在其后附加上64 位的(填充前)消息长度, 确保不同的消息在填充后不相同消息在填充后不相同。
其次将每个分组512 位的数据划分为16个32 位的子分组,在实现过程中,将其表示为16 个32 位整数进行运算。
初始化四个32 位链接变量为:A=0x67452301B=0xefcdab89C=0x98badcfeD=0x103254762、单步操作与主循环MD5共分为4轮,每轮进行16步单步操作,MD5的单步操作如下其中,g k (k=0,123)是每次运算中用到的非线性函数(每轮一个),用C 语言定义如下^define gO(b> c,. d) ((b&c) (、b 赴d))ftdefine gl (b, c> d) ((b&d) )ffdef ine g2(b, c f d) (b e d) tfdef ine g3(b, c f d) (c (b d))数据块X[ d(i)]来自于初始化中分好的16个32位数据分组,根据循环 步数按以下置换函数选取(i 表示循环的第i 步)T i 是一些随机数序列,T i 的值如下(按顺序选取)Pdefine rO(i)#define rl (i)Sdefine r2(i)Sdefine r3 (i)(i%16) <(l+5*i)%16) ((5+3*i)%16) <(7*i)%16)unsigned int T .64.=:0xd76aa478;0xe8c7b756?Ox242070dL Oxclbdce-ee,0xf57c0faf,0x4787c62a T0xa8304613:0xfd469501? 0x698098d8,0x8b44f7af7OxffffSbbl. 0x895cd7te7 0x6b90U22f0xfd987193,0x3679438^ 0x49b40821, Ch<f61u2562, OxcO4Ob34O, 0x265e5a51?Oxe^GcTaa, 0xd62fl05d. 0x02141453, 0xd8ale68L?0xe7d3fbc8?Ox21.elcde6, 0xc337O7d6T0xf4d50d87r0x455al4ed f0^a9e3e905,OxfcefaofS, 0x676f02d9. 0x8d2a4c8a, 0xfffa3942,0x8771f681, 0x6旳d6122, 0xfM538(k, 0xa4beea44:0x4bdecfa9?0xf6bb4b60?Oxbebfbc7O? 0x289b7ec6:0xeaaI27£a T0s64ef3085:0x04851 dO5? 0xd9d4d039, 0xe6db99e5?DxlfaSycfS, 0xc4ac566570xf4292244?0x432aff97I0xab9423a7J0xfc93a039, 0x655b59c3,0x8f0ccc92, Oxffeff47d. 0x85845ddl? 0x6faS7e4f, 0xfe2ce6e0,0xa3014314?Ox4eO811al, Oxf7537eS2. 0xbd3af2o570x2ad7d2bb.0xeb86d391?};vv<S i表示循环左移S i位,S i的数值如下(按顺序选取)unsigned int S[64]={7,12417, 22, 7,12f17f 22, 7, 12,17, 22t 1, 12,17t 22,5, 9,14, 20, 5, 9, 14, 20, 5, 9, 14,20, 5, 9,14, 20,4, 11,16, 23, 4,11,16, 23, 4,11,16, 23* 4,11, 16, 23,6,10,15, 21, 6,10,15, 21, 6F10,15, 21, 6, 10, 15, 21};因此,MD5主要的一个单步操作可以表示为a =b ((a f(b,c,d) T[i] X[J(i)])尺S[i])每轮16步结束后的4个32位数作为下一轮的输入继续循环束后的输入再加上初始值即得到最终结果128位的散列值' 循环如下图四轮结64步主A| B| C| Bjn 彳第1轮16步便用卧P Q; 电 B ] cl 叫+1第2轮"步便用驻Pl |A| Bl C| D| "■►f 第3轮16步便用知pt1 ~Al Bl Cl Dl ~程序验证为了验证程序的正确性,我们通过查找 Wikipedia 上使用的3个 测试向量来进行测试,测试向量如下:ND5(*The quick bxown fox jumps over the lazy dog")=9e 107d9d372bb6326b d8Id3542a419d6KD5 (*The quick brown fos jumps over the lazy dog- ■*)= edd909c290dOfb IcaOGSff addf 2 2cbdOMD5(^)=d41J8cd98f0Ob204e980O99SecfS427e运行程序,得到的结果如下:X * - ■ <■>第4轮"步使用g 尹P3v ! I ! I 1 + 模屮加C ^D 工cyniF可以看到,实验结果与测试向量相同,验证了程序的正确性。
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加密,并将加密结果输出。
《信息安全》实验报告3MD5的计算和破解

《信息安全》实验报告3MD5的计算和破解1.引言信息安全是一个重要的领域,加密算法是其中的核心技术之一、MD5(Message Digest Algorithm 5)是一种常用的哈希算法,广泛应用于文件校验、数据完整性验证等等领域。
本实验旨在通过计算和破解MD5,深入了解MD5的工作原理和安全性。
2.实验目的(1)了解MD5算法的基本原理;(2)掌握MD5算法的计算过程;(3)通过破解MD5,了解其安全性问题。
3.实验过程3.1MD5算法的基本原理MD5算法通过对输入的字符串进行分组,然后对每个分组进行一系列的位运算和逻辑运算,最终生成一个128位(16字节)的哈希值。
MD5算法的基本原理如下:(1)填充:在输入字符串的末尾填充一些字节,使得输入字符串的长度能被64整除。
(2)初始化:将16进制的常数赋给4个32位寄存器A、B、C、D。
(3)分组:将填充后的输入字符串分为若干个512位的分组。
(4)处理:对每个分组进行一系列的位运算和逻辑运算。
(5)生成哈希值:将处理后的结果按一定顺序连接起来,得到一个128位的哈希值。
3.2MD5的计算过程通过Python编程语言实现MD5算法的计算过程如下:(1)初始化四个32位寄存器A、B、C、D,并赋初值。
(2)将待计算的字符串分组,每个分组512位。
(3)对每个分组进行一系列的位运算和逻辑运算,生成一个128位的哈希值。
(4)将生成的哈希值转换为16进制字符串。
3.3MD5的破解MD5算法虽然被广泛应用,但是也存在一定的安全性问题。
MD5哈希值是固定长度的,而输入字符串的长度可以是任意长度的,这就导致了哈希碰撞(hash collision)的概率增加。
哈希碰撞是指不同的输入字符串可以生成相同的哈希值,从而破解MD5密码。
破解MD5密码一般采用暴力破解和字典攻击两种方式。
4.实验结果通过编程计算MD5并破解一个MD5密码,结果如下:5.实验总结通过本次实验,我们了解了MD5算法的基本原理和计算过程。
MD5报告

密码学课程设计报告学院专业班级学号姓名课题指导教师报告成绩日期:年月日一.实验目的通过运算器工具实现MD5、SHA-1/256、HMAC等算法的加解密对两个报文的MD5值进行异或比对,进行SHA-1的分步计算对MD5、SHA-1/256等算法进行扩展实验和算法跟踪二.课程设计原理散列函数是一种单向密码,即是一个从明文到密文的不可逆映射,只有加密过程,不可解密;同时散列函数可以将任意长度的输入经过变换以后得到固定长度的输出。
散列函数在完整性认证和数字签名等领域有广泛应用。
散列函数应满足以下要求:(1)算法公开,不需要密钥。
(2)具有数据压缩功能,可将任意长度的输入转换为固定长度的输出。
(3)已知m,容易计算出H(m)。
(4)给定消息散列值H(m),要计算出m在计算上是不可行的。
(5)对任意不同的输入m和n,它们的散列值是不能相同的。
三.设计题目分析3.1 题目背景一、MD5算法MD5(Message-Digest Algorithm 5)即信息-摘要算法,是MD4算法的改进;算法的输入为任意长度的消息,分为512比特长的分组,输出为128比特的消息摘要。
处理过程如下:(1)对消息进行填充,使其比特长度为n512+448(n为正整数),填充方式是固定的:第一位为1,其后各位为0。
(2)附加消息长度,使用上一步骤留出的64比特以小端(最低有效字节/位存储于低地址字节/位)方式来表示消息被填充前的长度,若消息长度大于264,则以264为模数取模。
(3)对消息摘要缓冲区初始化,算法使用128比特长的缓冲区来存储中间结果和最终散列值,将缓冲区表示成4个32比特长的寄存器A、B、C、D,每个寄存器以小端方式存储数据,初始值为(十六进制,低位字节在前)A=01234567,B=89ABCDEF,C=FEDCBA98,D=76543210。
(4)以分组为单位对消息进行处理,每一个分组都经过压缩函数HMD5处理;HMD5有4轮处理过程,每轮有16步迭代,4轮处理过程的处理结构一样,所用逻辑函数不同,分别表示为F、G、H、I;每轮的输入为当前处理的消息分组和缓冲区当前的值,输出仍存放在缓冲区中。
文件内容哈希算法调研报告

文件内容哈希算法调研报告一、引言文件内容哈希算法是一种用于确定文件内容是否发生改变的算法。
通过比较两个文件的哈希值,我们可以快速地确定文件内容是否发生了变化。
这对于许多应用场景,如文件完整性检查、数据备份和版本控制等,具有重要意义。
本文将对几种常见的文件内容哈希算法进行调研,包括MD5、SHA-1、SHA-256、SHA-3以及Keccak-256等。
二、算法原理1. MD5(Message Digest Algorithm 5)是一种常用的哈希算法,它可以将任意长度的数据块压缩为固定长度的哈希值。
MD5通常用于数字签名和数据完整性检查。
2. SHA-1(Secure Hash Algorithm 1)是另一种广泛使用的哈希算法,它提供了一种强大的数据完整性校验方法。
SHA-1可以产生一个长度为160位的哈希值,虽然与MD5相比有一定的安全性能差距,但在许多应用中仍然表现良好。
3. SHA-256是一种新的SHA-2家族的成员,它产生的哈希值长度为256位,因此具有更高的安全性。
SHA-256广泛应用于密码学和数据存储领域。
4. SHA-3是SHA-2的后继者,被设计为比SHA-2更安全。
SHA-3产生的哈希值长度与SHA-2类似,但具有更高的安全性。
5. Keccak是一种迭代加密算法,也被称为SHA-3竞赛的赢家。
与之前的SHA系列相比,Keccak 产生的哈希值具有更高的安全性,且速度更快。
三、对比分析以上这些算法各有优缺点。
MD5在某些情况下可能受到攻击,因为其哈希值长度相对较短。
相比之下,SHA-1和SHA-256的安全性更高,但在处理大数据量时可能会比较慢。
SHA-3和Keccak则提供了更高的安全性,且速度更快。
四、应用场景这些哈希算法在许多应用场景中都有应用。
例如,在文件完整性检查中,我们可以使用这些算法来比较文件是否被篡改。
在密码存储中,我们可以使用这些算法来确保密码的安全性。
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算法是一种常用的哈希算法,具有较高计算效率和较好的抗碰撞性能。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
哈尔滨工程大学实验报告实验名称:Hash 算法MD5班级:学号:姓名:实验时间:2014年6月成绩:指导教师:实验室名称:哈尔滨工程大学实验室与资产管理处制一、实验名称Hash算法MD5二、实验目的通过实际编程了解MD5 算法的加密和解密过程,加深对Hash 算法的认识。
三、实验环境(实验所使用的器件、仪器设备名称及规格)运行Windows 或Linux 操作系统的PC 机,具有gcc(Linux)、VC(Windows)等C 语言编译环境。
四、任务及其要求(1)利用自己所编的MD5 程序对一个文件进行处理,计算它的Hash 值,提交程序代程和运算结果。
(2)微软的系统软件都有MD5 验证,尝试查找软件的MD5 值。
同时,在Windows 操作系统中,通过开始→运行→sigverif 命令,利用数字签名查找验证非Windows 的系统软件。
__五、实验设计(包括原理图、真值表、分析及简化过程、卡诺图、源代码等)在MD5 算法中,首先需要对信息进行填充,使其字节长度与448 模512 同余,即信息的字节长度扩展至n*512+448,n 为一个正整数。
填充的方法如下:在信息的后面填充第一位为1,其余各位均为0,直到满足上面的条件时才停止用0 对信息填充。
然后,再在这个结果后面附加一个以64 位二进制表示的填充前信息长度。
经过这两步的处理,现在的信息字节长度为n*512+448= (n+1)*512,即长度恰好是512 的整数倍,这样做的目的是为满足后面处理中后面处理中对信息长度的要求。
n 个分组中第q 个分组表示为Yq。
MD5 中有A、B、C、D,4 个32 位被称作链接变量的整数参数,它们的初始值分别为:A=01234567B=89abcdef,C=fedcba98,D=当设置好这个4 个链接变量后,就开始进入算法的4 轮循环运算。
循环的次数是信息中512 位信息分组数目。
首先将上面4 个链接变量复制到另外4 个变量中A到AA,B 到BB,C 到CC,D 到DD,以备后面进行处理。
然后进入主循环,主循环有4 轮,每轮循环都很相似。
第1 轮进行16 次操作,每次操作对A、B、C 和D 中的其中3 个作一次非线性函数运算,然后将所得结果加上第4 个变量,文本的一个子分组和一个常数。
再将所得结果向左循环移S 位,并加上A、B、C 或D 其中之一。
最后用该结果取代A、B、C 或D 其中之一。
以下是每次操作中用到的4 个非线性函数(每轮一个)。
F(B,C,D)=(B∧C)∨__________(B∧D)(此处需修改)G(B,C,D)=(B∧D)∨(C∧D)H(B,C,D)=B⊕C⊕DI (B,C,D)=C⊕(B∨D)(注:∧是与,∨是或,是非,⊕是异或。
)2下面为每一轮16 步操作中的4 次操作,16 步操作按照一定次序顺序进行。
FF(A,B,C,D,M[j],S,T[i])表示A=B+(A+(F(B,C,D)+M[j]+T[i])<<<S)GG(A,B,C,D,M[j],S,T[i])表示A=B+(A+(G(G,C,D)+M[j]+T[i] )<<<S)HH(A,B,C,D,M[j],S,T[i])表示A=B+(A+(H(B,C,D)+M[j]+T[i] )<<<S)II (A,B,C,D,M[j],S,T[i])表示A=B+(A+(I (B,C,D)+M[j]+T[i] )<<<S)(注:“+”定义为mod 232 的模运算。
)M[j]表示在第q 个512 位数据块中的第j 个32 位子分组,0≤j≤15。
常数T[i]可以有如下选择,在第i 步中,T[i]是96*abs(sin(i))的整数部分(注:96= 232 。
),i 的单位是弧度。
其中,T[i]是32 位的随机数源,它消除了输入数据中任何规律性的特征。
表1-4 说明了四轮主循环中每轮16 步操作的具体步骤。
所有这些完成之后,将A、B、C、D 分别加上AA、BB、CC、DD。
然后用下一分组数据继续运行算法,最后的输出是A、B、C 和D 的级联。
#include <>#include <>#include <>#include <>typedef unsigned char *POINTER;typedef unsigned short int UINT2;typedef unsigned long int UINT4;typedef struct{UINT4 state[4];UINT4 count[2];unsigned char buffer[64];} MD5_CTX;void MD5Init(MD5_CTX *);void MD5Update(MD5_CTX *, unsigned char *, unsigned int);void MD5Final(unsigned char [16], MD5_CTX *);#define S11 7#define S12 12#define S13 17#define S14 22#define S21 5#define S22 9#define S23 14#define S24 20#define S31 4#define S32 11#define S33 16#define S34 23#define S41 6#define S42 10#define S43 15#define S44 21static unsigned char PADDING[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};#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)))#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))#define FF(a, b, c, d, x, s, ac) { (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }#define GG(a, b, c, d, x, s, ac) { (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }#define HH(a, b, c, d, x, s, ac) { (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }#define II(a, b, c, d, x, s, ac) { (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }inline void Encode(unsigned char *output, UINT4 *input, unsigned int len){unsigned int i, j;for (i = 0, j = 0; j < len; i++, j += 4) {output[j] = (unsigned char)(input[i] & 0xff);output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);}}inline void Decode(UINT4 *output, unsigned char *input, unsigned int len){unsigned int i, j;for (i = 0, j = 0; j < len; i++, j += 4)output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |(((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);}inline void MD5Transform (UINT4 state[4], unsigned char block[64]){UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];Decode (x, block, 64);FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */FF (a, b, c, d, x[ 8], S11, 0x698098d8); /*9 */FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /*28 */GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /*47 */HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */state[0] += a;state[1] += b;state[2] += c;state[3] += d;memset ((POINTER)x, 0, sizeof (x));}inline void MD5Init(MD5_CTX *context){context->count[0] = context->count[1] = 0;context->state[0] = 0x;context->state[1] = 0xefcdab89;context->state[2] = 0x98badcfe;context->state[3] = 0x;}inline void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputLen){unsigned int i, index, partLen;index = (unsigned int)((context->count[0] >> 3) & 0x3F);if ((context->count[0] += ((UINT4)inputLen << 3))< ((UINT4)inputLen << 3))context->count[1]++;context->count[1] += ((UINT4)inputLen >> 29);partLen = 64 - index;if (inputLen >= partLen) {memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen);MD5Transform(context->state, context->buffer);for (i = partLen; i + 63 < inputLen; i += 64)MD5Transform (context->state, &input[i]);index = 0;}elsei = 0;memcpy((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i);}inline void MD5Final(unsigned char digest[16], MD5_CTX *context){unsigned char bits[8];unsigned int index, padLen;Encode (bits, context->count, 8);index = (unsigned int)((context->count[0] >> 3) & 0x3f);padLen = (index < 56) (56 - index) : (120 - index);MD5Update (context, PADDING, padLen);MD5Update (context, bits, 8);Encode (digest, context->state, 16);memset ((POINTER)context, 0, sizeof (*context));}void MD5Digest(char *pszInput, unsigned long nInputSize, char *pszOutPut){MD5_CTX context;unsigned int len = strlen (pszInput);MD5Init (&context);MD5Update (&context, (unsigned char *)pszInput, len); MD5Final ((unsigned char *)pszOutPut, &context);}Int main(){ char szDigest[16];char encrypt[200];printf("请输入要计算MD5值的字符串:");gets(encrypt);printf("\n加密结果:");MD5Digest(encrypt,strlen(encrypt),szDigest);int i;for (i=0;i<16;i++) printf ("%02X",(unsigned char)szDigest[i]);getchar();}六、实验步骤1.算法分析在光盘中附加了有关MD5 算法的头文件和,根据所提供的文件分析MD5 算法的实现过程。