MD5的C++实现

放一波代码吧,MD5已经不是检查数据完整性的最佳选择了QAQ(但是有一定的教学意义)
基本原理网上都有,这份代码核心部分(压缩函数)也是从cryptopp搞来的,其他的填充啥的自己写的。就…称我为缝合怪吧hhh

注:由于填充过程是对整个数据读进内存然后进行的填充,所以计算大文件Hash时悠着点啊,内存炸了别赖我

md5.h

#ifndef MD5_H
#define MD5_H

#include<iostream>

using namespace std;

typedef unsigned int  uint32;
typedef unsigned char uint8;
typedef unsigned long long uint64;

#define F(b, c, d) ((b & c) | ((~b) & d))
#define G(b, c, d) ((b & d) | (c & (~d)))
#define H(b, c, d) (b ^ c ^ d)
#define I(b, c, d) (c ^ (b | ~d))
#define CLS(x, s)  ((x << s)|(x >> (32 - s)))
#define ROUND(f, w, x, y, z, data, s) \
	w = CLS(w + f(x, y, z) + data, s) + x



class MD5 {
private:
	// 4 32-bit registers
	uint32 ctx[4] = { 0x67452301L,0xefcdab89L,0x98badcfeL,0x10325476L };
	uint32* wordptr = NULL;
	uint8* byteptr = NULL;
	uint32 count = 0;
	// computer's endianess(little->false, big->true)
	bool   endian = true;;

public:
	MD5() {
		// test computer's endianess
		uint32 a = 0x01;
		uint8* b = (uint8*)&a;
		// set 'endian' flag
		if (*b == 0x01) {
			endian = false;
		}
		else if (*b == 0x00) {
			endian = true;
		}
	}
	void Load(uint8* data, uint64 len);
	void Transform();
	string GetMD5Hash(uint8* data, uint64 size);
	string GetFileMD5Hash(string filename);
};

#endif

md5.cpp

#include<iostream>
#include<fstream>
#include<math.h>
#include<windows.h>
#include"md5.h"
#include"utils.h"

void MD5::Load(uint8* data, uint64 size) {
	// get the length of data after padding
	uint64 bytelen = (size & 0x3f) < 56 ? (64 - (size & 0x3f) + size) : (64 - (size & 0x3f) + size + 64);
	// get the number of 512-bit blocks
	count = ceil((double)bytelen / 64);
	// create a new array
	wordptr = (uint32*)malloc(bytelen);
	if (wordptr != NULL) {
		byteptr = (uint8*)wordptr;
		// set zeros
		memset(wordptr, 0x00, bytelen);
		// copy 'data' to 'wordptr'/'byteptr' 
		memcpy(byteptr, data, size);
		// add 0x80
		*(byteptr + size) = 0x80;
		// add data's length
		if (endian == true) {
			// big-endian
			*(uint64*)(wordptr + bytelen / 4 - 2) = EndianTransfrom(size << 3);
		}
		else {
			// little-endian
			*(uint64*)(wordptr + bytelen / 4 - 2) = size << 3;
		}

	}
	return;
}

