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

#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;
}

}


这是一个简单的 C++ 实现 MD5 算法的代码示例: ```cpp #include <iostream> #include <cstring> #include <cstdio> using namespace std; typedef unsigned int uint32_t; // 左移位数表 const uint32_t S[] = { 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22 }; // 常数表 const uint32_t K[] = { 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 uint32_t shift_table[] = { 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, 9, 14, 0, 4, 11, 15, 3, 8, 9, 14, 5, 12, 2, 7, 10, 0, 6, 13, 15, 9, 11, 3, 8, 12, 2, 7, 1 }; // 左移函数 inline uint32_t left_rotate(uint32_t x, uint32_t c) { return (x << c) | (x >> (32 - c)); } void md5(uint32_t *input, uint32_t length, uint32_t *digest) { // 初始化 uint32_t A = 0x67452301; uint32_t B = 0xefcdab89; uint32_t C = 0x98badcfe; uint32_t D = 0x10325476; for (uint32_t i = 0; i < length; i += 16) { uint32_t a = A, b = B, c = C, d = D; uint32_t *chunk = input + i; // 循环压缩 for (uint32_t j = 0; j < 64; j++) { uint32_t F, g; if (j < 16) { F = (B & C) | ((~B) & D); g = j; } else if (j < 32) { F = (D & B) | ((~D) & C); g = (5 * j + 1) % 16; } else if (j < 48) { F = B ^ C ^ D; g = (3 * j + 5) % 16; } else { F = C ^ (B | (~D)); g = (7 * j) % 16; } uint32_t temp = D; D = C; C = B; B = B + left_rotate((a + F + K[j] + chunk[g]), S[j]); a = temp; } A += a; B += b; C += c; D += d; } digest[0] = A; digest[1] = B; digest[2] = C; digest[3] = D; } int main() { char *str = "hello, world!"; uint32_t len = strlen(str); uint32_t *input = new uint32_t[(len + 8) / 4]; memcpy(input, str, len); input[len / 4] |= 0x80 << ((len % 4) * 8); input[(len + 8) / 4 - 2] = len * 8; uint32_t digest[4]; md5(input, (len + 64) / 64 * 16, digest); printf("%08x%08x%08x%08x\n", digest[0], digest[1], digest[2], digest[3]); delete[] input; return 0; } ``` 这个程序计算字符串 "hello, world!" 的 MD5 值,并输出结果。注:这个实现并没有对输入进行预处理,而是直接将其视为一连串的 8 位字符。在实际使用中,需要对输入进行填充和预处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值