MD5加密c++版

很久之前就对md5很好奇,抽空研究了一下,算法过程还是挺简单的,为什么是这个过程就不是我辈能参透的了。自己写了个c++版本的,希望对md5好奇的朋友们有帮助。
md5.h

#include <string>

typedef unsigned int uint;

class MD5
{
public:
	MD5();
	std::string md5(std::string str);
	uint turnhex(uint);

private:
	uint m_k[64];
	uint m_a;
	uint m_b;
	uint m_c;
	uint m_d;
	static uint m_r[64];

};


md5.cpp

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <iostream>

#include "md5.h"

using namespace std;

uint MD5::m_r[64] = 
{
	7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 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, 6, 10, 15, 21, 6, 10, 15, 21
};

MD5::MD5()
{
	m_a = 0x67452301;
	m_b = 0xEFCDAB89;
	m_c = 0x98BADCFE;
	m_d = 0x10325476;
	for(int i = 0; i < 64; i++)
	{
		m_k[i] = 4294967296.0 * fabs(sin(i + 1));
	}
}

string MD5::md5(string str)
{
	int x = str.length() / 64;
	int y = str.length() % 64;
	int z;
	if(y > 56)
	{
		z = 64 * (x + 2);
	}
	else
	{
		z = 64 * (x + 1);
	}
	//上面计算出填充后的字节数z,然后开辟z字节的空间
	void *tmp = malloc(z);
	memset(tmp, 0, z);
	strcpy((char *)tmp, str.c_str());
	//在原字符串后第一个bit加个1然后若干个0,这里是指的都是bit
	*((unsigned char *)tmp + str.length()) = (unsigned char)(0x1 << 7);

	//转成uint型数据,在下面的循环计算中使用,z /= 4后即uint型数组w的大小
	uint *w = (uint *)tmp;
	z /= 4;
	//在数组的最后两位用以64位数据记录原字符串的bit长度
	*((unsigned __int64 *)(w) + z / 2 - 1) = str.length() * 8;

	uint h0 = m_a;
	uint h1 = m_b;
	uint h2 = m_c;
	uint h3 = m_d;
	//对w数组每16个数据为一段,进行一次计算
	for(int k = 0; k < z; k += 16)
	{
		uint a = h0;
		uint b = h1;
		uint c = h2;
		uint d = h3;
		for(int i = 0; i < 64; i++)
		{
			uint f, g;
			if(i < 16)
			{
				f = b & c | ~b & d;
				g = i;
			}
			else if(i < 32)
			{
				f = d & b | ~d & c;
				g = (5 * i + 1) % 16;
			}
			else if(i < 48)
			{
				f = b ^ c ^ d;
				g = (3 * i + 5) % 16;
			}
			else
			{
				f = c ^ (b | ~d);
				g = (7 * i) % 16;
			}
			//对于每个a,b,c,d通过计算得到temp
			uint temp = a + f + w[k + g] + m_k[i];
			temp = (temp << m_r[i] | temp >> (32 - m_r[i])) + b;
			//下面可以理解成先a = temp
			//然后a,b,c,d的循环换一下位置作为下一次计算的初值
			a = d;
			d = c;
			c = b;
			b = temp;
		}
		h0 += a;
		h1 += b;
		h2 += c;
		h3 += d;
	}
	free(tmp);
	char md5_str[33];
	sprintf(md5_str, "%08x%08x%08x%08x", turnhex(h0), turnhex(h1), \
			turnhex(h2), turnhex(h3));
	return md5_str;
}

uint MD5::turnhex(uint hex)
{
	uint ret = hex & 0xff;
	ret = ret << 8 | hex >> 8 & 0xff;
	ret = ret << 8 | hex >> 16 & 0xff;
	ret = ret << 8 | hex >> 24 & 0xff;
	return ret;
}

int main()
{
	MD5 md5;
	string str;
	while(cin >> str)
	{
		cout << md5.md5(str) << endl;
	}
	return 0;
}

代码简要说明:

MD5::MD5();对加密算法中每次都使用到的变量m_k[i], m_a, m_b, m_c, m_d进行初始化
uint MD5::turnhex(uint hex);如果hex = 0xaabbccdd;则turnhex(hex) == 0xddccbbaa;
unsigned __int64如果编译器不支持可以换成unsigned long long

参考资料:

百度百科 维基百科

发表评论?

2 条评论。

  1. 几年前写过一个用wxwidget库做界面的,不过用的是des算法,似乎比你的复杂一点

发表评论