MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。
将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。
MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。
MD5在实际应用中通常有两种用法,一种是计算一个字符串的MD5值,常用于密码相关的操作;另一种是用于计算一个文件的MD5值,一般用于网络传输中验证文件是否出错。
下面是C语言的MD5计算程序,来自Stardict,网上流行的代码都大同小异:
md5.h
#ifndef MD5_H #define MD5_H #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #ifdef HAVE_STDINT_H #include <stdint.h> typedef uint32_t uint32; #else /* A.Leo.: this wont work on 16 bits platforms ;) */ typedef unsigned uint32; #endif #define MD5_FILE_BUFFER_LEN 1024 struct MD5Context { uint32 buf[4]; uint32 bits[2]; unsigned char in[64]; }; void MD5Init(struct MD5Context *context); void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len); void MD5Final(unsigned char digest[16], struct MD5Context *context); void MD5Transform(uint32 buf[4], uint32 const in[16]); int getBytesMD5(const unsigned char* src, unsigned int length, char* md5); int getStringMD5(const char* src, char* md5); int getFileMD5(const char* path, char* md5); /* * This is needed to make RSAREF happy on some MS-DOS compilers. */ typedef struct MD5Context MD5_CTX; #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* !MD5_H */
源文件:
md5.c
#include <string.h> /* for memcpy() */ #include <stdio.h> #include "md5.h" #ifndef HIGHFIRST #define byteReverse(buf, len) /* Nothing */ #else void byteReverse(unsigned char *buf, unsigned longs); #ifndef ASM_MD5 /* * Note: this code is harmless on little-endian machines. */ void byteReverse(unsigned char *buf, unsigned longs) { uint32 t; do { t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | ((unsigned) buf[1] << 8 | buf[0]); *(uint32 *) buf = t; buf += 4; }while (--longs); } #endif #endif static void putu32(uint32 data, unsigned char *addr) { addr[0] = (unsigned char) data; addr[1] = (unsigned char) (data >> 8); addr[2] = (unsigned char) (data >> 16); addr[3] = (unsigned char) (data >> 24); } /* * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. */ void MD5Init(struct MD5Context *ctx) { ctx->buf[0] = 0x67452301; ctx->buf[1] = 0xefcdab89; ctx->buf[2] = 0x98badcfe; ctx->buf[3] = 0x10325476; ctx->bits[0] = 0; ctx->bits[1] = 0; } /* * Update context to reflect the concatenation of another buffer full * of bytes. */ void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) { uint32 t; /* Update bitcount */ t = ctx->bits[0]; if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29; t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ /* Handle any leading odd-sized chunks */ if (t) { unsigned char *p = (unsigned char *) ctx->in + t; t = 64 - t; if (len < t) { memcpy(p, buf, len); return; } memcpy(p, buf, t); byteReverse(ctx->in, 16); MD5Transform(ctx->buf, (uint32 *) ctx->in); buf += t; len -= t; } /* Process data in 64-byte chunks */ while (len >= 64) { memcpy(ctx->in, buf, 64); byteReverse(ctx->in, 16); MD5Transform(ctx->buf, (uint32 *) ctx->in); buf += 64; len -= 64; } /* Handle any remaining bytes of data. */ memcpy(ctx->in, buf, len); } /* * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ void MD5Final(unsigned char digest[16], struct MD5Context *ctx) { unsigned count; unsigned char *p; /* Compute number of bytes mod 64 */ count = (ctx->bits[0] >> 3) & 0x3F; /* Set the first char of padding to 0x80. This is safe since there is always at least one byte free */ p = ctx->in + count; *p++ = 0x80; /* Bytes of padding needed to make 64 bytes */ count = 64 - 1 - count; /* Pad out to 56 mod 64 */ if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, 0, count); byteReverse(ctx->in, 16); MD5Transform(ctx->buf, (uint32 *) ctx->in); /* Now fill the next block with 56 bytes */ memset(ctx->in, 0, 56); } else { /* Pad block to 56 bytes */ memset(p, 0, count - 8); } byteReverse(ctx->in, 14); /* Append length in bits and transform */ //((uint32 *) ctx->in)[14] = ctx->bits[0]; //((uint32 *) ctx->in)[15] = ctx->bits[1]; putu32(ctx->bits[0], ctx->in + 56); putu32(ctx->bits[1], ctx->in + 60); MD5Transform(ctx->buf, (uint32 *) ctx->in); byteReverse((unsigned char *) ctx->buf, 4); memcpy(digest, ctx->buf, 16); memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ } #ifndef ASM_MD5 /* The four core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) /* This is the central step in the MD5 algorithm. */ #define MD5STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) /* * The core of the MD5 algorithm, this alters an existing MD5 hash to * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ void MD5Transform(uint32 buf[4], uint32 const in[16]) { register uint32 a, b, c, d; a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3]; MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } /* * get MD5 of a byte buffer */ int getBytesMD5(const unsigned char* src, unsigned int length, char* md5) { unsigned char i = 0; unsigned char md5Bytes[16] = { 0 }; MD5_CTX context; if (src == NULL || md5 == NULL) { return -1; } MD5Init(&context); MD5Update(&context, src, length); MD5Final(md5Bytes, &context); for (i = 0; i < 16; i++) { sprintf(md5, "%02X", md5Bytes[i]); md5 += 2; } *md5 = '\0'; return 0; } /* * get MD5 for a string */ int getStringMD5(const char* src, char* md5) { return getBytesMD5((unsigned char*) src, strlen((char*) src), md5); } /** * get MD5 of a file */ int getFileMD5(const char* path, char* md5) { FILE* fp = NULL; unsigned char buffer[MD5_FILE_BUFFER_LEN] = { 0 }; int count = 0; MD5_CTX context; unsigned char md5Bytes[16] = { 0 }; int i; if (path == NULL || md5 == NULL) { return -1; } fp = fopen(path, "rb"); if (fp == NULL) { return -1; } MD5Init(&context); while ((count = fread(buffer, 1, MD5_FILE_BUFFER_LEN, fp)) > 0) { MD5Update(&context, buffer, count); } MD5Final(md5Bytes, &context); for (i = 0; i < 16; i++) { sprintf(md5, "%02X", md5Bytes[i]); md5 += 2; } *md5 = '\0'; return 0; } #endif
下面是调用函数计算MD5的代码:
main.c
/* * main.c * * Created on: 2014-11-6 * Author: HZY */ #include <stdio.h> #include <string.h> #include "md5.h" int main(int c, char** v){ char buffer[128]; getStringMD5("hello world", buffer); printf("%s\n", buffer); getFileMD5("hello.pdf", buffer); printf("%s\n", buffer); return 0; }
计算无误:
如果使用java的话也比较简单,java做了相应的封装:
MD5Test.java
package com.hu.md5; import java.io.File; import java.io.FileInputStream; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MD5Test { /** * @param args */ public static void main(String[] args) { MD5Test test = new MD5Test(); System.out.println(test.getStringMD5("hello world")); System.out.println(test.getFileMD5("hello.pdf")); } /** * Get MD5 of a string * * @param src * @return */ private String getStringMD5(String src) { MessageDigest messageDigest = null; byte[] srcBytes = src.getBytes(); try { messageDigest = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } messageDigest.update(srcBytes, 0, srcBytes.length); BigInteger bigInt = new BigInteger(1, messageDigest.digest()); return bigInt.toString(16); } /** * get MD5 of a file * * @param file * @return */ private String getFileMD5(File file) { // 获取文件的MD5值 MessageDigest messageDigest = null; FileInputStream fileInStream = null; byte buffer[] = new byte[1024]; int length = -1; try { messageDigest = MessageDigest.getInstance("MD5"); fileInStream = new FileInputStream(file); while ((length = fileInStream.read(buffer, 0, 1024)) != -1) { messageDigest.update(buffer, 0, length); } fileInStream.close(); } catch (Exception e) { e.printStackTrace(); return null; } BigInteger bigInt = new BigInteger(1, messageDigest.digest()); return bigInt.toString(16); } /** * get MD5 of a file with file path * * @param path * @return */ private String getFileMD5(String path) { return getFileMD5(new File(path)); } }
附件有相应的代码。
相关推荐
总的来说,MD5算法在文件完整性检测方面扮演了重要角色,而这个基于MD5的检测程序则提供了一个方便的工具,帮助用户快速验证文件的完整性。不过,由于MD5的安全性问题,对于涉及敏感数据的情况,建议使用更强大的...
MD5的主要用途是验证数据的完整性,常用于文件校验、密码存储和网络传输数据的验证。 在C++Builder环境下,开发MD5功能的程序通常需要包含特定的库或自定义的类模块。在这个"MD5算法BCB模块"中,提供了一个可以在XE...
在软件开发中,正确地实现和使用MD5可以帮助确保文件在传输或存储过程中的完整性,但需要注意的是,MD5算法已经不再被认为安全用于密码存储,因为它存在碰撞攻击的可能性。对于更安全的用途,可以考虑使用SHA-256或...
此外,附带的7个Hash验证工具可能是为了方便用户检验MD5值的正确性,它们可能有命令行接口,接受输入的MD5摘要和文件路径,然后比较计算出的MD5值是否一致。 在使用MD5算法时,需要注意其安全性问题。由于MD5碰撞...
MD5(Message-Digest Algorithm 5)是一种广泛用于数据完整性校验和安全散列的算法。它由Ronald Rivest在1991年设计,主要用于确保数据在传输...因此,了解和使用MD5验证器对于保障数据安全和文件完整性具有重要意义。
MD5由美国密码学家Ronald Rivest于1991年设计,尽管它在安全领域已经不再被视为安全,因为存在碰撞攻击的可能性,但在验证数据完整性方面仍有一定的应用。 SHA(Secure Hash Algorithm)家族包括SHA-1和SHA-2(包括...
在C语言中实现MD5算法,可以用于数据完整性校验、密码存储等方面。 在STM32单片机上应用MD5算法,首先需要理解STM32的基本架构。STM32是基于ARM Cortex-M系列内核的微控制器,具有高性能、低功耗的特点。在STM32上...
1. **文件校验**:通过计算文件的MD5摘要,可以验证文件在传输或存储过程中的完整性。如果文件的MD5值与原始值不同,那么可以判断文件可能被篡改或损坏。 2. **密码存储**:在很多系统中,用户的密码并不直接存储,...
MD5的主要应用是验证数据的完整性和一致性,特别是在文件传输、软件下载和密码存储等领域。 MD5的工作原理基于分块处理和一系列复杂的数学运算,包括位操作、加法、异或和旋转等。它将输入数据分成512位的块,并对...
`testMd5`可能是用以测试MD5实现的示例程序,它可能包含一段代码,读取一个文件内容,然后计算并打印出该文件的MD5摘要,以此验证算法的正确性。 使用MD5时,需要注意的是,由于MD5算法的安全性问题,它已经不再...
而HMAC(Hash-based Message Authentication Code)是基于密钥的哈希函数,用于验证数据的完整性和来源的可靠性。它结合了密钥和MD5算法,为密码提供额外的安全层。 HMAC-MD5的工作原理是通过将密钥和消息一起输入...
MD5的主要应用是验证数据的完整性和一致性,例如在软件下载、密码存储和数字签名等领域。 在C++中实现MD5算法,你需要理解以下几个关键概念: 1. **MD5的基本结构**:MD5算法由四个不同的处理函数(F, G, H, I)和...
MD5的主要应用在于数据完整性校验、文件校验和以及密码存储。 在网络安全领域,MD5被广泛用于数字签名。数字签名是一种用于验证信息完整性和发送者身份的技术。通过MD5,发送者可以对信息生成一个唯一的数字指纹,...
MD5的主要应用是验证数据完整性,比如在下载文件后计算其MD5值并与提供者给出的MD5值比较,确保文件在传输过程中没有被篡改。尽管MD5的安全性在近年来已被削弱,不再适用于密码存储或高度安全的认证场景,但在一些非...
使用这些函数,开发者可以很容易地将MD5整合到他们的C程序中,以检查文件的完整性或处理密码。然而,需要注意的是,MD5由于其安全性问题(易遭碰撞攻击),已经不再适合用于密码存储和安全认证。尽管如此,MD5仍然是...
6. **使用说明**:`md5使用说明.txt`文件应该包含了如何在不同语言环境下使用这些MD5加密算法的详细步骤和示例。通常会包括代码片段、依赖库的安装指南、如何调用函数以及如何解释和比较MD5摘要等内容。 在实际项目...
源代码中可能还会包含示例用法,展示如何使用这些函数来计算文件的MD5值,并与预期值进行比较,从而完成文件的完整性验证。学习和理解这些源代码可以帮助开发者更好地理解和应用MD5算法,也可以为开发自己的校验工具...
本篇文档介绍的是一个基于Verilog HDL语言实现的MD5算法模块,该模块可以直接应用于嵌入式系统中,并且提供了完整的仿真验证结果,确保了其实现的正确性。接下来将详细介绍此模块的设计原理、内部结构以及如何在实际...