一、原理

前一阵子,想知道md5的原理查了一下资料,说得基本都一样,最后让我看懂的是这两个链接:

http://blog.csdn.net/qf_study/article/details/2630903

http://baike.baidu.com/link?url=MBQj5ddK13WUItbGHutP_cEX17jZ5ou3nu_bdHYECctRKFLIikI0xrcwzv31JB2PsZHMKlFnOT94v9aMB6LzTa

用我的话说一下原理就是这样的:

先定义a、b、c、d四个变量,赋一个初值。
然后把你输入的数据按照每512位分个块,最后的512字节前448字节用部位实现,后64字节存输入的长度;
每个512位的块,分成16个组,每组也就是一个32位的变量,按照一定的算法叠加到a,b,c,d四个变量里;
算法是这样的:a=b+(a+Process P(b,c,d)+M[i]+T[k])<<s),后面的块把结果叠加到前面块的计算结果中(相当于abcd就是个全局变量)
最后算出的a,b,c,d级联到一起,就是一个128位的数,用16进制表示每个位,就是一个长度为32的字符串,也就是最终的结果;

二、MD5的源码:

http://www.cnblogs.com/ruihong/archive/2012/10/24/2736727.html (如果转载请加注源作者的链接)

经过修改之后,可以编译使用了,为了方便以后引用,记录如下:

md5.h

#ifndef _CMD5_H
#define _CMD5_H //#pragma warning(disable:4786) #include <string> using namespace std; /*!
* Manage CMD5.
*/
class CMD5
{
private:
#define uint8 unsigned char
#define uint32 unsigned long int struct md5_context
{
uint32 total[];
uint32 state[];
uint8 buffer[];
}; void md5_starts( struct md5_context *ctx );
void md5_process( struct md5_context *ctx, uint8 data[] );
void md5_update( struct md5_context *ctx, uint8 *input, uint32 length );
void md5_finish( struct md5_context *ctx, uint8 digest[] ); public:
//! construct a CMD5 from any buffer
void GenerateMD5(unsigned char* buffer,int bufferlen); //! construct a CMD5
CMD5(); //! construct a md5src from char *
CMD5(const char * md5src); //! construct a CMD5 from a 16 bytes md5
CMD5(unsigned long* md5src); //! add a other md5
CMD5 operator +(CMD5 adder); //! just if equal
bool operator ==(CMD5 cmper); //! give the value from equer
// void operator =(CMD5 equer); //! to a string
string ToString(); unsigned long m_data[];
};
#endif /* md5.h */

md5.cpp

