我实现的一个MD5代码,C/C++版本

本文详细介绍了MD5加密算法的实现原理,包括填充、循环移位等关键步骤,并展示了如何使用MD5进行字符串加密。同时,阐述了MD5在实际应用中的安全性考虑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#ifndef YMD5_H_
#define YMD5_H_

#include <string>
using std::string;

namespace yyy {

typedef unsigned int uint32;

class MD5 {
public:
  static string Md5(const string& s);
  static char*  Md5(char* r, const char* s);

private:
//对数组做填充
  static size_t AppendString(char* buf, size_t textlen);
//四轮处理
  static void FourRoundRun(uint32 res[], const char* buf);
//数组中的每个gn[i][j]元素通过公式: 2 * sin(16* 1) 32 i + j + 计算后取整得到
  static uint32 gn[4][16];
//做循环移位的步数  
  static int move[4][16];
};

}

#endif
#include "YMd5.h"
#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;

namespace yyy {

//四个逻辑函数,用函数指针数组组织
static inline uint32 F(uint32 x, uint32 y, uint32 z) { return (x&y)|((~x)&z);}
static inline uint32 G(uint32 x, uint32 y, uint32 z) { return (x&z)|(y&(~z));}
static inline uint32 H(uint32 x, uint32 y, uint32 z) { return x^y^z;}
static inline uint32 I(uint32 x, uint32 y, uint32 z) { return y^(x|(~z));}
typedef uint32 (*P_FUN)(uint32 x, uint32 y, uint32 z);
P_FUN pfun[4] = {F, G, H, I};

//将整数x循环左移n位
static inline uint32 CirLeftMove(uint32 x, int n) { return (x<<n)|((x&0xffffffff)>>(32-n)); }

//将buf从start开始的offset个字节内存赋值到a这个uint数组,要求a的长度是offset/4(向上取整)
static inline void Char2Uint(uint32 a[], const char* buf, const int len) { memcpy(a, buf, len); }

//将a从start开始的offset个整数内存赋值到buf这个字符串,要求buf的长度是4*offset
static inline char* Uint2Char(char* buf, const uint32 a[], const int offset) { memcpy(buf, a, offset*4); }

//将a数组,按16进制输出成字符串数组,输入buf长度大于32+1,函数里面不作检查
static const char int2hex[17] = {'0', '1', '2', '3', '4', '5', '6', '7', 
			   '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
static inline char* Uint2HexString(char* buf, const uint32 a[], const int len) {
  int i = -1;
  for (int j = 0; j < len; ++j) {
    buf[++i] = int2hex[(a[j] >>  4) & 0xf];
    buf[++i] = int2hex[(a[j] >>  0) & 0xf];
    buf[++i] = int2hex[(a[j] >> 12) & 0xf];
    buf[++i] = int2hex[(a[j] >>  8) & 0xf];
    buf[++i] = int2hex[(a[j] >> 20) & 0xf];
    buf[++i] = int2hex[(a[j] >> 16) & 0xf];
    buf[++i] = int2hex[(a[j] >> 28) & 0xf];
    buf[++i] = int2hex[(a[j] >> 24) & 0xf];
  }
  buf[++i] = 0;
  return buf;
}

int MD5::move[4][16] = {
  { 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 }};

uint32 MD5::gn[4][16] = {
  { 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 }};

#define J_TO_I(i, j) {\
  if (r == 0) i = j & 0xf; \
  else if (r == 1) i = (1+5*j) & 0xf; \
  else if (r == 2) i = (5+3*j) & 0xf; \
  else if (r == 3) i = (7*j) & 0xf; \
}

inline void MD5::FourRoundRun(uint32 res[], const char * buf) {
  uint32 a[16];
  Char2Uint(a, buf, 64);

  uint32 tmp_res[4];
  memcpy(tmp_res, res, sizeof(res)*4);

  for(int r = 0; r < 4; ++r) {
    for (int j = 0; j < 16; ++j) {
      int i = 0;
      J_TO_I(i, j);
      tmp_res[0] = tmp_res[1] + CirLeftMove(tmp_res[0] + (*(pfun[r]))(tmp_res[1], tmp_res[2], tmp_res[3]) + a[i] + gn[r][j], move[r][j]);

      int tmp = tmp_res[3];
      tmp_res[3] = tmp_res[2];
      tmp_res[2] = tmp_res[1];
      tmp_res[1] = tmp_res[0];
      tmp_res[0] = tmp;
    }
  }
  res[0] += tmp_res[0];
  res[1] += tmp_res[1];
  res[2] += tmp_res[2];
  res[3] += tmp_res[3];
}

char* MD5::Md5(char* r, const char* s) {
  uint32 temp[4], result[4] = { 0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476 };
  const size_t BUFLEN = 64;
  char buf[BUFLEN*2+1];
  size_t offset = 0, len = 0;
  memcpy(temp, result, sizeof(result));

  bool end = false;
  while (!end) {
    strncpy(buf, s+offset, BUFLEN);
    buf[BUFLEN] = 0;
    len = strlen(buf);
    offset += len;
    if (len < BUFLEN) {
      len = AppendString(buf, strlen(s));
      end = true;
    }
    if (len == 64) {
      FourRoundRun(result, buf); 
    } else if (len == 128) {
      FourRoundRun(result, buf);
      FourRoundRun(result, buf+BUFLEN);
    }
  }
  strcpy(r, Uint2HexString(buf, result, 4));
  return r;
}

string MD5::Md5(const string& s) {
  char res[33];
  Md5(res, s.c_str());
  return string(res);
}

inline size_t MD5::AppendString(char* buf, size_t textlen) { //这里必须保证使用的buf有(64*2+1)byte的长度
  size_t append_len, retlen, len = strlen(buf);
  size_t res = len&0x3f;
  if (res >= 56) {
    append_len = 64 - res + 56;
    retlen = 128;
  } else if (res < 56) {
    append_len = 56 - res;
    retlen = 64;
  } 
  *(buf+len) = 0x80;
  memset(buf+len+1, 0, append_len-1);
  textlen *= 8;//转换成bit长度
  memcpy(buf+len+append_len, &textlen, sizeof(size_t));
  return retlen;
}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值