MD5加密算法(C++版)

此算法使用C++写成。更多详细内容可参考GitHub项目

模块分解

①填充字符串函数:在长度为K bits的原始消息尾部填充长度为P bits的标识(1000…00),其中1 <= P <= 512(即至少需要填充一个bit),使得填充后的消息位数为 K+P ≡ 448(mod 512)。注意,当K ≡ 448(mod 512)时,填充的字节数 P = 512 bit。填充得到上述消息后,在尾部附加K值的低64位,最后得到一个长度为 K+P+64 ≡ 0(mod 512)的消息。

②字符串分块函数:将填充好的字符串分割成L个长度为512bit的分组

③循环压缩函数:对每个512-bit分组进行64轮迭代运算
(1)对分组(A,B,C,D)中的A进行迭代运算
公式为:A <= B + ((A + g(B,C,D) + X[k] + T[i])) << S[i]
其中:
· A,B,C,D代表MD5缓冲区当前的数值
· g为轮函数,1-16轮迭代使用F函数,17-32轮迭代使用G函数,33-48轮迭 代使用H函数,49-64轮迭代使用I函数
· X[k]代表当前处理消息分组的第k个32位字,X[k]由第n轮迭代对应的顺序表决定
· T[i]代表T表的第i项的值,T[i] = int(2^32 * |sin(i)|)
· S[i]对应第i轮的左循环移位的s值
(2)对分组(A,B,C,D)作循环轮换
公式为:(B,C,D,A)<=(A,B,C,D)

④MD5编码函数:用于调用前面的功能函数进行MD5编码
(1)输入待加密的明文字符串
(2)对明文字符串进行填充
(3)对填充后的明文字符串进行分块(Yq)
(4)使用预设的初始值初始化MD5缓冲区间(IV)
(5)对各个分块字符串利用公式HMD5(CVi-1, Yi)进行循环压缩,运算结果作为下一块的输入(CVi)
当所有的分块迭代完成后,输出结果CVL,L表示最后一个分块的序号

循环压缩函数迭代部分的步骤分解

1. 64轮迭代

在这里插入图片描述

2. 单次迭代的计算步骤

在这里插入图片描述

3. 4轮循环所使用的生成函数

在这里插入图片描述

C++代码

#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>

using namespace std;

#define A 0x67452301
#define B 0xefcdab89
#define C 0x98badcfe
#define D 0x10325476

const char str16[] = "0123456789abcdef";

const unsigned int T[] = {
    0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,
    0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,
    0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,
    0x6b901122,0xfd987193,0xa679438e,0x49b40821,
    0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,
    0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,
    0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,
    0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a,
    0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,
    0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,
    0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,
    0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,
    0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,
    0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1,
    0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,
    0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391 };

const unsigned int s[] = { 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,
                           5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
                           4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,
                           6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21};
class MD5 {
private:
    unsigned int tempA, tempB, tempC, tempD, strlength;
public:
    MD5() {
        tempA = A;
        tempB = B;
        tempC = C;
        tempD = D;
        strlength = 0;
    }
    // F函数
    unsigned int F(unsigned int b, unsigned int c, unsigned int d) {
        return (b & c) | ((~b) & d);
    }
    // G函数
    unsigned int G(unsigned int b, unsigned int c, unsigned int d) {
        return (b & d) | (c & (~d));
    }
    // H函数
    unsigned int H(unsigned int b, unsigned int c, unsigned int d) {
        return b ^ c ^ d;
    }
    // I函数
    unsigned int I(unsigned int b, unsigned int c, unsigned int d) {
        return c ^ (b | (~d));
    }
    // 移位操作函数
    unsigned int shift(unsigned int a, unsigned int n) {
        return (a << n) | (a >> (32 - n));
    }
    // 编码函数
    string encode(string src) {
        vector<unsigned int> rec = padding(src);
        for(unsigned int i = 0; i < strlength/16; i++) {
            unsigned int num[16];
            for(int j = 0; j < 16; j++) {
                num[j] = rec[i*16+j];
            }
            iterateFunc(num, 16);
        }
        return format(tempA) + format(tempB) + format(tempC) + format(tempD);
    }
    // 循环压缩
    void iterateFunc(unsigned int* X, int size = 16) {
        unsigned int a = tempA,
                     b = tempB,
                     c = tempC,
                     d = tempD,
                     rec = 0,
                     g, k;
        for(int i = 0; i < 64; i++) {
            if(i < 16) {
                // F迭代
                g = F(b, c, d);
                k = i;
            }
            else if(i < 32) {
                // G迭代
                g = G(b, c, d);
                k = (1 + 5*i) % 16;
            }
            else if(i < 48) {
                // H迭代
                g = H(b, c, d);
                k = (5 + 3*i) % 16;
            }
            else {
                // I迭代
                g = I(b, c, d);
                k = (7*i) % 16;
            }
            rec = d;
            d = c;
            c = b;
            b = b + shift(a + g + X[k] + T[i], s[i]);
            a = rec;
        }
        tempA += a;
        tempB += b;
        tempC += c;
        tempD += d;
    }
    // 填充字符串
    vector<unsigned int> padding(string src) {
        // 以512位,64个字节为一组
        unsigned int num = ((src.length() + 8) / 64) + 1;
        vector<unsigned int> rec(num*16);
        strlength = num*16;
        for(unsigned int i = 0; i < src.length(); i++){
            // 一个unsigned int对应4个字节,保存4个字符信息
            rec[i>>2] |= (int)(src[i]) << ((i % 4) * 8);
        }
        // 补充1000...000
        rec[src.length() >> 2] |= (0x80 << ((src.length() % 4)*8));
        // 填充原文长度
        rec[rec.size()-2] = (src.length() << 3);
        return rec;
    }
    // 整理输出
    string format(unsigned int num) {
        string res = "";
        unsigned int base = 1 << 8;
        for(int i = 0; i < 4; i++) {
            string tmp = "";
            unsigned int b = (num >> (i * 8)) % base & 0xff;
            for(int j = 0; j < 2; j++) {
                tmp = str16[b%16] + tmp;
                b /= 16;
            }
            res += tmp;
        }
        return res;
    }
};

int main() {
    MD5 test;
    string a = "";
    cout << "Plain Text: ";
    getline(cin,a);
    cout << "result: " << test.encode(a) << endl;
}
  • 19
    点赞
  • 76
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZTao-z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值