最近发现md5加密算法挺有趣,特点是单向加密不可逆,加密后的字符串长度相等,于是就用C++尝试实现了一下
最近有网友反馈加密结果不一致的问题,于是进一步来回顾了一下6年前写的这篇博客,发现的问题:此程序,在windows下vs编译运行正常,但是在linux平台下(测试环境为64位 ubuntu1804),同样的代码运行的结果却不一样,经过调试发现,原来是因为abs这个库函数,linux默认用的返回值为int类型的abs函数,vs下默认是double类型的,默认用的版本不一样,于是,将abs和sin函数统一使用std命名空间下的,经过测试,结果一致!大家以后也要养成良好习惯,不要再次踩入我6年前的这个错误,标准库函数统一使用std命名空间,可参考google c++编码规范!
网友反应出来的中文不一致的问题,是因为,windows下默认使用gbk编码,而llinux下使用的utf8,网页上的在线md5加密,中文也是utf8格式的,所以导致vs或者windows下可能中文的md5码和网上看到的不一样!如果是在windows平台上,包含中文的字符串,需要确认自己的字符串编码是否为utf8格式,如果不是,windows下需要将gbk编码转为utf8格式,这个使用windows.h这个头文件里的MultiByteToWideChar 这个系统api可以实现转换,从而结果实现一致(这个我本地今天[2022月06月19日 17:35] 已经测试验证过,windows下vs2017,linux下对应为ubuntu1804,vscode编译调试,三者环境下,加密所得的md5码,和在线md5加密结果最终是一致,包换中文的字符串加密结果,三个平台也是一致的!关于windows下gbk转utf8编码的博客也很多,需要的可以自行学习参考一下,我这里就不发出来了!
头文件定义
1 /*
2 *******************************************************
3 * brief: md5 encryption
4 * author: Monkey.Knight
5 *******************************************************
6 */
7
8 #ifndef __MD5_ENCODE_H__
9 #define __MD5_ENCODE_H__
10
11 // std
12 #include <string>
13
14 // define
15 #define UInt32 unsigned int
16 #define BIT_OF_BYTE 8
17 #define BIT_OF_GROUP 512
18 #define SRC_DATA_LEN 64
19
20 // 四个非线性函数宏定义
21 #define DEF_F(X, Y, Z ) ((( (X) & (Y) )|((~X)&(Z))))
22 #define DEF_G(X, Y, Z) (((X)&(Z))|((Y)&(~Z)))
23 #define DEF_H(X, Y, Z) ((X)^(Y)^(Z))
24 #define DEF_I(X, Y, Z) ((Y)^((X)|(~Z)))
25
26 // 求链接数函数宏定义
27 #define FF(a, b, c, d, Mj, s, ti) (a = b + CycleMoveLeft((a + DEF_F(b,c,d) + Mj + ti),s));
28 #define GG(a, b, c, d, Mj, s, ti) (a = b + CycleMoveLeft((a + DEF_G(b,c,d) + Mj + ti),s));
29 #define HH(a, b, c, d, Mj, s, ti) (a = b + CycleMoveLeft((a + DEF_H(b,c,d) + Mj + ti),s));
30 #define II(a, b, c, d, Mj, s, ti) (a = b + CycleMoveLeft((a + DEF_I(b,c,d) + Mj + ti),s));
31
32
33 class Md5Encode {
34 public:
35 // 4轮循环算法
36 struct ParamDynamic{
37 UInt32 ua_;
38 UInt32 ub_;
39 UInt32 uc_;
40 UInt32 ud_;
41 UInt32 va_last_;
42 UInt32 vb_last_;
43 UInt32 vc_last_;
44 UInt32 vd_last_;
45 };
46 public:
47 Md5Encode() {
48 }
49 std::string Encode(std::string src_info);
50
51 protected:
52
53 UInt32 CycleMoveLeft(UInt32 src_num, int bit_num_to_move);
54 UInt32 FillData(const char *in_data_ptr, int data_byte_len, char** out_data_ptr);
55 void RoundF(char *data_512_ptr, ParamDynamic & param);
56 void RoundG(char *data_512_ptr, ParamDynamic & param);
57 void RoundH(char *data_512_ptr, ParamDynamic & param);
58 void RoundI(char *data_512_ptr, ParamDynamic & param);
59 void RotationCalculate(char *data_512_ptr, ParamDynamic & param);
60 std::string GetHexStr(unsigned int num_str);
61
62 private:
63 // 幻数定义
64 static const int kA;
65 static const int kB;
66 static const int kC;
67 static const int kD;
68 static const unsigned long long k_ti_num_integer;
69 };
70
71 #endif
源文件:
#include "md5_encode.h"
#include <iostream>
// 幻数定义
const int Md5Encode::kA = 0x67452301;
const int Md5Encode::kB = 0xefcdab89;
const int Md5Encode::kC = 0x98badcfe;
const int Md5Encode::kD = 0x10325476;
const unsigned long long Md5Encode::k_ti_num_integer = 4294967296;
// function: CycleMoveLeft
// @param src_num:要左移的数
// @param bit_num_to_move:要移动的bit位数
// @return 循环左移后的结果数
UInt32 Md5Encode::CycleMoveLeft(UInt32 src_num, int bit_num_to_move) {
UInt32 src_num1 = src_num;
UInt32 src_num2 = src_num;
if (0 >= bit_num_to_move) {
return src_num;
}
UInt32 num1 = src_num1 << bit_num_to_move;
UInt32 num2 = src_num2 >> (32 - bit_num_to_move);
return ((src_num1 << bit_num_to_move) \
| (src_num2 >> (32 - bit_num_to_move)));
}
// function: FillData
// @param in_data_ptr: 要加密的信息数据
// @param data_byte_len: 数据的字节数
// @param out_data_ptr: 填充必要信息后的数据
// return : 填充信息后的数据长度,以字节为单位
UInt32 Md5Encode::FillData(const char *in_data_ptr, int data_byte_len, char** out_data_ptr) {
int bit_num = data_byte_len*BIT_OF_BYTE;
int grop_num = bit_num / BIT_OF_GROUP;
int mod_bit_num = bit_num % BIT_OF_GROUP;
int bit_need_fill = 0;
if (mod_bit_num > (BIT_OF_GROUP - SRC_DATA_LEN)) {
bit_need_fill = (BIT_OF_GROUP - mod_bit_num);
bit_need_fill += (BIT_OF_GROUP - SRC_DATA_LEN);
}
else {
bit_need_fill = (BIT_OF_GROUP - SRC_DATA_LEN) - mod_bit_num; // 这里多加了一个BIT_OF_GROUP,避免bit_need_fill正好等于0,暂时不加
}
int all_bit = bit_num + bit_need_fill;
if (0 < bit_need_fill) {
*out_data_ptr = new char[all_bit / BIT_OF_BYTE + SRC_DATA_LEN / BIT_OF_BYTE];
memset(*out_data_ptr, 0, all_bit / BIT_OF_BYTE + SRC_DATA_LEN / BIT_OF_BYTE);
// copy data
memcpy(*out_data_ptr, in_data_ptr, data_byte_len);
// fill rest data
unsigned char *tmp = reinterpret_cast<unsigned char *>(*out_data_ptr);
tmp += data_byte_len;
// fill 1 and 0
*tmp = 0x80;
// fill origin data len
unsigned long long * origin_num = (unsigned long long *)((*out_data_ptr) + ((all_bit / BIT_OF_BYTE)));
*origin_num = data_byte_len*BIT_OF_BYTE;
}
return (all_bit / BIT_OF_BYTE + SRC_DATA_LEN / BIT_OF_BYTE);
}
void Md5Encode::RoundF(char *data_BIT_OF_GROUP_ptr, ParamDynamic & param) {
UInt32 *M = reinterpret_cast<UInt32*>(data_BIT_OF_GROUP_ptr);
int s[] = { 7, 12, 17, 22 };
for (int i = 0; i < 16; ++i) {
UInt32 ti = k_ti_num_integer * std::abs(std::sin(i + 1));
if (i % 4 == 0) {
FF(param.ua_, param.ub_, param.uc_, param.ud_, M[i], s[i % 4], ti);
}
else if (i % 4 == 1) {
FF(param.ud_, param.ua_, param.ub_, param.uc_, M[i], s[i % 4], ti);
}
else if (i % 4 == 2) {
FF(param.uc_, param.ud_, param.ua_, param.ub_, M[i], s[i % 4], ti);
}
else if (i % 4 == 3) {
FF(param.ub_, param.uc_, param.ud_, param.ua_, M[i], s[i % 4], ti);
}
}
}
void Md5Encode::RoundG(char *data_BIT_OF_GROUP_ptr, ParamDynamic & param) {
UInt32 *M = reinterpret_cast<UInt32*>(data_BIT_OF_GROUP_ptr);
int s[] = { 5, 9, 14, 20 };
for (int i = 0; i < 16; ++i) {
UInt32 ti = k_ti_num_integer * std::abs(std::sin(i + 1 + 16));
int index = (i * 5 + 1) % 16;
if (i % 4 == 0) {
GG(param.ua_, param.ub_, param.uc_, param.ud_, M[index], s[i % 4], ti);
}
else if (i % 4 == 1) {
GG(param.ud_, param.ua_, param.ub_, param.uc_, M[index], s[i % 4], ti);
}
else if (i % 4 == 2) {
GG(param.uc_, param.ud_, param.ua_, param.ub_, M[index], s[i % 4], ti);
}
else if (i % 4 == 3) {
GG(param.ub_, param.uc_, param.ud_, param.ua_, M[index], s[i % 4], ti);
}
}
}
void Md5Encode::RoundH(char *data_BIT_OF_GROUP_ptr, ParamDynamic & param) {
UInt32 *M = reinterpret_cast<UInt32*>(data_BIT_OF_GROUP_ptr);
int s[] = { 4, 11, 16, 23 };
for (int i = 0; i < 16; ++i) {
UInt32 ti = k_ti_num_integer * std::abs(std::sin(i + 1 + 32));
int index = (i * 3 + 5) % 16;
if (i % 4 == 0) {
HH(param.ua_, param.ub_, param.uc_, param.ud_, M[index], s[i % 4], ti);
}
else if (i % 4 == 1) {
HH(param.ud_, param.ua_, param.ub_, param.uc_, M[index], s[i % 4], ti);
}
else if (i % 4 == 2) {
HH(param.uc_, param.ud_, param.ua_, param.ub_, M[index], s[i % 4], ti);
}
else if (i % 4 == 3) {
HH(param.ub_, param.uc_, param.ud_, param.ua_, M[index], s[i % 4], ti);
}
}
}
void Md5Encode::RoundI(char *data_BIT_OF_GROUP_ptr, ParamDynamic & param) {
UInt32 *M = reinterpret_cast<UInt32*>(data_BIT_OF_GROUP_ptr);
int s[] = { 6, 10, 15, 21 };
for (int i = 0; i < 16; ++i) {
UInt32 ti = k_ti_num_integer * std::abs(std::sin(i + 1 + 48));
int index = (i * 7 + 0) % 16;
if (i % 4 == 0) {
II(param.ua_, param.ub_, param.uc_, param.ud_, M[index], s[i % 4], ti);
}
else if (i % 4 == 1) {
II(param.ud_, param.ua_, param.ub_, param.uc_, M[index], s[i % 4], ti);
}
else if (i % 4 == 2) {
II(param.uc_, param.ud_, param.ua_, param.ub_, M[index], s[i % 4], ti);
}
else if (i % 4 == 3) {
II(param.ub_, param.uc_, param.ud_, param.ua_, M[index], s[i % 4], ti);
}
}
}
void Md5Encode::RotationCalculate(char *data_512_ptr, ParamDynamic & param) {
if (NULL == data_512_ptr) {
return;
}
RoundF(data_512_ptr, param);
RoundG(data_512_ptr, param);
RoundH(data_512_ptr, param);
RoundI(data_512_ptr, param);
param.ua_ = param.va_last_ + param.ua_;
param.ub_ = param.vb_last_ + param.ub_;
param.uc_ = param.vc_last_ + param.uc_;
param.ud_ = param.vd_last_ + param.ud_;
param.va_last_ = param.ua_;
param.vb_last_ = param.ub_;
param.vc_last_ = param.uc_;
param.vd_last_ = param.ud_;
}
// 转换成十六进制字符串输出
std::string Md5Encode::GetHexStr(unsigned int num_str) {
std::string hexstr = "";
char szch[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
unsigned char *tmptr = (unsigned char *)&num_str;
int len = sizeof(num_str);
// 小端字节序,逆序打印
for (int i = 0; i < len; i++){
unsigned char ch = tmptr[i] & 0xF0;
ch = ch >> 4;
hexstr.append(1, szch[ch]);
ch = tmptr[i] & 0x0F;
hexstr.append(1, szch[ch]);
}
return hexstr;
}
// function: Encode
// @param src_info:要加密的信息
// return :加密后的MD5值
std::string Md5Encode::Encode(std::string src_info) {
ParamDynamic param;
param.ua_ = kA;
param.ub_ = kB;
param.uc_ = kC;
param.ud_ = kD;
param.va_last_ = kA;
param.vb_last_ = kB;
param.vc_last_ = kC;
param.vd_last_ = kD;
std::string result;
const char *src_data = src_info.c_str();
char *out_data_ptr = NULL;
int total_byte = FillData(src_data, strlen(src_data), &out_data_ptr);
//char * data_BIT_OF_GROUP = out_data_ptr;
for (int i = 0; i < total_byte / (BIT_OF_GROUP / BIT_OF_BYTE); ++i) {
char * data_BIT_OF_GROUP = out_data_ptr;
data_BIT_OF_GROUP += i*(BIT_OF_GROUP / BIT_OF_BYTE);
RotationCalculate(data_BIT_OF_GROUP, param);
}
if (NULL != out_data_ptr) {
delete[] out_data_ptr, out_data_ptr = NULL;
}
result.append(GetHexStr(param.ua_));
result.append(GetHexStr(param.ub_));
result.append(GetHexStr(param.uc_));
result.append(GetHexStr(param.ud_));
return result;
}
测试:
#include <iostream>
#include <cmath>
#include "md5_encode.h"
int main(int argc, char* argv[]) {
std::string src = "fasdfasdfasdfnmmw,enrsudfnsmndfejkjhuasdmnf";
Md5Encode encode_obj;
std::string ret = encode_obj.Encode(src);
std::cout << "info: " << src.c_str() << std::endl;
std::cout << "md5: " << ret.c_str() << std::endl;
return 0;
}
结果:
info: fasdfasdfasdfnmmw,enrsudfnsmndfejkjhuasdmnf
md5: 01109ec97162a71ca5e67b5f059c3cac
原文链接: https://www.cnblogs.com/knight-monkey/p/knight_201604130940_study.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/231841
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!