mirror of
https://github.com/Relintai/rcpp_framework.git
synced 2025-04-24 05:43:21 +02:00
352 lines
9.0 KiB
C++
352 lines
9.0 KiB
C++
/**
|
|
*
|
|
* Md5.cc
|
|
* An Tao
|
|
*
|
|
* Copyright 2018, An Tao. All rights reserved.
|
|
* https://github.com/an-tao/drogon
|
|
* Use of this source code is governed by a MIT license
|
|
* that can be found in the License file.
|
|
*
|
|
* Drogon
|
|
*
|
|
*/
|
|
|
|
#include "Md5.h"
|
|
#include <math.h>
|
|
#include <string.h>
|
|
|
|
const uint32_t Md5Encode::kA = 0x67452301;
|
|
const uint32_t Md5Encode::kB = 0xefcdab89;
|
|
const uint32_t Md5Encode::kC = 0x98badcfe;
|
|
const uint32_t Md5Encode::kD = 0x10325476;
|
|
|
|
const uint64_t Md5Encode::tiNumInteger = 4294967296;
|
|
|
|
// function: CycleMoveLeft
|
|
// @param srcNum: the number to be moved left
|
|
// @param bitNumToMove: the number of bit of moving
|
|
// @return result after moving
|
|
uint32_t Md5Encode::cycleMoveLeft(uint32_t srcNum, int bitNumToMove)
|
|
{
|
|
uint32_t srcNum1 = srcNum;
|
|
uint32_t srcNum2 = srcNum;
|
|
if (0 >= bitNumToMove)
|
|
{
|
|
return srcNum;
|
|
}
|
|
return ((srcNum1 << bitNumToMove) | (srcNum2 >> (32 - bitNumToMove)));
|
|
}
|
|
|
|
// function: FillData
|
|
// @param inDataPtr: input data
|
|
// @param dataByteLen: length of input data
|
|
// @param outDataPtr: output data
|
|
// return : length of output data
|
|
uint32_t Md5Encode::fillData(const char *inDataPtr,
|
|
int dataByteLen,
|
|
char **outDataPtr)
|
|
{
|
|
int bitNum = dataByteLen * BIT_OF_BYTE;
|
|
// int grop_num = bitNum / BIT_OF_GROUP;
|
|
int modBitNum = bitNum % BIT_OF_GROUP;
|
|
int bitNeedFill = 0;
|
|
if (modBitNum > (BIT_OF_GROUP - SRC_DATA_LEN))
|
|
{
|
|
bitNeedFill = (BIT_OF_GROUP - modBitNum);
|
|
bitNeedFill += (BIT_OF_GROUP - SRC_DATA_LEN);
|
|
}
|
|
else
|
|
{
|
|
bitNeedFill = (BIT_OF_GROUP - SRC_DATA_LEN) - modBitNum;
|
|
}
|
|
int allBit = bitNum + bitNeedFill;
|
|
if (0 < bitNeedFill)
|
|
{
|
|
*outDataPtr =
|
|
new char[allBit / BIT_OF_BYTE + SRC_DATA_LEN / BIT_OF_BYTE];
|
|
memset(*outDataPtr,
|
|
0,
|
|
allBit / BIT_OF_BYTE + SRC_DATA_LEN / BIT_OF_BYTE);
|
|
// copy data
|
|
memcpy(*outDataPtr, inDataPtr, dataByteLen);
|
|
// fill rest data
|
|
unsigned char *tmp = reinterpret_cast<unsigned char *>(*outDataPtr);
|
|
tmp += dataByteLen;
|
|
// fill 1 and 0
|
|
*tmp = 0x80;
|
|
// fill origin data len
|
|
unsigned long long *originNum =
|
|
(unsigned long long *)((*outDataPtr) + ((allBit / BIT_OF_BYTE)));
|
|
*originNum = dataByteLen * BIT_OF_BYTE;
|
|
}
|
|
return (allBit / BIT_OF_BYTE + SRC_DATA_LEN / BIT_OF_BYTE);
|
|
}
|
|
|
|
void Md5Encode::roundF(char *data512Ptr, ParamDynamic ¶m)
|
|
{
|
|
uint32_t *M = reinterpret_cast<uint32_t *>(data512Ptr);
|
|
int s[] = {7, 12, 17, 22};
|
|
for (int i = 0; i < 16; ++i)
|
|
{
|
|
uint64_t ti = tiNumInteger * fabs(sin(i + 1));
|
|
if (i % 4 == 0)
|
|
{
|
|
FF(param.ua_, param.ub_, param.uc_, param.ud_, M[i], s[i % 4], ti);
|
|
}
|
|
else if (i % 4 == 1)
|
|
{
|
|
FF(param.ud_, param.ua_, param.ub_, param.uc_, M[i], s[i % 4], ti);
|
|
}
|
|
else if (i % 4 == 2)
|
|
{
|
|
FF(param.uc_, param.ud_, param.ua_, param.ub_, M[i], s[i % 4], ti);
|
|
}
|
|
else if (i % 4 == 3)
|
|
{
|
|
FF(param.ub_, param.uc_, param.ud_, param.ua_, M[i], s[i % 4], ti);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Md5Encode::roundG(char *data512Ptr, ParamDynamic ¶m)
|
|
{
|
|
uint32_t *M = reinterpret_cast<uint32_t *>(data512Ptr);
|
|
int s[] = {5, 9, 14, 20};
|
|
for (int i = 0; i < 16; ++i)
|
|
{
|
|
auto sss = sin(i + 1 + 16);
|
|
uint64_t ti = tiNumInteger * fabs(sss);
|
|
int index = (i * 5 + 1) % 16;
|
|
if (i % 4 == 0)
|
|
{
|
|
GG(param.ua_,
|
|
param.ub_,
|
|
param.uc_,
|
|
param.ud_,
|
|
M[index],
|
|
s[i % 4],
|
|
ti);
|
|
}
|
|
else if (i % 4 == 1)
|
|
{
|
|
GG(param.ud_,
|
|
param.ua_,
|
|
param.ub_,
|
|
param.uc_,
|
|
M[index],
|
|
s[i % 4],
|
|
ti);
|
|
}
|
|
else if (i % 4 == 2)
|
|
{
|
|
GG(param.uc_,
|
|
param.ud_,
|
|
param.ua_,
|
|
param.ub_,
|
|
M[index],
|
|
s[i % 4],
|
|
ti);
|
|
}
|
|
else if (i % 4 == 3)
|
|
{
|
|
GG(param.ub_,
|
|
param.uc_,
|
|
param.ud_,
|
|
param.ua_,
|
|
M[index],
|
|
s[i % 4],
|
|
ti);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Md5Encode::roundH(char *data512Ptr, ParamDynamic ¶m)
|
|
{
|
|
uint32_t *M = reinterpret_cast<uint32_t *>(data512Ptr);
|
|
int s[] = {4, 11, 16, 23};
|
|
for (int i = 0; i < 16; ++i)
|
|
{
|
|
uint64_t ti = tiNumInteger * fabs(sin(i + 1 + 32));
|
|
int index = (i * 3 + 5) % 16;
|
|
if (i % 4 == 0)
|
|
{
|
|
HH(param.ua_,
|
|
param.ub_,
|
|
param.uc_,
|
|
param.ud_,
|
|
M[index],
|
|
s[i % 4],
|
|
ti);
|
|
}
|
|
else if (i % 4 == 1)
|
|
{
|
|
HH(param.ud_,
|
|
param.ua_,
|
|
param.ub_,
|
|
param.uc_,
|
|
M[index],
|
|
s[i % 4],
|
|
ti);
|
|
}
|
|
else if (i % 4 == 2)
|
|
{
|
|
HH(param.uc_,
|
|
param.ud_,
|
|
param.ua_,
|
|
param.ub_,
|
|
M[index],
|
|
s[i % 4],
|
|
ti);
|
|
}
|
|
else if (i % 4 == 3)
|
|
{
|
|
HH(param.ub_,
|
|
param.uc_,
|
|
param.ud_,
|
|
param.ua_,
|
|
M[index],
|
|
s[i % 4],
|
|
ti);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Md5Encode::roundI(char *data512Ptr, ParamDynamic ¶m)
|
|
{
|
|
uint32_t *M = reinterpret_cast<uint32_t *>(data512Ptr);
|
|
int s[] = {6, 10, 15, 21};
|
|
for (int i = 0; i < 16; ++i)
|
|
{
|
|
uint64_t ti = tiNumInteger * fabs(sin(i + 1 + 48));
|
|
int index = (i * 7 + 0) % 16;
|
|
if (i % 4 == 0)
|
|
{
|
|
II(param.ua_,
|
|
param.ub_,
|
|
param.uc_,
|
|
param.ud_,
|
|
M[index],
|
|
s[i % 4],
|
|
ti);
|
|
}
|
|
else if (i % 4 == 1)
|
|
{
|
|
II(param.ud_,
|
|
param.ua_,
|
|
param.ub_,
|
|
param.uc_,
|
|
M[index],
|
|
s[i % 4],
|
|
ti);
|
|
}
|
|
else if (i % 4 == 2)
|
|
{
|
|
II(param.uc_,
|
|
param.ud_,
|
|
param.ua_,
|
|
param.ub_,
|
|
M[index],
|
|
s[i % 4],
|
|
ti);
|
|
}
|
|
else if (i % 4 == 3)
|
|
{
|
|
II(param.ub_,
|
|
param.uc_,
|
|
param.ud_,
|
|
param.ua_,
|
|
M[index],
|
|
s[i % 4],
|
|
ti);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Md5Encode::rotationCalculate(char *data512Ptr, ParamDynamic ¶m)
|
|
{
|
|
if (nullptr == data512Ptr)
|
|
{
|
|
return;
|
|
}
|
|
roundF(data512Ptr, param);
|
|
roundG(data512Ptr, param);
|
|
roundH(data512Ptr, param);
|
|
roundI(data512Ptr, param);
|
|
param.ua_ = param.va_last_ + param.ua_;
|
|
param.ub_ = param.vb_last_ + param.ub_;
|
|
param.uc_ = param.vc_last_ + param.uc_;
|
|
param.ud_ = param.vd_last_ + param.ud_;
|
|
|
|
param.va_last_ = param.ua_;
|
|
param.vb_last_ = param.ub_;
|
|
param.vc_last_ = param.uc_;
|
|
param.vd_last_ = param.ud_;
|
|
}
|
|
|
|
// Convert to hex format string
|
|
std::string Md5Encode::getHexStr(uint32_t numStr)
|
|
{
|
|
std::string hexstr = "";
|
|
char szch[] = {'0',
|
|
'1',
|
|
'2',
|
|
'3',
|
|
'4',
|
|
'5',
|
|
'6',
|
|
'7',
|
|
'8',
|
|
'9',
|
|
'A',
|
|
'B',
|
|
'C',
|
|
'D',
|
|
'E',
|
|
'F'};
|
|
unsigned char *tmptr = (unsigned char *)&numStr;
|
|
int len = sizeof(numStr);
|
|
for (int i = 0; i < len; ++i)
|
|
{
|
|
unsigned char ch = tmptr[i] & 0xF0;
|
|
ch = ch >> 4;
|
|
hexstr.append(1, szch[ch]);
|
|
ch = tmptr[i] & 0x0F;
|
|
hexstr.append(1, szch[ch]);
|
|
}
|
|
return hexstr;
|
|
}
|
|
|
|
// function: Encode
|
|
// @param srcInfo: the string to be encoded.
|
|
// return : the string after encoding
|
|
std::string Md5Encode::encode(const char *data, const size_t dataLen)
|
|
{
|
|
ParamDynamic param;
|
|
param.ua_ = kA;
|
|
param.ub_ = kB;
|
|
param.uc_ = kC;
|
|
param.ud_ = kD;
|
|
param.va_last_ = kA;
|
|
param.vb_last_ = kB;
|
|
param.vc_last_ = kC;
|
|
param.vd_last_ = kD;
|
|
|
|
std::string result;
|
|
char *outDataPtr = nullptr;
|
|
int totalByte = fillData(data, dataLen, &outDataPtr);
|
|
|
|
for (int i = 0; i < totalByte / (BIT_OF_GROUP / BIT_OF_BYTE); ++i)
|
|
{
|
|
char *dataBitOfGroup = outDataPtr;
|
|
dataBitOfGroup += i * (BIT_OF_GROUP / BIT_OF_BYTE);
|
|
rotationCalculate(dataBitOfGroup, param);
|
|
}
|
|
delete[] outDataPtr, outDataPtr = nullptr;
|
|
result.append(getHexStr(param.ua_));
|
|
result.append(getHexStr(param.ub_));
|
|
result.append(getHexStr(param.uc_));
|
|
result.append(getHexStr(param.ud_));
|
|
return result;
|
|
}
|