/*
* RFC 1321 compliant CMD5 implementation,
* by Christophe Devine <devine@cr0.net>;
* this program is licensed under the GPL.
*/
#include "md5.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #define GET_UINT32(n,b,i) \
{ \
(n) = (uint32) ((uint8 *) b)[(i)] \
| (((uint32) ((uint8 *) b)[(i)+]) << ) \
| (((uint32) ((uint8 *) b)[(i)+]) << ) \
| (((uint32) ((uint8 *) b)[(i)+]) << ); \
} #define PUT_UINT32(n,b,i) \
{ \
(((uint8 *) b)[(i)] ) = (uint8) (((n) ) & 0xFF); \
(((uint8 *) b)[(i)+]) = (uint8) (((n) >> ) & 0xFF); \
(((uint8 *) b)[(i)+]) = (uint8) (((n) >> ) & 0xFF); \
(((uint8 *) b)[(i)+]) = (uint8) (((n) >> ) & 0xFF); \
} //extern pthread_mutex_t mutexMemory; void CMD5::md5_starts( struct md5_context *ctx )
{
ctx->total[] = ;
ctx->total[] = ;
ctx->state[] = 0x67452301;
ctx->state[] = 0xEFCDAB89;
ctx->state[] = 0x98BADCFE;
ctx->state[] = 0x10325476;
} void CMD5::md5_process( struct md5_context *ctx, uint8 data[] )
{
uint32 A, B, C, D, X[]; GET_UINT32( X[], data, );
GET_UINT32( X[], data, );
GET_UINT32( X[], data, );
GET_UINT32( X[], data, );
GET_UINT32( X[], data, );
GET_UINT32( X[], data, );
GET_UINT32( X[], data, );
GET_UINT32( X[], data, );
GET_UINT32( X[], data, );
GET_UINT32( X[], data, );
GET_UINT32( X[], data, );
GET_UINT32( X[], data, );
GET_UINT32( X[], data, );
GET_UINT32( X[], data, );
GET_UINT32( X[], data, );
GET_UINT32( X[], data, ); #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) #define P(a,b,c,d,k,s,t) \
{ \
a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
} A = ctx->state[];
B = ctx->state[];
C = ctx->state[];
D = ctx->state[]; #define F(x,y,z) (z ^ (x & (y ^ z))) P( A, B, C, D, , , 0xD76AA478 );
P( D, A, B, C, , , 0xE8C7B756 );
P( C, D, A, B, , , 0x242070DB );
P( B, C, D, A, , , 0xC1BDCEEE );
P( A, B, C, D, , , 0xF57C0FAF );
P( D, A, B, C, , , 0x4787C62A );
P( C, D, A, B, , , 0xA8304613 );
P( B, C, D, A, , , 0xFD469501 );
P( A, B, C, D, , , 0x698098D8 );
P( D, A, B, C, , , 0x8B44F7AF );
P( C, D, A, B, , , 0xFFFF5BB1 );
P( B, C, D, A, , , 0x895CD7BE );
P( A, B, C, D, , , 0x6B901122 );
P( D, A, B, C, , , 0xFD987193 );
P( C, D, A, B, , , 0xA679438E );
P( B, C, D, A, , , 0x49B40821 ); #undef F #define F(x,y,z) (y ^ (z & (x ^ y))) P( A, B, C, D, , , 0xF61E2562 );
P( D, A, B, C, , , 0xC040B340 );
P( C, D, A, B, , , 0x265E5A51 );
P( B, C, D, A, , , 0xE9B6C7AA );
P( A, B, C, D, , , 0xD62F105D );
P( D, A, B, C, , , 0x02441453 );
P( C, D, A, B, , , 0xD8A1E681 );
P( B, C, D, A, , , 0xE7D3FBC8 );
P( A, B, C, D, , , 0x21E1CDE6 );
P( D, A, B, C, , , 0xC33707D6 );
P( C, D, A, B, , , 0xF4D50D87 );
P( B, C, D, A, , , 0x455A14ED );
P( A, B, C, D, , , 0xA9E3E905 );
P( D, A, B, C, , , 0xFCEFA3F8 );
P( C, D, A, B, , , 0x676F02D9 );
P( B, C, D, A, , , 0x8D2A4C8A ); #undef F #define F(x,y,z) (x ^ y ^ z) P( A, B, C, D, , , 0xFFFA3942 );
P( D, A, B, C, , , 0x8771F681 );
P( C, D, A, B, , , 0x6D9D6122 );
P( B, C, D, A, , , 0xFDE5380C );
P( A, B, C, D, , , 0xA4BEEA44 );
P( D, A, B, C, , , 0x4BDECFA9 );
P( C, D, A, B, , , 0xF6BB4B60 );
P( B, C, D, A, , , 0xBEBFBC70 );
P( A, B, C, D, , , 0x289B7EC6 );
P( D, A, B, C, , , 0xEAA127FA );
P( C, D, A, B, , , 0xD4EF3085 );
P( B, C, D, A, , , 0x04881D05 );
P( A, B, C, D, , , 0xD9D4D039 );
P( D, A, B, C, , , 0xE6DB99E5 );
P( C, D, A, B, , , 0x1FA27CF8 );
P( B, C, D, A, , , 0xC4AC5665 ); #undef F #define F(x,y,z) (y ^ (x | ~z)) P( A, B, C, D, , , 0xF4292244 );
P( D, A, B, C, , , 0x432AFF97 );
P( C, D, A, B, , , 0xAB9423A7 );
P( B, C, D, A, , , 0xFC93A039 );
P( A, B, C, D, , , 0x655B59C3 );
P( D, A, B, C, , , 0x8F0CCC92 );
P( C, D, A, B, , , 0xFFEFF47D );
P( B, C, D, A, , , 0x85845DD1 );
P( A, B, C, D, , , 0x6FA87E4F );
P( D, A, B, C, , , 0xFE2CE6E0 );
P( C, D, A, B, , , 0xA3014314 );
P( B, C, D, A, , , 0x4E0811A1 );
P( A, B, C, D, , , 0xF7537E82 );
P( D, A, B, C, , , 0xBD3AF235 );
P( C, D, A, B, , , 0x2AD7D2BB );
P( B, C, D, A, , , 0xEB86D391 ); #undef F ctx->state[] += A;
ctx->state[] += B;
ctx->state[] += C;
ctx->state[] += D;
} void CMD5::md5_update( struct md5_context *ctx, uint8 *input, uint32 length )
{
uint32 left, fill; if( ! length ) return; left = ( ctx->total[] >> ) & 0x3F;
fill = - left; ctx->total[] += length << ;
ctx->total[] += length >> ; ctx->total[] &= 0xFFFFFFFF;
ctx->total[] += ctx->total[] < length << ; if( left && length >= fill )
{
memcpy( (void *) (ctx->buffer + left), (void *) input, fill );
md5_process( ctx, ctx->buffer );
length -= fill;
input += fill;
left = ;
} while( length >= )
{
md5_process( ctx, input );
length -= ;
input += ;
} if( length )
{
memcpy( (void *) (ctx->buffer + left), (void *) input, length );
}
} static uint8 md5_padding[] =
{
0x80, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , ,
}; void CMD5::md5_finish( struct md5_context *ctx, uint8 digest[] )
{
uint32 last, padn;
uint8 msglen[]; PUT_UINT32( ctx->total[], msglen, );
PUT_UINT32( ctx->total[], msglen, ); last = ( ctx->total[] >> ) & 0x3F;
padn = ( last < ) ? ( - last ) : ( - last ); md5_update( ctx, md5_padding, padn );
md5_update( ctx, msglen, ); PUT_UINT32( ctx->state[], digest, );
PUT_UINT32( ctx->state[], digest, );
PUT_UINT32( ctx->state[], digest, );
PUT_UINT32( ctx->state[], digest, );
} void CMD5::GenerateMD5(unsigned char* buffer,int bufferlen)
{
struct md5_context context;
md5_starts (&context);
md5_update (&context, buffer, bufferlen);
md5_finish (&context,(unsigned char*)m_data);
} CMD5::CMD5()
{
for(int i=;i<;i++)
m_data[i]=;
} CMD5::CMD5(unsigned long* md5src)
{
memcpy(m_data,md5src,);
}
int _httoi(const char *value)
{
struct CHexMap
{
char chr;
int value;
};
const int HexMapL = ;
CHexMap HexMap[HexMapL] =
{
{'', }, {'', },
{'', }, {'', },
{'', }, {'', },
{'', }, {'', },
{'', }, {'', },
{'a', }, {'b', },
{'c', }, {'d', },
{'e', }, {'f', }
};
//pthread_mutex_lock(&mutexMemory);
char *mstr = strdup(value);
//pthread_mutex_unlock(&mutexMemory);
char *s = mstr;
int result = ;
if (*s == '' && *(s + ) == 'X') s += ;
bool firsttime = true;
while (*s != '/0')
{
bool found = false;
for (int i = ; i < HexMapL; i++)
{
if (*s == HexMap[i].chr)
{
if (!firsttime) result <<= ;
result |= HexMap[i].value;
found = true;
break;
}
}
if (!found) break;
s++;
firsttime = false;
}
//pthread_mutex_lock(&mutexMemory);
free(mstr);
//pthread_mutex_unlock(&mutexMemory);
return result;
} CMD5::CMD5(const char* md5src)
{
if (strcmp(md5src,"")==)
{
for(int i=;i<;i++)
m_data[i]=;
return;
}
for(int j = ; j < ; j++ )
{
char buf[];
strncpy(buf,md5src,);
md5src+=;
((unsigned char*)m_data)[j] = _httoi(buf);
}
} CMD5 CMD5::operator +(CMD5 adder)
{
unsigned long m_newdata[];
for(int i=;i<;i++)
m_newdata[i]=m_data[i]^(adder.m_data[i]);
return CMD5(m_newdata);
} bool CMD5::operator ==(CMD5 cmper)
{
return (memcmp(cmper.m_data ,m_data,)==);
} //void CMD5::operator =(CMD5 equer)
//{
// memcpy(m_data,equer.m_data ,16);
//} string CMD5::ToString()
{
char output[];
for(int j = ; j < ; j++ )
{
sprintf( output + j * , "%02x", ((unsigned char*)m_data)[j]);
}
return string(output);
}

