26 [[nodiscard]] std::string
digest(std::istream &stream)
const
29 uint32_t a = 0x67452301;
30 uint32_t b = 0xEFCDAB89;
31 uint32_t c = 0x98BADCFE;
32 uint32_t d = 0x10325476;
35 std::vector<uint8_t> data;
37 while (stream.get(ch)) {
38 data.push_back(
static_cast<uint8_t
>(ch));
42 const uint64_t original_bit_length = data.size() * 8;
46 while ((data.size() % 64) != 56) {
51 for (
int i = 0; i < 8; ++i) {
52 data.push_back((original_bit_length >> (i * 8)) & 0xFF);
56 for (
size_t offset = 0; offset < data.size(); offset += 64) {
57 process_block(data.data() + offset, a, b, c, d);
61 return to_hex_string(a, b, c, d);
66 static uint32_t f(uint32_t x, uint32_t y, uint32_t z)
68 return (x & y) | (~x & z);
70 static uint32_t g(uint32_t x, uint32_t y, uint32_t z)
72 return (x & z) | (y & ~z);
74 static uint32_t h(uint32_t x, uint32_t y, uint32_t z)
78 static uint32_t i(uint32_t x, uint32_t y, uint32_t z)
84 static uint32_t rotate_left(uint32_t value, uint32_t shift)
86 return (value << shift) | (value >> (32 - shift));
90 static void process_block(
const uint8_t *block, uint32_t &a, uint32_t &b, uint32_t &c, uint32_t &d)
94 for (
int j = 0; j < 16; ++j) {
95 x[j] = block[j * 4] | (block[j * 4 + 1] << 8) | (block[j * 4 + 2] << 16) | (block[j * 4 + 3] << 24);
105 for (
int j = 0; j < 16; ++j) {
106 uint32_t k_val =
static_cast<uint32_t
>(std::floor(std::abs(std::sin(j + 1)) * 4294967296.0));
107 uint32_t f_val = f(b, c, d);
108 uint32_t temp = a + f_val + x[j] + k_val;
109 temp = rotate_left(temp, s_[j]);
117 for (
int j = 0; j < 16; ++j) {
118 uint32_t k_val =
static_cast<uint32_t
>(std::floor(std::abs(std::sin(j + 17)) * 4294967296.0));
119 uint32_t g_val = g(b, c, d);
120 uint32_t x_index = (1 + 5 * j) % 16;
121 uint32_t temp = a + g_val + x[x_index] + k_val;
122 temp = rotate_left(temp, s_[16 + j]);
130 for (
int j = 0; j < 16; ++j) {
131 uint32_t k_val =
static_cast<uint32_t
>(std::floor(std::abs(std::sin(j + 33)) * 4294967296.0));
132 uint32_t h_val = h(b, c, d);
133 uint32_t x_index = (5 + 3 * j) % 16;
134 uint32_t temp = a + h_val + x[x_index] + k_val;
135 temp = rotate_left(temp, s_[32 + j]);
143 for (
int j = 0; j < 16; ++j) {
144 uint32_t k_val =
static_cast<uint32_t
>(std::floor(std::abs(std::sin(j + 49)) * 4294967296.0));
145 uint32_t i_val = i(b, c, d);
146 uint32_t x_index = (7 * j) % 16;
147 uint32_t temp = a + i_val + x[x_index] + k_val;
148 temp = rotate_left(temp, s_[48 + j]);
163 [[nodiscard]]
static std::string to_hex_string(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
165 std::stringstream ss;
166 ss << std::hex << std::setfill(
'0');
169 auto append_word = [&ss](uint32_t word) {
170 for (
int i = 0; i < 4; ++i) {
171 ss << std::setw(2) << ((word >> (i * 8)) & 0xFF);
184 static constexpr std::array<uint32_t, 64> s_ = {
Computes the MD5 digest of an input stream.
std::string digest(std::istream &stream) const
Computes the MD5 digest of an input stream.