aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/digest/md5/md5.cpp
diff options
context:
space:
mode:
authorarcadia-devtools <arcadia-devtools@yandex-team.ru>2022-02-08 18:25:47 +0300
committerarcadia-devtools <arcadia-devtools@yandex-team.ru>2022-02-08 18:25:47 +0300
commita3ac8a71f16e0db7d50d5b1235466ff754e0d228 (patch)
tree8433eb84ffae296ccb9ae094d08491c86c48bdb1 /library/cpp/digest/md5/md5.cpp
parent60312eaed2e51caa7ed482270d3545a9d27cb284 (diff)
downloadydb-a3ac8a71f16e0db7d50d5b1235466ff754e0d228.tar.gz
intermediate changes
ref:f398132a6a7101a031da4a85ff8dc9f360af7d8a
Diffstat (limited to 'library/cpp/digest/md5/md5.cpp')
-rw-r--r--library/cpp/digest/md5/md5.cpp198
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;
}
}