NTL密码算法开源库拓展——MD5算法

2021SC@SDUSC

NTL密码算法开源库拓展——MD5算法

算法描述

MD5算法就像一个函数,任意一个二进制串都可以作为自变量进入这个“函数”,然后会出来一个固定为128位的二进制串。
我们先用一个例子来过一下这个过程,然后用文字描述算法细节。
比如加密一个普通的内容为hello的ASCII文本文件,这个文件由40个二进制位存储在计算机上:

01101000 01100101 01101100 01101100 01101111 [存储]

算法开始:
进行二进制位补充。具体这样补充:
从这40位的后面开始,先补充一个1位,再补充0位,一直到总共448位长度(也就是补充407个0位)。接着在后面写入原始信息长度与264的模。也就是40mod(264)=40,40转化为2进制为101000,用64存储就是:

00101000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [存储]

二进制位补充完成。
得到内容(共512位):

01101000 01100101 01101100 01101100 01101111 1 (407个0)00101000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [存储]

然后对这个512个位平均分成16组,每组32个位:
第1组:01101000 01100101 01101100 01101100
第2组:01101111 10000000 00000000 00000000

第32组:00000000 00000000 00000000 00000000

然后使用四个常数进行运算,分别是:
A=0x67452301,B=0xefcdab89,C=0x98badcfe,D=0x10325476。
A: 00000001 00100011 01000101 01100111 [存储]
B: 10001001 10101011 11001101 11101111 [存储]
C: 11111110 11011100 10111010 10011000 [存储]
D: 01110110 01010100 00110010 00010000 [存储]

一共进行64轮运算:
先说明运算符:
=赋值运算符: i=0意味着把0赋值给i,也就是让i的值为0
&按位与运算符:1010b & 1100b的值为1000b
or按位或运算符:1010b or 1100b的值为1110b
^按位异或运算符:1010b ^ 1100b的值为0110b
按位取反运算符:1010b的值为0101b
<<按位循环左移运算符:1100b << 3的值为0110b
mod是取模运算符:33 mod 16 的值为1
i==64是判断i是否和64相等

以上计算有一个地方需要说明,就是给t赋值计算的时候,不考虑进位,每个数都是由32位二进制串表示,加的时候若有进位则进位丢失,得到的t也用32位二进制串表示。
以上数还有两个没有提到,k[i]和s[i]:
s[i]取值为以下数组的第i+1个数
{ 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 }
如s[0]==7,s[3]=22…

k[i]取值为以下数组的第i+1个数
{ 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 }
进行完这些运算后,A,B,C,D的值都获得了更新
A: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx [存储]
B: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx [存储]
C: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx [存储]
D: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx [存储]
把这四个数A -> B -> C -> D按照从低内存到高内存排列起来,共128位,这就是MD5算法的输出。

代码实现

#ifndef MD5_H
#define MD5_H
/* Parameters of MD5. */
#define s11 7
#define s12 12
#define s13 17
#define s14 22
#define s21 5
#define s22 9
#define s23 14
#define s24 20
#define s31 4
#define s32 11
#define s33 16
#define s34 23
#define s41 6
#define s42 10
#define s43 15
#define s44 21

/**
 * @Basic MD5 functions.
 *
 * @param there bit32.
 *
 * @return one bit32.
 */
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))

/**
 * @Rotate Left.
 *
 * @param {num} the raw number.
 *
 * @param {n} rotate left n.
 *
 * @return the number after rotated left.
 */
#define ROTATELEFT(num, n) (((num) << (n)) | ((num) >> (32-(n))))

/**
 * @Transformations for rounds 1, 2, 3, and 4.
 */
