zoukankan      html  css  js  c++  java
  • c++实现md5加密

    最近发现md5加密算法挺有趣,特点是单向加密不可逆,加密后的字符串长度相等,于是就用C++尝试实现了一下

    头文件定义

    
    
     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 * abs(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 * abs(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 * abs(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 * abs(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

  • 相关阅读:
    android滤镜效果
    Android ListView的OnItemClickListener详解
    Categories
    利用Stack倒序List,利用Set使List不能添加重复元素
    IOS数据类型对应输出格式
    win7的dropbox无法启动 重新安装也没用
    记一次datatable的删除操作
    winform动态创建radio以及使用委托判断哪个选中
    临时表列的长度
    退出winform应用程序
  • 原文地址:https://www.cnblogs.com/knight-monkey/p/knight_201604130940_study.html
Copyright © 2011-2022 走看看