void MD5::Transform() {
	uint32 tmp, a, b, c, d;
	for (register int i = 0; i < count; i++) {
		int offset = i << 4;
		a = ctx[0]; b = ctx[1]; c = ctx[2]; d = ctx[3];

		ROUND(F, a, b, c, d, wordptr[offset + 0] + 0xd76aa478, 7);
		ROUND(F, d, a, b, c, wordptr[offset + 1] + 0xe8c7b756, 12);
		ROUND(F, c, d, a, b, wordptr[offset + 2] + 0x242070db, 17);
		ROUND(F, b, c, d, a, wordptr[offset + 3] + 0xc1bdceee, 22);
		ROUND(F, a, b, c, d, wordptr[offset + 4] + 0xf57c0faf, 7);
		ROUND(F, d, a, b, c, wordptr[offset + 5] + 0x4787c62a, 12);
		ROUND(F, c, d, a, b, wordptr[offset + 6] + 0xa8304613, 17);
		ROUND(F, b, c, d, a, wordptr[offset + 7] + 0xfd469501, 22);
		ROUND(F, a, b, c, d, wordptr[offset + 8] + 0x698098d8, 7);
		ROUND(F, d, a, b, c, wordptr[offset + 9] + 0x8b44f7af, 12);
		ROUND(F, c, d, a, b, wordptr[offset + 10] + 0xffff5bb1, 17);
		ROUND(F, b, c, d, a, wordptr[offset + 11] + 0x895cd7be, 22);
		ROUND(F, a, b, c, d, wordptr[offset + 12] + 0x6b901122, 7);
		ROUND(F, d, a, b, c, wordptr[offset + 13] + 0xfd987193, 12);
		ROUND(F, c, d, a, b, wordptr[offset + 14] + 0xa679438e, 17);
		ROUND(F, b, c, d, a, wordptr[offset + 15] + 0x49b40821, 22);

		ROUND(G, a, b, c, d, wordptr[offset + 1] + 0xf61e2562, 5);
		ROUND(G, d, a, b, c, wordptr[offset + 6] + 0xc040b340, 9);
		ROUND(G, c, d, a, b, wordptr[offset + 11] + 0x265e5a51, 14);
		ROUND(G, b, c, d, a, wordptr[offset + 0] + 0xe9b6c7aa, 20);
		ROUND(G, a, b, c, d, wordptr[offset + 5] + 0xd62f105d, 5);
		ROUND(G, d, a, b, c, wordptr[offset + 10] + 0x02441453, 9);
		ROUND(G, c, d, a, b, wordptr[offset + 15] + 0xd8a1e681, 14);
		ROUND(G, b, c, d, a, wordptr[offset + 4] + 0xe7d3fbc8, 20);
		ROUND(G, a, b, c, d, wordptr[offset + 9] + 0x21e1cde6, 5);
		ROUND(G, d, a, b, c, wordptr[offset + 14] + 0xc33707d6, 9);
		ROUND(G, c, d, a, b, wordptr[offset + 3] + 0xf4d50d87, 14);
		ROUND(G, b, c, d, a, wordptr[offset + 8] + 0x455a14ed, 20);
		ROUND(G, a, b, c, d, wordptr[offset + 13] + 0xa9e3e905, 5);
		ROUND(G, d, a, b, c, wordptr[offset + 2] + 0xfcefa3f8, 9);
		ROUND(G, c, d, a, b, wordptr[offset + 7] + 0x676f02d9, 14);
		ROUND(G, b, c, d, a, wordptr[offset + 12] + 0x8d2a4c8a, 20);

		ROUND(H, a, b, c, d, wordptr[offset + 5] + 0xfffa3942, 4);
		ROUND(H, d, a, b, c, wordptr[offset + 8] + 0x8771f681, 11);
		ROUND(H, c, d, a, b, wordptr[offset + 11] + 0x6d9d6122, 16);
		ROUND(H, b, c, d, a, wordptr[offset + 14] + 0xfde5380c, 23);
		ROUND(H, a, b, c, d, wordptr[offset + 1] + 0xa4beea44, 4);
		ROUND(H, d, a, b, c, wordptr[offset + 4] + 0x4bdecfa9, 11);
		ROUND(H, c, d, a, b, wordptr[offset + 7] + 0xf6bb4b60, 16);
		ROUND(H, b, c, d, a, wordptr[offset + 10] + 0xbebfbc70, 23);
		ROUND(H, a, b, c, d, wordptr[offset + 13] + 0x289b7ec6, 4);
		ROUND(H, d, a, b, c, wordptr[offset + 0] + 0xeaa127fa, 11);
		ROUND(H, c, d, a, b, wordptr[offset + 3] + 0xd4ef3085, 16);
		ROUND(H, b, c, d, a, wordptr[offset + 6] + 0x04881d05, 23);
		ROUND(H, a, b, c, d, wordptr[offset + 9] + 0xd9d4d039, 4);
		ROUND(H, d, a, b, c, wordptr[offset + 12] + 0xe6db99e5, 11);
		ROUND(H, c, d, a, b, wordptr[offset + 15] + 0x1fa27cf8, 16);
		ROUND(H, b, c, d, a, wordptr[offset + 2] + 0xc4ac5665, 23);

		ROUND(I, a, b, c, d, wordptr[offset + 0] + 0xf4292244, 6);
		ROUND(I, d, a, b, c, wordptr[offset + 7] + 0x432aff97, 10);
		ROUND(I, c, d, a, b, wordptr[offset + 14] + 0xab9423a7, 15);
		ROUND(I, b, c, d, a, wordptr[offset + 5] + 0xfc93a039, 21);
		ROUND(I, a, b, c, d, wordptr[offset + 12] + 0x655b59c3, 6);
		ROUND(I, d, a, b, c, wordptr[offset + 3] + 0x8f0ccc92, 10);
		ROUND(I, c, d, a, b, wordptr[offset + 10] + 0xffeff47d, 15);
		ROUND(I, b, c, d, a, wordptr[offset + 1] + 0x85845dd1, 21);
		ROUND(I, a, b, c, d, wordptr[offset + 8] + 0x6fa87e4f, 6);
		ROUND(I, d, a, b, c, wordptr[offset + 15] + 0xfe2ce6e0, 10);
		ROUND(I, c, d, a, b, wordptr[offset + 6] + 0xa3014314, 15);
		ROUND(I, b, c, d, a, wordptr[offset + 13] + 0x4e0811a1, 21);
		ROUND(I, a, b, c, d, wordptr[offset + 4] + 0xf7537e82, 6);
		ROUND(I, d, a, b, c, wordptr[offset + 11] + 0xbd3af235, 10);
		ROUND(I, c, d, a, b, wordptr[offset + 2] + 0x2ad7d2bb, 15);
		ROUND(I, b, c, d, a, wordptr[offset + 9] + 0xeb86d391, 21);

		ctx[0] += a; ctx[1] += b; ctx[2] += c; ctx[3] += d;
	}
}

string MD5::GetMD5Hash(uint8* data, uint64 size) {
	Load(data, size);
	Transform();
	free(byteptr);
	return bytesToHexString((uint8*)ctx, 16);
}

string MD5::GetFileMD5Hash(string filename) {
	// get file's size
	ifstream fin(filename, ios::in | ios::binary);
	fin.seekg(0, ios::end);
	uint64 size = fin.tellg();
	fin.seekg(0, ios::beg);

	// initialize timer's variables
	LARGE_INTEGER cpuFreq, startTime, endTime;
	double  runtime;
	QueryPerformanceFrequency(&cpuFreq);
	QueryPerformanceCounter(&startTime);

	// read data
	uint8* data = (uint8*)malloc(size);
	memset(data, 0, size);
	fin.read((char*)data, size);
	fin.close();

	// compute hash and test md5's speed
	QueryPerformanceCounter(&startTime);
	string result = GetMD5Hash(data, size);
	QueryPerformanceCounter(&endTime);
	runtime = (((endTime.QuadPart - startTime.QuadPart) * 1.0f) / cpuFreq.QuadPart);
	printf("MD5 Speed: %lf MB/s\n", size * 1.0 / runtime / 1024 / 1024);

	free(data);
	return result;
}

上一篇:fork函数详解(附代码)


下一篇:C# Sqlite数据类型