main.cpp

#include <iostream>
#include "md5.h"
using namespace std; int main()
{
const char *text = "hello world";
const char *text1 = "hello ";
const char *text2 = "world"; CMD5 iMD5;
iMD5.GenerateMD5((unsigned char*)text, strlen(text) );
std::string result = iMD5.ToString();
cout<<result<<endl;
}

Makefile

COMPILER=g++

executemain : main.o md5.o
$(COMPILER) -o executemain main.o md5.o
main.o : main.cpp md5.h
$(COMPILER) -g -c main.cpp
md5.o : md5.h md5.cpp
$(COMPILER) -g -c md5.cpp
clean :
rm -f executemain main.o md5.o

三、大文件也没问题

源码中只给md5传了一个字符数组,万一是大文件怎么办?

看懂了原理,应该不难理解,都是分成512个位的块叠加,用数组多传几次是一样的效果,只是源码中把主要函数设置为私有变量,如果需要自己封装一下也可以实现,只是给大家引用一个CSDN大神的解法:http://bbs.csdn.net/topics/230085330提供个思路吧

$ cat t2.c; gcc -o t2 t2.c `pkg-config openssl --cflags --libs`; ./t2
/***************************************************************/
#include <stdio.h>
#include <openssl/md5.h>
#include <openssl/rand.h> typedef unsigned char byte;
#define INPUT_LEN (1024+123) void test1( byte* input , int len , int l1 )
{
int i;
byte md5[];
MD5_CTX ctx;
MD5_Init( &ctx );
for( ;len >= l1; input += l1 , len -= l1 )
MD5_Update( &ctx , input , l1 );
if( len )
MD5_Update( &ctx , input , len );
MD5_Final( md5 , &ctx ); for( i = ; i < ; ++i )
printf( "%02X " , md5[i] );
printf( " : %d\n" , l1 );
}
int main()
{
int l1;
byte input[INPUT_LEN];
RAND_bytes( input , sizeof( input ) ); for( l1 = ; l1 <= INPUT_LEN; l1 <<= )
test1( input , sizeof( input ) , l1 );
return ;
}
/***************************************************************/
AD BB AF 9C E9 5A DD 7D CB 3A 3F C8 E1 :
AD BB AF 9C E9 5A DD 7D CB 3A 3F C8 E1 :
AD BB AF 9C E9 5A DD 7D CB 3A 3F C8 E1 :
AD BB AF 9C E9 5A DD 7D CB 3A 3F C8 E1 :
AD BB AF 9C E9 5A DD 7D CB 3A 3F C8 E1 :
AD BB AF 9C E9 5A DD 7D CB 3A 3F C8 E1 :
AD BB AF 9C E9 5A DD 7D CB 3A 3F C8 E1 :
AD BB AF 9C E9 5A DD 7D CB 3A 3F C8 E1 :
AD BB AF 9C E9 5A DD 7D CB 3A 3F C8 E1 :
AD BB AF 9C E9 5A DD 7D CB 3A 3F C8 E1 :
AD BB AF 9C E9 5A DD 7D CB 3A 3F C8 E1 :

