30 [[nodiscard]] std::string
digest(std::istream &stream)
const
33 uint32_t a = 0x67452301;
34 uint32_t b = 0xEFCDAB89;
35 uint32_t c = 0x98BADCFE;
36 uint32_t d = 0x10325476;
39 std::vector<uint8_t> data;
41 while (stream.get(ch)) {
42 data.push_back(
static_cast<uint8_t
>(ch));
46 const uint64_t original_bit_length = data.size() * 8;
50 while ((data.size() % 64) != 56) {
55 for (
int i = 0; i < 8; ++i) {
56 data.push_back((original_bit_length >> (i * 8)) & 0xFF);
60 for (
size_t offset = 0; offset < data.size(); offset += 64) {
61 process_block(data.data() + offset, a, b, c, d);
65 return to_hex_string(a, b, c, d);
70 static uint32_t f(uint32_t x, uint32_t y, uint32_t z)
72 return (x & y) | (~x & z);
74 static uint32_t g(uint32_t x, uint32_t y, uint32_t z)
76 return (x & z) | (y & ~z);
78 static uint32_t h(uint32_t x, uint32_t y, uint32_t z)
82 static uint32_t i(uint32_t x, uint32_t y, uint32_t z)
88 static uint32_t rotate_left(uint32_t value, uint32_t shift)
90 return (value << shift) | (value >> (32 - shift));
94 static void process_block(
const uint8_t *block, uint32_t &a, uint32_t &b, uint32_t &c, uint32_t &d)
98 for (
int j = 0; j < 16; ++j) {
99 x[j] = block[j * 4] | (block[j * 4 + 1] << 8) | (block[j * 4 + 2] << 16) | (block[j * 4 + 3] << 24);
109 for (
int j = 0; j < 16; ++j) {
110 uint32_t k_val =
static_cast<uint32_t
>(std::floor(std::abs(std::sin(j + 1)) * 4294967296.0));
111 uint32_t f_val = f(b, c, d);
112 uint32_t temp = a + f_val + x[j] + k_val;
113 temp = rotate_left(temp, s_[j]);
121 for (
int j = 0; j < 16; ++j) {
122 uint32_t k_val =
static_cast<uint32_t
>(std::floor(std::abs(std::sin(j + 17)) * 4294967296.0));
123 uint32_t g_val = g(b, c, d);
124 uint32_t x_index = (1 + 5 * j) % 16;
125 uint32_t temp = a + g_val + x[x_index] + k_val;
126 temp = rotate_left(temp, s_[16 + j]);
134 for (
int j = 0; j < 16; ++j) {
135 uint32_t k_val =
static_cast<uint32_t
>(std::floor(std::abs(std::sin(j + 33)) * 4294967296.0));
136 uint32_t h_val = h(b, c, d);
137 uint32_t x_index = (5 + 3 * j) % 16;
138 uint32_t temp = a + h_val + x[x_index] + k_val;
139 temp = rotate_left(temp, s_[32 + j]);
147 for (
int j = 0; j < 16; ++j) {
148 uint32_t k_val =
static_cast<uint32_t
>(std::floor(std::abs(std::sin(j + 49)) * 4294967296.0));
149 uint32_t i_val = i(b, c, d);
150 uint32_t x_index = (7 * j) % 16;
151 uint32_t temp = a + i_val + x[x_index] + k_val;
152 temp = rotate_left(temp, s_[48 + j]);
167 [[nodiscard]]
static std::string to_hex_string(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
169 std::stringstream ss;
170 ss << std::hex << std::setfill(
'0');
173 auto append_word = [&ss](uint32_t word) {
174 for (
int i = 0; i < 4; ++i) {
175 ss << std::setw(2) << ((word >> (i * 8)) & 0xFF);
188 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.