/** * * 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 #include 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(*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(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(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(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(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; }