md5的C++实现的更多相关文章

  1. 关于CryptoJS中md5加密以及aes加密的随笔

    最近项目中用到了各种加密,其中就包括从没有接触过得aes加密,因此从网上各种查,官方的一种说法: 高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学 ...

  2. Android数据加密之MD5加密

    前言: 项目中无论是密码的存储或者说判断文件是否是同一文件,都会用到MD5算法,今天来总结一下MD5加密算法. 什么是MD5加密? MD5英文全称“Message-Digest Algorithm 5 ...

  3. [C#] 简单的 Helper 封装 -- SecurityHelper 安全助手:封装加密算法(MD5、SHA、HMAC、DES、RSA)

    using System; using System.IO; using System.Security.Cryptography; using System.Text; namespace Wen. ...

  4. java单向加密算法小结(2)--MD5哈希算法

    上一篇文章整理了Base64算法的相关知识,严格来说,Base64只能算是一种编码方式而非加密算法,这一篇要说的MD5,其实也不算是加密算法,而是一种哈希算法,即将目标文本转化为固定长度,不可逆的字符 ...

  5. android_m2repository_rxx.zip下载地址以及MD5

    地址 MD5 https://dl-ssl.google.com/android/repository/android_m2repository_r08.zip 8C8EC4C731B7F55E646 ...

  6. 一种简单的md5加盐加密的方法(防止彩虹表撞库)

    md5加密(或者说摘要算法)大家都很熟悉了 就不解释了 现在很多数据库设计都喜欢用单向加密的方式保存密码,验证时对提交的密码再次加密之后做密文对比 /// <summary> 使用MD5加 ...

  7. 2、摘要函数——MD2/MD4/MD5数字签名

    摘要是用来防止数据被私自改动的方法,其中用到的函数叫做摘要函数.这些函数的输入可以是任意大小的信息,但是输出是大小固定的摘要.摘要有个重要的特性:如果改变了输入信息的任何内容,即使改变一位,输出也将发 ...

  8. c#官方推荐md5通用加密类

    /// <summary> /// MD5加密 /// </summary> /// <param name="input">需要加密的字符串& ...

  9. 密码学应用(DES,AES, MD5, SHA1, RSA, Salt, Pkcs8)

    目录 一.数据加密标准 - Data Encryption Standard(DES) 二.高级加密标准 - Advanced Encryption Standard(AES) 三.消息摘要算法第五版 ...

  10. 原创:MD5 32位加密软件

    网站后台数据库切勿使用明文保存密码,否则一旦黑客拿下你的Webshell,后果不堪设想. 网站后台密码加密大多数采用的就是MD5算法加密.今天给大家送一个本人用c#简单编写的MD5 32位加密程序,虽 ...

随机推荐

  1. PHPMailer不能发送邮件

    PHPMailer不能连接SMTP服务器,和修改SMTP大小写没有关系 (2011-10-22 12:17:35) 转载▼ 标签: php phpmailer 杂谈 分类: 默认分类 PHPmaile ...

  2. html常用的综合体

    clip:rect(20px 100px 50px 20px); clip属性中的rect,clip:rect(y1 x2 y2 x1)参数说明如下: y1=定位的y坐标(垂直方向)的起点 x1=定位 ...

  3. 使用xmarks同步 chrome ie firefox safari书签

    xmarks是什么? Install Xmarks on each computer you use, and it seamlessly integrates with your web brows ...

  4. 回到过去美好的时光——源代码版本管理Always Use source code Control

    Don't Repeat Yourself Don't Repeat Yourself,这是程序员修炼之道中的经典名言.源代码版本管理对程序员来说是非常重要的工作.因为它让你能够回到过去,而不用做重复 ...

  5. Java基础知识学习(八)

    IO操作 5个重要的类分别是:InputStream.OutStream.Reader.Writer和File类 面向字符的输入输出流 输入流都是Reader的子类, CharArrayReader ...

  6. JAVA中获取路径

    内容来自于snannan_268 关键字: java中获取路径 JAVA中获取路径: 1.jsp中取得路径:   以工程名为TEST为例: (1)得到包含工程名的当前页面全路径:request.get ...

  7. 烂泥:centos单独编译安装gd库

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 这几天一直在弄一个商城系统,该系统的源码及数据库都已经上传并创建完毕.但是在安装该系统时,却提示缺少gd库.如下: 使用php探针查看,发现php确实没 ...

  8. oops call trace 解析

    Call Trace: [  221.634988]  [<ffffffff8103fbc7>] ? kmld_pte_lookup+0x17/0x60 [  221.635016]  [ ...

  9. discuz mysqli_connect() 不支持 advice_mysqli_connect

      看网友的解决方案是:下面2行去掉注释 ? 1 2 ;extension=php_mysql.dll ;extension=php_mysqli.dl 尝试修改 ? 1 #vi /etc/php.i ...

  10. linux centos使用xrdp远程界面登陆

    redhat6 安装xrdp 直接使用windows远程桌面连接登陆 下面介绍实现方法: 第一步:下载源码包,并安装一些依赖的软件下载xrdp源码包 ​wget http://downloads.so ...