md5演算法 C++ 實現
阿新 • • 發佈:2020-12-21
#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 } };