当前访客身份:游客 [ 登录 | 加入开源中国 ]

代码分享

当前位置:
代码分享 » C/C++  » 安全与加密
猫叔猫叔

MD5算法

猫叔猫叔 发布于 2016年08月21日 14时, 0评/863阅
分享到: 
收藏 +0
0
C++11 code, Linux。 本人测试PC小端字节序
标签: <无>

代码片段(4) [全屏查看所有代码]

1. [代码]main.cpp     跳至 [1] [2] [3] [全屏预览]

#include "MD5.h"
#include <cstdio>

MD5::Result hash(const char *data, size_t len, MD5& algo)
{
  MD5::Result res;
  algo.reset();
  algo.add(data, len);
  algo.finish(res);
  return res;
}
	
void hexhash(const MD5::Result& res)
{	  
  for (size_t i=0; i<res.size(); ++i)
	printf("%02x", res[i]);
  printf("\n");
}

int main(void)
{
  MD5 algo;
  
  hexhash(hash("",    0, algo));
  hexhash(hash("123", 3, algo));
  hexhash(hash("abc", 3, algo));
  
  return 0;
}

2. [代码]MD5.h     跳至 [1] [2] [3] [全屏预览]

// -*-Mode: C++;-*-
#ifndef QQ371432590_MD5_H_
#define QQ371432590_MD5_H_

#include <cstdint> // uintX_t
#include <cstddef> // size_t
#include <array>

class MD5
{
public:
  typedef char                    byte_type;
  typedef byte_type               Byte;
  typedef std::array<uint8_t, 16> result_type;
  typedef result_type             Result;
  
  void reset();
  void add(const Byte* d, size_t n);
  void add(const void* d, size_t n) {add(reinterpret_cast<const Byte*>(d), n);}
  void finish(result_type& res);
private:
  uint64_t count_;
  uint8_t buffer_[64];
  uint32_t state_[4];
};

#endif // QQ371432590_MD5_H_

3. [代码]MD5.cpp     跳至 [1] [2] [3] [全屏预览]

#include "MD5.h"
#include <endian.h> // freeBSD <sys/endian.h>
#include <cstring> // memset  memcpy

namespace {
  typedef uint32_t U32;
  typedef uint64_t U64;

  inline U32& encode(U32& x) {return x = htole32(x);}
  inline void encode(U64& x) {x = htole64(x);}
  inline void decode(U32& x) {x = htole32(x);}
  
  void MD5_transform(U32* state_, U32* x);
} // Private namespace.

void MD5::reset()
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
  enum Encode : U32 {
	state_0 = 0x67452301, state_1 = 0xefcdab89,
	state_2 = 0x98badcfe, state_3 = 0x10325476
  };
#else
  enum Encode : U32 {
   	state_0 = 0x01234567, state_1 = 0x89abcdef,
   	state_2 = 0xfedcba98, state_3 = 0x76543210
   };
#endif
  count_    = 0;
  state_[0] = Encode::state_0;
  state_[1] = Encode::state_1;
  state_[2] = Encode::state_2;
  state_[3] = Encode::state_3;
  std::memset(buffer_, 0, sizeof(buffer_));
}

void MD5::add(const Byte* cd, size_t sz)
{
  //assert(sz < (sz<<3));
  //assert(sz<<3 <= UINT64_MAX-count_);

  size_t startPos = static_cast<size_t>((count_ >> 3) & 63);
  size_t partSize = sizeof(buffer_) - startPos;
  count_ += static_cast<uint64_t>(sz << 3);

  if (sz >= partSize) {
	std::memcpy(&buffer_[startPos], cd, partSize);
	MD5_transform(state_, reinterpret_cast<U32*>(buffer_));
	sz -= partSize;
	cd += partSize;
	startPos = 0; 
	while (sz >= sizeof(buffer_)) {
	  std::memcpy(buffer_, cd, sizeof(buffer_));
	  MD5_transform(state_, reinterpret_cast<U32*>(buffer_));
	  sz -= sizeof(buffer_);
	  cd += sizeof(buffer_);
	}
  }

  std::memcpy(&buffer_[startPos], cd, sz);
}