#define FF(a, b, c, d, x, s, ac) { \
  (a) += F ((b), (c), (d)) + (x) + ac; \
  (a) = ROTATELEFT ((a), (s)); \
  (a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
  (a) += G ((b), (c), (d)) + (x) + ac; \
  (a) = ROTATELEFT ((a), (s)); \
  (a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
  (a) += H ((b), (c), (d)) + (x) + ac; \
  (a) = ROTATELEFT ((a), (s)); \
  (a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
  (a) += I ((b), (c), (d)) + (x) + ac; \
  (a) = ROTATELEFT ((a), (s)); \
  (a) += (b); \
}

#include <string>
#include <cstring>

using std::string;

/* Define of btye.*/
typedef unsigned char byte;
/* Define of byte. */
typedef unsigned int bit32;

class MD5 {
public:
  /* Construct a MD5 object with a string. */
  MD5(const string& message);

  /* Generate md5 digest. */
  const byte* getDigest();

  /* Convert digest to string value */
  string toStr();

private:
  /* Initialization the md5 object, processing another message block,
   * and updating the context.*/
  void init(const byte* input, size_t len);

  /* MD5 basic transformation. Transforms state based on block. */
  void transform(const byte block[64]);

  /* Encodes input (usigned long) into output (byte). */
  void encode(const bit32* input, byte* output, size_t length);

  /* Decodes input (byte) into output (usigned long). */
  void decode(const byte* input, bit32* output, size_t length);

private:
  /* Flag for mark whether calculate finished. */
  bool finished;

	/* state (ABCD). */
  bit32 state[4];

  /* number of bits, low-order word first. */
  bit32 count[2];

  /* input buffer. */
  byte buffer[64];

  /* message digest. */
  byte digest[16];

	/* padding for calculate. */
  static const byte PADDING[64];

  /* Hex numbers. */
  static const char HEX_NUMBERS[16];
};
#endif // MD5_H

#include "md5.h"

/* Define the static member of MD5. */
const byte MD5::PADDING[64] = { 0x80 };
const char MD5::HEX_NUMBERS[16] = {
  '0', '1', '2', '3',
  '4', '5', '6', '7',
  '8', '9', 'a', 'b',
  'c', 'd', 'e', 'f'
};

MD5::MD5(const string& message) {
  finished = false;
  /* Reset number of bits. */
  count[0] = count[1] = 0;
  /* Initialization constants. */
  state[0] = 0x67452301;
  state[1] = 0xefcdab89;
  state[2] = 0x98badcfe;
  state[3] = 0x10325476;

  /* Initialization the object according to message. */
  init((const byte*)message.c_str(), message.length());
}

const byte* MD5::getDigest() {
  if (!finished) {
    finished = true;

    byte bits[8];
    bit32 oldState[4];
    bit32 oldCount[2];
    bit32 index, padLen;

    /* Save current state and count. */
    memcpy(oldState, state, 16);
    memcpy(oldCount, count, 8);

    /* Save number of bits */
    encode(count, bits, 8);

    /* Pad out to 56 mod 64. */
    index = (bit32)((count[0] >> 3) & 0x3f);
    padLen = (index < 56) ? (56 - index) : (120 - index);
    init(PADDING, padLen);

    /* Append length (before padding) */
    init(bits, 8);

    /* Store state in digest */
    encode(state, digest, 16);

    /* Restore current state and count. */
    memcpy(state, oldState, 16);
    memcpy(count, oldCount, 8);
  }
  return digest;
}


void MD5::init(const byte* input, size_t len) {

  bit32 i, index, partLen;

  finished = false;

  /* Compute number of bytes mod 64 */
  index = (bit32)((count[0] >> 3) & 0x3f);

  /* update number of bits */
  if ((count[0] += ((bit32)len << 3)) < ((bit32)len << 3)) {
    ++count[1];
  }
  count[1] += ((bit32)len >> 29);

  partLen = 64 - index;

  /* transform as many times as possible. */
  if (len >= partLen) {

    memcpy(&buffer[index], input, partLen);
    transform(buffer);

    for (i = partLen; i + 63 < len; i += 64) {
      transform(&input[i]);
    }
    index = 0;

  } else {
    i = 0;
  }

  /* Buffer remaining input */
  memcpy(&buffer[index], &input[i], len - i);
}

void MD5::transform(const byte block[64]) {

  bit32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];

  decode(block, x, 64);

  /* Round 1 */
  FF (a, b, c, d, x[ 0], s11, 0xd76aa478);
  FF (d, a, b, c, x[ 1], s12, 0xe8c7b756);
  FF (c, d, a, b, x[ 2], s13, 0x242070db);
  FF (b, c, d, a, x[ 3], s14, 0xc1bdceee);
  FF (a, b, c, d, x[ 4], s11, 0xf57c0faf);
  FF (d, a, b, c, x[ 5], s12, 0x4787c62a);
  FF (c, d, a, b, x[ 6], s13, 0xa8304613);
  FF (b, c, d, a, x[ 7], s14, 0xfd469501);
  FF (a, b, c, d, x[ 8], s11, 0x698098d8);
  FF (d, a, b, c, x[ 9], s12, 0x8b44f7af);
  FF (c, d, a, b, x[10], s13, 0xffff5bb1);
  FF (b, c, d, a, x[11], s14, 0x895cd7be);
  FF (a, b, c, d, x[12], s11, 0x6b901122);
  FF (d, a, b, c, x[13], s12, 0xfd987193);
  FF (c, d, a, b, x[14], s13, 0xa679438e);
  FF (b, c, d, a, x[15], s14, 0x49b40821);

  /* Round 2 */
  GG (a, b, c, d, x[ 1], s21, 0xf61e2562);
  GG (d, a, b, c, x[ 6], s22, 0xc040b340);
  GG (c, d, a, b, x[11], s23, 0x265e5a51);
  GG (b, c, d, a, x[ 0], s24, 0xe9b6c7aa);
  GG (a, b, c, d, x[ 5], s21, 0xd62f105d);
  GG (d, a, b, c, x[10], s22,  0x2441453);
  GG (c, d, a, b, x[15], s23, 0xd8a1e681);
  GG (b, c, d, a, x[ 4], s24, 0xe7d3fbc8);
  GG (a, b, c, d, x[ 9], s21, 0x21e1cde6);
  GG (d, a, b, c, x[14], s22, 0xc33707d6);
  GG (c, d, a, b, x[ 3], s23, 0xf4d50d87);
  GG (b, c, d, a, x[ 8], s24, 0x455a14ed);
  GG (a, b, c, d, x[13], s21, 0xa9e3e905);
  GG (d, a, b, c, x[ 2], s22, 0xfcefa3f8);
  GG (c, d, a, b, x[ 7], s23, 0x676f02d9);
  GG (b, c, d, a, x[12], s24, 0x8d2a4c8a);

  /* Round 3 */
  HH (a, b, c, d, x[ 5], s31, 0xfffa3942);
  HH (d, a, b, c, x[ 8], s32, 0x8771f681);
  HH (c, d, a, b, x[11], s33, 0x6d9d6122);
  HH (b, c, d, a, x[14], s34, 0xfde5380c);
  HH (a, b, c, d, x[ 1], s31, 0xa4beea44);
  HH (d, a, b, c, x[ 4], s32, 0x4bdecfa9);
  HH (c, d, a, b, x[ 7], s33, 0xf6bb4b60);
  HH (b, c, d, a, x[10], s34, 0xbebfbc70);
  HH (a, b, c, d, x[13], s31, 0x289b7ec6);
  HH (d, a, b, c, x[ 0], s32, 0xeaa127fa);
  HH (c, d, a, b, x[ 3], s33, 0xd4ef3085);
  HH (b, c, d, a, x[ 6], s34,  0x4881d05);
  HH (a, b, c, d, x[ 9], s31, 0xd9d4d039);
  HH (d, a, b, c, x[12], s32, 0xe6db99e5);
  HH (c, d, a, b, x[15], s33, 0x1fa27cf8);
  HH (b, c, d, a, x[ 2], s34, 0xc4ac5665);

  /* Round 4 */
  II (a, b, c, d, x[ 0], s41, 0xf4292244);
  II (d, a, b, c, x[ 7], s42, 0x432aff97);
  II (c, d, a, b, x[14], s43, 0xab9423a7);
  II (b, c, d, a, x[ 5], s44, 0xfc93a039);
  II (a, b, c, d, x[12], s41, 0x655b59c3);
  II (d, a, b, c, x[ 3], s42, 0x8f0ccc92);
  II (c, d, a, b, x[10], s43, 0xffeff47d);
  II (b, c, d, a, x[ 1], s44, 0x85845dd1);
  II (a, b, c, d, x[ 8], s41, 0x6fa87e4f);
  II (d, a, b, c, x[15], s42, 0xfe2ce6e0);
  II (c, d, a, b, x[ 6], s43, 0xa3014314);
  II (b, c, d, a, x[13], s44, 0x4e0811a1);
  II (a, b, c, d, x[ 4], s41, 0xf7537e82);
  II (d, a, b, c, x[11], s42, 0xbd3af235);
  II (c, d, a, b, x[ 2], s43, 0x2ad7d2bb);
  II (b, c, d, a, x[ 9], s44, 0xeb86d391);

  state[0] += a;
  state[1] += b;
  state[2] += c;
  state[3] += d;
}
void MD5::encode(const bit32* input, byte* output, size_t length) {

  for (size_t i = 0, j = 0; j < length; ++i, j += 4) {
    output[j]= (byte)(input[i] & 0xff);
    output[j + 1] = (byte)((input[i] >> 8) & 0xff);
    output[j + 2] = (byte)((input[i] >> 16) & 0xff);
    output[j + 3] = (byte)((input[i] >> 24) & 0xff);
  }
}
void MD5::decode(const byte* input, bit32* output, size_t length) {
  for (size_t i = 0, j = 0; j < length; ++i, j += 4) {
    output[i] = ((bit32)input[j]) | (((bit32)input[j + 1]) << 8) |
    (((bit32)input[j + 2]) << 16) | (((bit32)input[j + 3]) << 24);
  }
}
string MD5::toStr() {
  const byte* digest_ = getDigest();
  string str;
  str.reserve(16 << 1);
  for (size_t i = 0; i < 16; ++i) {
    int t = digest_[i];
    int a = t / 16;
    int b = t % 16;
    str.append(1, HEX_NUMBERS[a]);
    str.append(1, HEX_NUMBERS[b]);
  }
  return str;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

元解~殇怀

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

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

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

打赏作者

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

抵扣说明:

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

余额充值