使用C++
实现md5算法
#include <iostream>
#include <string>
#include <cmath>
#include <fstream>
using namespace std;
typedef unsigned char byte;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef uint (*func) (uint, uint, uint);
class Md5 {
public:
// 加密字符串
string encryption(string s){
return encryption((byte *)s.c_str(), s.size());
}
// 加密byte
string encryption(byte *text, uint len){
init();
encryption_byte(text, len);
encryption_last();
return byte_to_hex_string(result, 16);
}
// 加密文件
string encryption_file(string file_name){
ifstream fin(file_name);
char buf[1024];
init();
while(!fin.eof()){
fin.read(buf, 1024);
streamsize len = fin.gcount();
if(len) encryption_byte((byte *)buf, len);
}
encryption_last();
fin.close();
return byte_to_hex_string(result, 16);
}
private:
inline void init(){
memcpy(chunk, CHUNK, sizeof CHUNK);
length = 0ULL;
}
static inline uint F(uint x, uint y, uint z){
return x & y | ~x & z;
}
static inline uint G(uint x, uint y, uint z){
return x & z | ~z & y;
}
static inline uint H(uint x, uint y, uint z){
return x ^ y ^ z;
}
static inline uint I(uint x, uint y, uint z){
return y ^ (~z | x);
}
static inline uint left_shit(uint num, uint bits){
return num << bits | num >> 32 - bits;
}
static inline void convert(uint (*f)(uint, uint, uint), uint &a, uint &b, uint &c, uint &d, uint m, uint t, uint s){
a = b + left_shit(a + f(b, c, d) + m + t, s);
}
static inline void byte_to_uint(const byte *src, uint *dst, uint len){
for(uint i = 0, j = 0; i < len; i += 4)
dst[j++] = src[i] | (uint)src[i+1] << 8 | (uint)src[i+2] << 16 | (uint)src[i+3] << 24;
}
static inline void uint_to_byte(uint *src, byte *dst, uint len){
for(uint i = 0, j = 0; i < len; ++i)
for (int k = 0; k < 30; k += 8)
dst[j++] = src[i] >> k & 0xff;
}
static inline void ull_to_byte(ull src, byte *dst){
for(uint i = 0; i < 60; i += 8)
dst[i>>3] = src >> i & 0xff;
}
static inline char byte_to_hex(uint c){
if(c <= 9) return c + '0';
return c - 10 + 'A';
}
static inline string byte_to_hex_string(byte *s, uint len){
string res = "";
for(uint i = 0; i < len; ++i){
res.push_back(byte_to_hex(s[i]>>4));
res.push_back(byte_to_hex(s[i]&0x0f));
}
return res;
}
// 把data进行加密的过程,每次只能加密512bits
void md5_process(const byte* data){
uint a[4];
memcpy(a, chunk, sizeof chunk);
uint m[16];
uint sin_count = 0;
byte_to_uint(data, m, 64);
// 64次转换
for(int i = 0; i < 4; ++i)
for(int j = 16; j; --j)
convert(A_F[i], a[j&0x03], a[j+1&0x03], a[j+2&0x03], a[j+3&0x03], m[M_INDEX[i][16-j]], (0x100000000UL)*abs(sin(++sin_count)), S[i][16-j&0x03]);
// 更新chunk
for(int i = 0; i < 4; ++i)
chunk[i] += a[i];
}
// 在前面的基础上加密data数据,
void encryption_byte(const byte *data, uint len){
// 计算多余长度
uint index = length >> 3 & 0x3f;
length += len << 3;
// 计算在buffer中的位置
uint det = 64 - index;
uint i = 0;
// 把data进行切片,然后进行md5加密
if(len >= det){
memcpy(buffer + index, data, det);
md5_process(buffer);
i = det;
while(i + 63 < len){
md5_process(data + i);
i += 64;
}
index = 0;
}
// data剩余的数据
memcpy(buffer + index, data + i, len - i);
}
void encryption_last(){
byte length_buffer[8];
// 获取长度的byte
ull_to_byte(length, length_buffer);
uint index = length >> 3 & 0x3f;
// 填充字符
encryption_byte(FILL_DATA, index < 56 ? 56 - index : 120 - index);
encryption_byte(length_buffer, 8);
// 转成16进制
uint_to_byte(chunk, result, 16);
}
private:
static const uint CHUNK[4];
static const uint S[4][4];
static const func A_F[4];
static const byte FILL_DATA[64];
static const uint M_INDEX[4][16];
uint chunk[4];
byte result[16];
byte buffer[64];
ull length;
};
const uint Md5::CHUNK[4] = {0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476};
const uint Md5::S[4][4] = {
{7, 12, 17, 22},
{5, 9, 14, 20},
{4, 11, 16, 23},
{6, 10, 15, 21}
};
const byte Md5::FILL_DATA[64] = {0x80};
const func Md5::A_F[4] = {F, G, H, I};
const uint Md5::M_INDEX[4][16] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
{ 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12 },
{ 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2 },
{ 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 }
};