void MD5::finish(result_type& res)
{
  size_t startPos = static_cast<size_t>((count_>>3) & 0x3f);
  buffer_[startPos++] = 0x80;
  size_t partSize = sizeof(buffer_) - startPos;
	
  if (partSize < 8) {
	std::memset(&buffer_[startPos], 0, partSize);
	MD5_transform(state_, reinterpret_cast<U32*>(buffer_));
	std::memset(buffer_, 0, sizeof(buffer_)-8);
  } else /* if (partSize >= 8) */ {
	std::memset(&buffer_[startPos], 0, partSize-8);
  }
  
  {
	auto p = reinterpret_cast<U64*>(&buffer_[sizeof(buffer_)-8]);
	*p = count_;
	encode(*p);
  }
  MD5_transform(state_, reinterpret_cast<U32*>(buffer_));

  decode(state_[0]);
  decode(state_[1]);
  decode(state_[2]);
  decode(state_[3]);
  std::memcpy(res.data(), state_, res.size());
}

namespace {
#define F1(x,y,z) (z^(x&(y^z)))
#define F2(x,y,z) F1(z,x,y)
#define F3(x,y,z) (x^y^z)
#define F4(x,y,z) (y^(x|~z))
#define ROL(x,n) ((x<<n)|(x>>(32-n)))
#define ROUND(f,a,b,c,d,x,n) (a+=(f(b,c,d)+x), a=ROL(a,n), a+=b)

