diff options
author | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-02-08 18:25:47 +0300 |
---|---|---|
committer | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-02-08 18:25:47 +0300 |
commit | a3ac8a71f16e0db7d50d5b1235466ff754e0d228 (patch) | |
tree | 8433eb84ffae296ccb9ae094d08491c86c48bdb1 /library/cpp/digest/md5/md5.cpp | |
parent | 60312eaed2e51caa7ed482270d3545a9d27cb284 (diff) | |
download | ydb-a3ac8a71f16e0db7d50d5b1235466ff754e0d228.tar.gz |
intermediate changes
ref:f398132a6a7101a031da4a85ff8dc9f360af7d8a
Diffstat (limited to 'library/cpp/digest/md5/md5.cpp')
-rw-r--r-- | library/cpp/digest/md5/md5.cpp | 198 |
1 files changed, 95 insertions, 103 deletions
diff --git a/library/cpp/digest/md5/md5.cpp b/library/cpp/digest/md5/md5.cpp index 27af7f88d7..24a5b69eef 100644 --- a/library/cpp/digest/md5/md5.cpp +++ b/library/cpp/digest/md5/md5.cpp @@ -1,19 +1,17 @@ #include "md5.h" -#include <contrib/libs/nayuki_md5/md5.h> +#include <library/cpp/string_utils/base64/base64.h> -#include <util/generic/strbuf.h> -#include <util/generic/string.h> #include <util/stream/input.h> #include <util/stream/file.h> -#include <library/cpp/string_utils/base64/base64.h> #include <util/string/hex.h> -#include <cstring> -#include <cstdlib> +#include <contrib/libs/nayuki_md5/md5.h> namespace { + constexpr size_t MD5_BLOCK_LENGTH = 64; + constexpr size_t MD5_PADDING_SHIFT = 56; constexpr size_t MD5_HEX_DIGEST_LENGTH = 32; struct TMd5Stream: public IOutputStream { @@ -28,6 +26,14 @@ namespace { MD5* M_; }; + + inline TArrayRef<const ui8> MakeUnsignedArrayRef(const void* data, const size_t size) { + return MakeArrayRef(static_cast<const ui8*>(data), size); + } + + inline TArrayRef<const ui8> MakeUnsignedArrayRef(const TArrayRef<const char>& data) { + return MakeUnsignedArrayRef(data.data(), data.size()); + } } char* MD5::File(const char* filename, char* buf) { @@ -51,30 +57,23 @@ TString MD5::File(const TString& filename) { return buf; } -char* MD5::Data(const void* data, size_t len, char* buf) { - MD5 md5; - md5.Update(data, len); - return md5.End(buf); +char* MD5::Data(const TArrayRef<const ui8>& data, char* buf) { + return MD5().Update(data).End(buf); } -TString MD5::Data(TArrayRef<ui8> data) { - MD5 md5; - md5.Update(data.data(), data.size()); +char* MD5::Data(const void* data, size_t len, char* buf) { + return Data(MakeUnsignedArrayRef(data, len), buf); +} +TString MD5::Data(const TArrayRef<const ui8>& data) { TString buf; buf.ReserveAndResize(MD5_HEX_DIGEST_LENGTH); - md5.End(buf.begin()); + Data(data, buf.begin()); return buf; } TString MD5::Data(TStringBuf data) { - MD5 md5; - md5.Update(data.data(), data.size()); - - TString buf; - buf.ReserveAndResize(MD5_HEX_DIGEST_LENGTH); - md5.End(buf.begin()); - return buf; + return Data(MakeUnsignedArrayRef(data)); } char* MD5::Stream(IInputStream* in, char* buf) { @@ -89,27 +88,7 @@ MD5& MD5::Update(IInputStream* in) { return *this; } -static inline void MD5Transform(ui32 state[4], const unsigned char block[64]) { - return md5_compress((uint32_t*)state, (const ui8*)block); -} - -/* - * Encodes input (ui32) into output (unsigned char). Assumes len is - * a multiple of 4. - */ - -static void Encode(unsigned char* output, ui32* input, unsigned int len) { - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) { - output[j] = (unsigned char)(input[i] & 0xff); - output[j + 1] = (unsigned char)((input[i] >> 8) & 0xff); - output[j + 2] = (unsigned char)((input[i] >> 16) & 0xff); - output[j + 3] = (unsigned char)((input[i] >> 24) & 0xff); - } -} - -static unsigned char PADDING[64] = { +static const ui8 PADDING[MD5_BLOCK_LENGTH] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -117,7 +96,8 @@ static unsigned char PADDING[64] = { /* MD5 initialization. Begins an MD5 operation, writing a new context. */ void MD5::Init() { - Count[0] = Count[1] = 0; + BufferSize = 0; + StreamSize = 0; /* Load magic initialization constants. */ State[0] = 0x67452301; State[1] = 0xefcdab89; @@ -131,27 +111,30 @@ void MD5::Init() { * context. */ -void MD5::UpdatePart(const void* inputPtr, unsigned int inputLen) { - const unsigned char* input = (const unsigned char*)inputPtr; - unsigned int i, index, partLen; - /* Compute number of bytes mod 64 */ - index = (unsigned int)((Count[0] >> 3) & 0x3F); - /* Update number of bits */ - if ((Count[0] += ((ui32)inputLen << 3)) < ((ui32)inputLen << 3)) - Count[1]++; - Count[1] += ((ui32)inputLen >> 29); - partLen = 64 - index; - /* Transform as many times as possible. */ - if (inputLen >= partLen) { - memcpy((void*)&Buffer[index], (const void*)input, partLen); - MD5Transform(State, Buffer); - for (i = partLen; i + 63 < inputLen; i += 64) - MD5Transform(State, &input[i]); - index = 0; - } else - i = 0; - /* Buffer remaining input */ - memcpy((void*)&Buffer[index], (const void*)&input[i], inputLen - i); +void MD5::UpdatePart(TArrayRef<const ui8> data) { + /* Count input bytes */ + StreamSize += data.size(); + if (BufferSize > 0) { + /* Filling remaining buffer */ + const ui8 freeBufferSize = MD5_BLOCK_LENGTH - BufferSize; + const ui8 partLen = data.size() >= freeBufferSize ? freeBufferSize : data.size(); + memcpy(&Buffer[BufferSize], data.data(), partLen); + BufferSize += partLen; + data = data.Slice(partLen); + if (BufferSize == MD5_BLOCK_LENGTH) { + /* Buffer is full and ready for hashing */ + md5_compress(State, Buffer); + BufferSize = 0; + } + } + /* Processing input by chanks */ + while (data.size() >= MD5_BLOCK_LENGTH) { + md5_compress(State, data.data()); + data = data.Slice(MD5_BLOCK_LENGTH); + } + /* Save remaining input in buffer */ + memcpy(Buffer, data.data(), data.size()); + BufferSize += data.size(); } /* @@ -159,16 +142,19 @@ void MD5::UpdatePart(const void* inputPtr, unsigned int inputLen) { */ void MD5::Pad() { - unsigned char bits[8]; - unsigned int index, padLen; - /* Save number of bits */ - Encode(bits, Count, 8); - /* Pad out to 56 mod 64. */ - index = (unsigned int)((Count[0] >> 3) & 0x3f); - padLen = (index < 56) ? (56 - index) : (120 - index); - Update(PADDING, padLen); - /* Append length (before padding) */ - Update(bits, 8); + size_t streamSize = StreamSize; + + const size_t paddingSize = (MD5_PADDING_SHIFT > BufferSize) ? (MD5_PADDING_SHIFT - BufferSize) : (MD5_PADDING_SHIFT + MD5_BLOCK_LENGTH - BufferSize); + Update(PADDING, paddingSize); + + // Size of stream in bits + // If size greater than 2^64 - 1 only lower 64 bits used + streamSize <<= 3; + for (int i = 0; i < 8; ++i, streamSize >>= 8) { + // Storing in reverse order + Buffer[MD5_PADDING_SHIFT + i] = static_cast<ui8>(streamSize & 0xFFU); + } + md5_compress(State, Buffer); } /* @@ -176,36 +162,35 @@ void MD5::Pad() { * the message digest and zeroizing the context. */ -unsigned char* MD5::Final(unsigned char digest[16]) { +ui8* MD5::Final(ui8 digest[16]) { /* Do padding. */ Pad(); /* Store state in digest */ - Encode(digest, State, 16); + memcpy(digest, State, 16); /* Zeroize sensitive information. */ - memset((void*)this, 0, sizeof(*this)); + Init(); return digest; } char* MD5::End(char* buf) { - unsigned char digest[16]; static const char hex[] = "0123456789abcdef"; + ui8 digest[16]; if (!buf) buf = (char*)malloc(33); if (!buf) return nullptr; Final(digest); - int i = 0; - for (; i < 16; i++) { - buf[i + i] = hex[digest[i] >> 4]; - buf[i + i + 1] = hex[digest[i] & 0x0f]; + for (ui8 i = 0; i < MD5_HEX_DIGEST_LENGTH / 2; i++) { + buf[i * 2] = hex[digest[i] >> 4]; + buf[i * 2 + 1] = hex[digest[i] & 0x0f]; } - buf[i + i] = '\0'; + buf[32] = '\0'; return buf; } char* MD5::End_b64(char* buf) { - unsigned char digest[16]; + ui8 digest[16]; if (!buf) buf = (char*)malloc(25); if (!buf) @@ -217,7 +202,7 @@ char* MD5::End_b64(char* buf) { } ui64 MD5::EndHalfMix() { - unsigned char digest[16]; + ui8 digest[16]; Final(digest); ui64 res = 0; for (int i = 3; i >= 0; i--) { @@ -227,40 +212,47 @@ ui64 MD5::EndHalfMix() { return res; } -TString MD5::Calc(const TStringBuf& data) { - TString result; - result.resize(32); +TString MD5::Calc(TStringBuf data) { + return Calc(MakeUnsignedArrayRef(data)); +} - Data((const unsigned char*)data.data(), data.size(), result.begin()); +TString MD5::Calc(const TArrayRef<const ui8>& data) { + return Data(data); +} - return result; +TString MD5::CalcRaw(TStringBuf data) { + return CalcRaw(MakeUnsignedArrayRef(data)); } -TString MD5::CalcRaw(const TStringBuf& data) { +TString MD5::CalcRaw(const TArrayRef<const ui8>& data) { TString result; - result.resize(16); - MD5 md5; - md5.Update(data.data(), data.size()); - md5.Final(reinterpret_cast<unsigned char*>(result.begin())); + result.ReserveAndResize(16); + MD5().Update(data).Final(reinterpret_cast<ui8*>(result.begin())); return result; } ui64 MD5::CalcHalfMix(const char* data, size_t len) { - MD5 md5; - md5.Update(data, len); - return md5.EndHalfMix(); + return CalcHalfMix(MakeUnsignedArrayRef(data, len)); +} + +ui64 MD5::CalcHalfMix(TStringBuf data) { + return CalcHalfMix(MakeUnsignedArrayRef(data)); +} + +ui64 MD5::CalcHalfMix(const TArrayRef<const ui8>& data) { + return MD5().Update(data).EndHalfMix(); } -ui64 MD5::CalcHalfMix(const TStringBuf& data) { - return CalcHalfMix(data.data(), data.size()); +bool MD5::IsMD5(TStringBuf data) { + return IsMD5(MakeUnsignedArrayRef(data)); } -bool MD5::IsMD5(const TStringBuf& data) { +bool MD5::IsMD5(const TArrayRef<const ui8>& data) { if (data.size() != 32) { return false; } - for (const char *p = data.data(), *e = data.data() + data.size(); p != e; ++p) { - if (Char2DigitTable[(unsigned char)*p] == '\xff') { + for (const ui8 *p = data.data(), *e = data.data() + data.size(); p != e; ++p) { + if (Char2DigitTable[*p] == '\xff') { return false; } } |