MD5加密
来源:互联网 发布:数据库通用访问工具 编辑:程序博客网 时间:2024/05/29 18:44
一、MD5概念
MD5,全名Message Digest Algorithm 5 ,中文名为消息摘要算法第五版,
为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护。
上面这段话话引用自百度百科,我的理解MD5是一种信息摘要算法,主要是通过特定的hash散列方法将文本信息转换成简短的信息摘要,
压缩+加密+hash算法的结合体,是绝对不可逆的。
二、MD5计算步骤
MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,
经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
第一步、填充
如果输入信息的长度(bit)对512求余的结果不等于448,就需要填充使得对512求余的结果等于448。
填充的方法是填充一个1和n个0。填充完后,信息的长度就为N*512+448(bit);
第二步、记录信息长度
用64位来存储填充前信息长度。这64位加在第一步结果的后面,这样信息长度就变为N*512+448+64=(N+1)*512位。
第三步、装入标准的幻数(四个整数)
标准的幻数(物理顺序)是(A=(01234567)16,B=(89ABCDEF)16,C=(FEDCBA98)16,D=(76543210)16)。如果在程序中定义应该是(A=0X67452301L,B=0XEFCDAB89L,C=0X98BADCFEL,D=0X10325476L)。有点晕哈,其实想一想就明白了。
第四步、四轮循环运算
循环的次数是分组的个数(N+1)
1)将每一512字节细分成16个小组,每个小组64位(8个字节)2)先认识四个线性函数(&是与,|是或,~是非,^是异或)
- FF(a,b,c,d,Mj,s,ti)表示a=b+((a+F(b,c,d)+Mj+ti)<<<s) < span="" style="word-wrap: break-word;">
- GG(a,b,c,d,Mj,s,ti)表示a=b+((a+G(b,c,d)+Mj+ti)<<<s) < span="" style="word-wrap: break-word;">
- HH(a,b,c,d,Mj,s,ti)表示a=b+((a+H(b,c,d)+Mj+ti)<<<s) < span="" style="word-wrap: break-word;">
- II(a,b,c,d,Mj,s,ti)表示a=b+((a+I(b,c,d)+Mj+ti)<<<s) < span="" style="word-wrap: break-word;">
4)四轮运算
- //MessageDigestAlgorithm5.h
- #pragma once
- #include
- #include
- #include
- using namespace std;
- typedef unsigned char Byte;
- class CMessageDigestAlgorithm5
- {
- public:
- CMessageDigestAlgorithm5(void);
- ~CMessageDigestAlgorithm5(void);
- //MD5算法主函数,对str加密
- string Encode(string &str);
- string Encode(ifstream& infile);
- private:
- unsigned int F(unsigned int x, unsigned int y,unsigned int z);
- unsigned int G(unsigned int x, unsigned int y,unsigned int z);
- unsigned int H(unsigned int x, unsigned int y,unsigned int z);
- unsigned int I(unsigned int x, unsigned int y,unsigned int z);
- void Initialize();
- unsigned int LeftRotate(unsigned int opNumber,unsigned int opBit);
- void FF(unsigned int &a, unsigned int b,unsigned int c,unsigned int d, unsigned int Mj,unsigned int s,unsigned int Ti);
- void GG(unsigned int &a, unsigned int b,unsigned int c,unsigned int d, unsigned int Mj,unsigned int s,unsigned int Ti);
- void HH(unsigned int &a, unsigned int b,unsigned int c,unsigned int d, unsigned int Mj,unsigned int s,unsigned int Ti);
- void II(unsigned int &a, unsigned int b,unsigned int c,unsigned int d, unsigned int Mj,unsigned int s,unsigned int Ti);
- void ByteToUnsignedInt(const Byte* input, unsigned int* output, size_t length);
- string ByteToHexString(const Byte* input, size_t length);
- void UnsignedIntToByte(const unsigned int * input, Byte* output, size_t length);
- void ProcessOfMDA5(const Byte block[64]);
- void EncodeByte(const Byte* input, size_t length);
- void Final();
- private:
- unsigned int m_ChainingVariable[4];
- unsigned int m_Count[2];
- Byte m_Result[16];
- Byte m_Buffer[64];
- enum
- {
- S11 = 7,
- S12 = 12,
- S13 = 17,
- S14 = 22,
- S21 = 5,
- S22 = 9,
- S23 = 14,
- S24 = 20,
- S31 = 4,
- S32 = 11,
- S33 = 16,
- S34 = 23,
- S41 = 6,
- S42 = 10,
- S43 = 15,
- S44 = 21,
- };
- static const Byte g_Padding[64];
- };
- //MessageDigestAlgorithm5.cpp
- #include "stdafx.h"
- #include "MessageDigestAlgorithm5.h"
- const Byte CMessageDigestAlgorithm5::g_Padding[64] = { 0x80 };//第一位补1,其他补0
- CMessageDigestAlgorithm5::CMessageDigestAlgorithm5(void)
- {
- }
- CMessageDigestAlgorithm5::~CMessageDigestAlgorithm5(void)
- {
- }
- unsigned int CMessageDigestAlgorithm5::F(unsigned int x, unsigned int y,unsigned int z)
- {
- return (x & y) | ((~ x) & z);
- }
- unsigned int CMessageDigestAlgorithm5::G(unsigned int x, unsigned int y,unsigned int z)
- {
- return (x & z) | (y & (~ z));
- }
- unsigned int CMessageDigestAlgorithm5::H(unsigned int x, unsigned int y,unsigned int z)
- {
- return x ^ y ^ z;
- }
- unsigned int CMessageDigestAlgorithm5::I(unsigned int x, unsigned int y,unsigned int z)
- {
- return y ^ (x | (~ z));
- }
- /***************************************************
- *参数:空
- *功能:初始化链接变量
- *返回值:空
- ****************************************************/
- void CMessageDigestAlgorithm5::Initialize()
- {
- m_Count[0] = m_Count[1] = 0;
- m_ChainingVariable[0] = 0x67452301;
- m_ChainingVariable[1] = 0xefcdab89;
- m_ChainingVariable[2] = 0x98badcfe;
- m_ChainingVariable[3] = 0x10325476;
- }
- /***************************************************
- *参数:opNumber表示待左移的数
- opBit表示左移的位数
- *功能:完成循环左移操作
- *返回值:循环左移后值
- ****************************************************/
- unsigned int CMessageDigestAlgorithm5::LeftRotate(unsigned int opNumber,unsigned int opBit)
- {
- unsigned int left = opNumber;
- unsigned int right = opNumber;
- return (left << opBit) | (right >> (32 - opBit));
- }
- void CMessageDigestAlgorithm5::FF(unsigned int &a, unsigned int b,unsigned int c,unsigned int d, unsigned int Mj,unsigned int s,unsigned int Ti)
- {
- unsigned int temp = a + F(b,c,d) + Mj + Ti;
- a = b + LeftRotate(temp,s);
- }
- void CMessageDigestAlgorithm5::GG(unsigned int &a, unsigned int b,unsigned int c,unsigned int d,unsigned int Mj,unsigned int s,unsigned int Ti)
- {
- unsigned int temp = a + G(b,c,d) + Mj + Ti;
- a = b + LeftRotate(temp,s);
- }
- void CMessageDigestAlgorithm5::HH(unsigned int &a, unsigned int b,unsigned int c,unsigned int d, unsigned int Mj,unsigned int s,unsigned int Ti)
- {
- unsigned int temp = a + H(b,c,d) + Mj + Ti;
- a = b + LeftRotate(temp,s);
- }
- void CMessageDigestAlgorithm5::II(unsigned int &a, unsigned int b,unsigned int c,unsigned int d, unsigned int Mj,unsigned int s,unsigned int Ti)
- {
- unsigned int temp = a + I(b,c,d) + Mj + Ti;
- a = b + LeftRotate(temp,s);
- }
- /***************************************************
- *参数:input表示输入字节数组
- output表示输出unsigned int数组
- length表示输入字节长度
- *功能:byte转unsigned int(左低右高)
- *返回值:空
- ****************************************************/
- void CMessageDigestAlgorithm5::ByteToUnsignedInt(const Byte* input, unsigned int* output, size_t length)
- {
- for(size_t i = 0,j = 0;j < length;++ i, j += 4)
- {
- output[i] = ((static_cast<unsigned < span="" style="word-wrap: break-word;">int>(input[j]))
- |((static_cast<unsigned < span="" style="word-wrap: break-word;">int>(input[j + 1])) << 8)
- |((static_cast<unsigned < span="" style="word-wrap: break-word;">int>(input[j + 2])) << 16)
- |((static_cast<unsigned < span="" style="word-wrap: break-word;">int>(input[j + 3])) << 24));
- }
- }
- /***************************************************
- *参数:input表示输入unsigned int数组
- output表示输出字节数组
- length表示输入字节长度
- *功能:unsigned int转byte
- *返回值:空
- ****************************************************/
- void CMessageDigestAlgorithm5::UnsignedIntToByte(const unsigned int * input, Byte* output, size_t length)
- {
- for (size_t i = 0, j = 0; j < length; ++i, j += 4)
- {
- output[j] = static_cast(input[i] & 0xff);
- output[j + 1] = static_cast((input[i] >> 8) & 0xff);
- output[j + 2] = static_cast((input[i] >> 16) & 0xff);
- output[j + 3] = static_cast((input[i] >> 24) & 0xff);
- }
- }
- /***************************************************
- *参数:groups[]表示一个512位(64字节)分组
- *功能:四轮主要操作
- *返回值:空
- ****************************************************/
- void CMessageDigestAlgorithm5::ProcessOfMDA5(const Byte groups[64])
- {
- unsigned int a = m_ChainingVariable[0], b = m_ChainingVariable[1], c = m_ChainingVariable[2], d = m_ChainingVariable[3];
- unsigned int M[16];
- ByteToUnsignedInt( groups, M, 64);
- FF(a, b, c, d, M[ 0], S11, 0xd76aa478);
- FF(d, a, b, c, M[ 1], S12, 0xe8c7b756);
- FF(c, d, a, b, M[ 2], S13, 0x242070db);
- FF(b, c, d, a, M[ 3], S14, 0xc1bdceee);
- FF(a, b, c, d, M[ 4], S11, 0xf57c0faf);
- FF(d, a, b, c, M[ 5], S12, 0x4787c62a);
- FF(c, d, a, b, M[ 6], S13, 0xa8304613);
- FF(b, c, d, a, M[ 7], S14, 0xfd469501);
- FF(a, b, c, d, M[ 8], S11, 0x698098d8);
- FF(d, a, b, c, M[ 9], S12, 0x8b44f7af);
- FF(c, d, a, b, M[10], S13, 0xffff5bb1);
- FF(b, c, d, a, M[11], S14, 0x895cd7be);
- FF(a, b, c, d, M[12], S11, 0x6b901122);
- FF(d, a, b, c, M[13], S12, 0xfd987193);
- FF(c, d, a, b, M[14], S13, 0xa679438e);
- FF(b, c, d, a, M[15], S14, 0x49b40821);
- GG(a, b, c, d, M[ 1], S21, 0xf61e2562);
- GG(d, a, b, c, M[ 6], S22, 0xc040b340);
- GG(c, d, a, b, M[11], S23, 0x265e5a51);
- GG(b, c, d, a, M[ 0], S24, 0xe9b6c7aa);
- GG(a, b, c, d, M[ 5], S21, 0xd62f105d);
- GG(d, a, b, c, M[10], S22, 0x2441453);
- GG(c, d, a, b, M[15], S23, 0xd8a1e681);
- GG(b, c, d, a, M[ 4], S24, 0xe7d3fbc8);
- GG(a, b, c, d, M[ 9], S21, 0x21e1cde6);
- GG(d, a, b, c, M[14], S22, 0xc33707d6);
- GG(c, d, a, b, M[ 3], S23, 0xf4d50d87);
- GG(b, c, d, a, M[ 8], S24, 0x455a14ed);
- GG(a, b, c, d, M[13], S21, 0xa9e3e905);
- GG(d, a, b, c, M[ 2], S22, 0xfcefa3f8);
- GG(c, d, a, b, M[ 7], S23, 0x676f02d9);
- GG(b, c, d, a, M[12], S24, 0x8d2a4c8a);
- HH(a, b, c, d, M[ 5], S31, 0xfffa3942);
- HH(d, a, b, c, M[ 8], S32, 0x8771f681);
- HH(c, d, a, b, M[11], S33, 0x6d9d6122);
- HH(b, c, d, a, M[14], S34, 0xfde5380c);
- HH(a, b, c, d, M[ 1], S31, 0xa4beea44);
- HH(d, a, b, c, M[ 4], S32, 0x4bdecfa9);
- HH(c, d, a, b, M[ 7], S33, 0xf6bb4b60);
- HH(b, c, d, a, M[10], S34, 0xbebfbc70);
- HH(a, b, c, d, M[13], S31, 0x289b7ec6);
- HH(d, a, b, c, M[ 0], S32, 0xeaa127fa);
- HH(c, d, a, b, M[ 3], S33, 0xd4ef3085);
- HH(b, c, d, a, M[ 6], S34, 0x4881d05);
- HH(a, b, c, d, M[ 9], S31, 0xd9d4d039);
- HH(d, a, b, c, M[12], S32, 0xe6db99e5);
- HH(c, d, a, b, M[15], S33, 0x1fa27cf8);
- HH(b, c, d, a, M[ 2], S34, 0xc4ac5665);
- II(a, b, c, d, M[ 0], S41, 0xf4292244);
- II(d, a, b, c, M[ 7], S42, 0x432aff97);
- II(c, d, a, b, M[14], S43, 0xab9423a7);
- II(b, c, d, a, M[ 5], S44, 0xfc93a039);
- II(a, b, c, d, M[12], S41, 0x655b59c3);
- II(d, a, b, c, M[ 3], S42, 0x8f0ccc92);
- II(c, d, a, b, M[10], S43, 0xffeff47d);
- II(b, c, d, a, M[ 1], S44, 0x85845dd1);
- II(a, b, c, d, M[ 8], S41, 0x6fa87e4f);
- II(d, a, b, c, M[15], S42, 0xfe2ce6e0);
- II(c, d, a, b, M[ 6], S43, 0xa3014314);
- II(b, c, d, a, M[13], S44, 0x4e0811a1);
- II(a, b, c, d, M[ 4], S41, 0xf7537e82);
- II(d, a, b, c, M[11], S42, 0xbd3af235);
- II(c, d, a, b, M[ 2], S43, 0x2ad7d2bb);
- II(b, c, d, a, M[ 9], S44, 0xeb86d391);
- m_ChainingVariable[0] += a;
- m_ChainingVariable[1] += b;
- m_ChainingVariable[2] += c;
- m_ChainingVariable[3] += d;
- }
- /***************************************************
- *参数:input表示输入字节数组
- length表示输入字节长度=16(8*16=128位输出)
- *功能:byte转16进制
- *返回值:16进制字符串
- ****************************************************/
- string CMessageDigestAlgorithm5::ByteToHexString(const Byte* input, size_t length)
- {
- const char MapByteToHex[16] =
- {
- '0', '1', '2', '3',
- '4', '5', '6', '7',
- '8', '9', 'A', 'B',
- 'C', 'D', 'E', 'F'
- };
- string str;
- for (size_t i = 0; i < length; ++ i)
- {
- unsigned int temp = static_cast<unsigned < span="" style="word-wrap: break-word;">int>(input[i]);
- unsigned int a = temp / 16;
- unsigned int b = temp % 16;
- str.append(1, MapByteToHex[a]);
- str.append(1, MapByteToHex[b]);
- }
- return str;
- }
- /***************************************************
- *参数:str表示待加密文本
- *功能:MD5算法主函数
- *返回值:MD5加密后算列值
- ****************************************************/
- string CMessageDigestAlgorithm5::Encode(string &str)
- {
- Initialize();
- EncodeByte((const Byte * )(str.c_str()), str.length());
- Final();
- string strMD5 = ByteToHexString(m_Result,16);
- return strMD5;
- }
- /***************************************************
- *参数:infile表示待加密文件
- *功能:MD5算法主函数
- *返回值:MD5加密后算列值
- ****************************************************/
- string CMessageDigestAlgorithm5::Encode(ifstream & infile)
- {
- if (!infile)
- {
- return "";
- }
- Initialize();
- streamsize length;
- string str;
- char buffer[1024];
- while (! infile.eof())
- {
- infile.read(buffer, 1024);
- length = infile.gcount();
- if (length > 0)
- {
- EncodeByte((const Byte* )buffer,length);
- Final();
- }
- }
- infile.close();
- string strMD5 = ByteToHexString(m_Result,16);
- return strMD5;
- }
- void CMessageDigestAlgorithm5::EncodeByte(const Byte* input, size_t length)
- {
- unsigned int index, partLen;
- size_t i;
- index = static_cast<unsigned < span="" style="word-wrap: break-word;">int>((m_Count[0] >> 3) & 0x3f);//转换成字节mod64
- m_Count[0] += (static_cast<unsigned < span="" style="word-wrap: break-word;">int>(length) << 3);//bit数
- if (m_Count[0] < (static_cast<unsigned < span="" style="word-wrap: break-word;">int>(length) << 3))
- {
- ++m_Count[1];
- }
- m_Count[1] += (static_cast<unsigned < span="" style="word-wrap: break-word;">int>(length) >> 29);//
- partLen = 64 - index;
- if (length >= partLen)
- {
- memcpy(&m_Buffer[index], input, partLen);
- ProcessOfMDA5(m_Buffer);
- for (i = partLen; i + 63 < length; i += 64)
- {
- ProcessOfMDA5(&input[i]);
- }
- index = 0;
- }
- else
- {
- i = 0;
- }
- memcpy(&m_Buffer[index], &input[i], length - i);
- }
- void CMessageDigestAlgorithm5::Final()
- {
- Byte bits[8];
- unsigned int tempChainingVariable[4],tempCount[2];
- unsigned int index, padLen;
- memcpy(tempChainingVariable, m_ChainingVariable, 16);
- memcpy(tempCount, m_Count, 8);
- UnsignedIntToByte(m_Count, bits, 8);
- index = static_cast<unsigned < span="" style="word-wrap: break-word;">int>((m_Count[0] >> 3) & 0x3f);
- padLen = (index < 56) ? (56 - index) : (120 - index);
- EncodeByte(g_Padding, padLen);
- EncodeByte(bits, 8);
- UnsignedIntToByte(m_ChainingVariable,m_Result, 16);
- memcpy(m_ChainingVariable, tempChainingVariable, 16);
- memcpy(m_Count,tempCount, 8);
- }
五、说明
对于MD5算法,不同的读取格式产生的字节流是不一样的,而且涉及计算可能需要数据格式转换,如把bit转换成一定的整型数据方便计算,
因此,不同MD5算法实现版本算出的结果可能有很大不一样。
因此,我觉得最好多次计算的MD5算法版本一致。关于MD5算法,有一个比较好的在线计算工具,点击MD5在线计算器。
MD5算法是不可逆的,但是,基于键值对的字典关系原理,有一些收集海量MD5信息与摘要的数据库,采用枚举法能够从MD5值找到原文本信息,
提供一个类似的工具,点击MD5在线破解。此外,在此提供MD5的讨论社区,点击MD5讨论社区 。
- MD5加密
- MD5加密
- md5加密
- MD5加密
- md5加密
- MD5加密
- MD5加密
- md5 加密
- MD5加密
- md5加密
- MD5加密
- MD5加密
- MD5加密
- MD5加密
- MD5加密
- MD5加密
- MD5加密
- MD5加密
- html a标签img标签的认识
- 2-3-4树和红黑树
- 贝塞尔曲线
- KVO、KVC的实现原理与应用
- iTunes Connect 上架 -- App store 搜索不到 解决方法
- MD5加密
- P数序列
- sklearn模型保存(pickle模块和joblib模块)
- 实习小记 用list来免去查询数据时打开数据库链接所占用的资源
- 如何提高编译snap应用的速度
- Redis简介
- 不同格式 图片间的 相互转换!
- 记录当时从程序员转行做业务
- 计算机操作系统---1:操作系统引论