  void MD5_transform(U32* state_, U32* x)
  {
	U32 a = state_[0];
	U32 b = state_[1];
	U32 c = state_[2];
	U32 d = state_[3];

	ROUND(F1, a, b, c, d, encode(x[ 0]) + 0xd76aa478,  7);
	ROUND(F1, d, a, b, c, encode(x[ 1]) + 0xe8c7b756, 12);
	ROUND(F1, c, d, a, b, encode(x[ 2]) + 0x242070db, 17);
	ROUND(F1, b, c, d, a, encode(x[ 3]) + 0xc1bdceee, 22);
	ROUND(F1, a, b, c, d, encode(x[ 4]) + 0xf57c0faf,  7);
	ROUND(F1, d, a, b, c, encode(x[ 5]) + 0x4787c62a, 12);
	ROUND(F1, c, d, a, b, encode(x[ 6]) + 0xa8304613, 17);
	ROUND(F1, b, c, d, a, encode(x[ 7]) + 0xfd469501, 22);
	ROUND(F1, a, b, c, d, encode(x[ 8]) + 0x698098d8,  7);
	ROUND(F1, d, a, b, c, encode(x[ 9]) + 0x8b44f7af, 12);
	ROUND(F1, c, d, a, b, encode(x[10]) + 0xffff5bb1, 17);
	ROUND(F1, b, c, d, a, encode(x[11]) + 0x895cd7be, 22);
	ROUND(F1, a, b, c, d, encode(x[12]) + 0x6b901122,  7);
	ROUND(F1, d, a, b, c, encode(x[13]) + 0xfd987193, 12);
	ROUND(F1, c, d, a, b, encode(x[14]) + 0xa679438e, 17);
	ROUND(F1, b, c, d, a, encode(x[15]) + 0x49b40821, 22);

	ROUND(F2, a, b, c, d, x[ 1] + 0xf61e2562,  5);
	ROUND(F2, d, a, b, c, x[ 6] + 0xc040b340,  9);
	ROUND(F2, c, d, a, b, x[11] + 0x265e5a51, 14);
	ROUND(F2, b, c, d, a, x[ 0] + 0xe9b6c7aa, 20);
	ROUND(F2, a, b, c, d, x[ 5] + 0xd62f105d,  5);
	ROUND(F2, d, a, b, c, x[10] + 0x02441453,  9);
	ROUND(F2, c, d, a, b, x[15] + 0xd8a1e681, 14);
	ROUND(F2, b, c, d, a, x[ 4] + 0xe7d3fbc8, 20);
	ROUND(F2, a, b, c, d, x[ 9] + 0x21e1cde6,  5);
	ROUND(F2, d, a, b, c, x[14] + 0xc33707d6,  9);
	ROUND(F2, c, d, a, b, x[ 3] + 0xf4d50d87, 14);
	ROUND(F2, b, c, d, a, x[ 8] + 0x455a14ed, 20);
	ROUND(F2, a, b, c, d, x[13] + 0xa9e3e905,  5);
	ROUND(F2, d, a, b, c, x[ 2] + 0xfcefa3f8,  9);
	ROUND(F2, c, d, a, b, x[ 7] + 0x676f02d9, 14);
	ROUND(F2, b, c, d, a, x[12] + 0x8d2a4c8a, 20);

	ROUND(F3, a, b, c, d, x[ 5] + 0xfffa3942,  4);
	ROUND(F3, d, a, b, c, x[ 8] + 0x8771f681, 11);
	ROUND(F3, c, d, a, b, x[11] + 0x6d9d6122, 16);
	ROUND(F3, b, c, d, a, x[14] + 0xfde5380c, 23);
	ROUND(F3, a, b, c, d, x[ 1] + 0xa4beea44,  4);
	ROUND(F3, d, a, b, c, x[ 4] + 0x4bdecfa9, 11);
	ROUND(F3, c, d, a, b, x[ 7] + 0xf6bb4b60, 16);
	ROUND(F3, b, c, d, a, x[10] + 0xbebfbc70, 23);
	ROUND(F3, a, b, c, d, x[13] + 0x289b7ec6,  4);
	ROUND(F3, d, a, b, c, x[ 0] + 0xeaa127fa, 11);
	ROUND(F3, c, d, a, b, x[ 3] + 0xd4ef3085, 16);
	ROUND(F3, b, c, d, a, x[ 6] + 0x04881d05, 23);
	ROUND(F3, a, b, c, d, x[ 9] + 0xd9d4d039,  4);
	ROUND(F3, d, a, b, c, x[12] + 0xe6db99e5, 11);
	ROUND(F3, c, d, a, b, x[15] + 0x1fa27cf8, 16);
	ROUND(F3, b, c, d, a, x[ 2] + 0xc4ac5665, 23);

	ROUND(F4, a, b, c, d, x[ 0] + 0xf4292244,  6);
	ROUND(F4, d, a, b, c, x[ 7] + 0x432aff97, 10);
	ROUND(F4, c, d, a, b, x[14] + 0xab9423a7, 15);
	ROUND(F4, b, c, d, a, x[ 5] + 0xfc93a039, 21);
	ROUND(F4, a, b, c, d, x[12] + 0x655b59c3,  6);
	ROUND(F4, d, a, b, c, x[ 3] + 0x8f0ccc92, 10);
	ROUND(F4, c, d, a, b, x[10] + 0xffeff47d, 15);
	ROUND(F4, b, c, d, a, x[ 1] + 0x85845dd1, 21);
	ROUND(F4, a, b, c, d, x[ 8] + 0x6fa87e4f,  6);
	ROUND(F4, d, a, b, c, x[15] + 0xfe2ce6e0, 10);
	ROUND(F4, c, d, a, b, x[ 6] + 0xa3014314, 15);
	ROUND(F4, b, c, d, a, x[13] + 0x4e0811a1, 21);
	ROUND(F4, a, b, c, d, x[ 4] + 0xf7537e82,  6);
	ROUND(F4, d, a, b, c, x[11] + 0xbd3af235, 10);
	ROUND(F4, c, d, a, b, x[ 2] + 0x2ad7d2bb, 15);
	ROUND(F4, b, c, d, a, x[ 9] + 0xeb86d391, 21);
	
	state_[0] += a;
	state_[1] += b;
	state_[2] += c;
	state_[3] += d;
  } // MD5_transform

} // Private namespace.

4. [图片] 截图_2016-08-21_14-27-46.png    



开源中国-程序员在线工具:Git代码托管 API文档大全(120+) JS在线编辑演示 二维码 更多»

开源从代码分享开始 分享代码
猫叔猫叔的其它代码 全部(13)...