Browse Source

feat: md5 padding and final algorithm

master
Dnomd343 7 months ago
parent
commit
28a027a668
  1. 15
      main.cc
  2. 75
      md5_core.cc
  3. 10
      md5_core.h

15
main.cc

@ -24,12 +24,19 @@ int main() {
md5::md5_ctx c; md5::md5_ctx c;
dump_ctx(&c); dump_ctx(&c);
md5::md5_process(&c, data.c_str(), data.size()); // md5::md5_update(&c, data.c_str(), data.size());
md5::md5_process(&c, data.c_str(), data.size()); // md5::md5_update(&c, data.c_str(), data.size());
// dump_ctx(&c);
// md5::md5_reset(&c);
// md5::md5_update(&c, data.c_str(), data.size());
// md5::md5_update(&c, data.c_str(), data.size());
// dump_ctx(&c);
md5::md5_final(&c, data.c_str(), 0);
dump_ctx(&c); dump_ctx(&c);
md5::md5_reset(&c); md5::md5_reset(&c);
md5::md5_process(&c, data.c_str(), data.size()); md5::md5_final(&c, data.c_str(), data.size());
md5::md5_process(&c, data.c_str(), data.size());
dump_ctx(&c); dump_ctx(&c);
} }

75
md5_core.cc

@ -1,3 +1,4 @@
#include <cstring>
#include "md5_core.h" #include "md5_core.h"
#include "md5_math.h" #include "md5_math.h"
@ -15,7 +16,7 @@
#define STEP(i, f, a, b, c, d) \ #define STEP(i, f, a, b, c, d) \
do { \ do { \
a += f(b, c, d) + data[K(i)] + T(i); \ a += f(b, c, d) + block[K(i)] + T(i); \
CYCLIC(a, S(i)); \ CYCLIC(a, S(i)); \
a += b; \ a += b; \
} while (0) } while (0)
@ -33,14 +34,16 @@
namespace md5 { namespace md5 {
consteval int K(int index) { static const unsigned char Padding[64] {0x80};
int i = index >> 4;
consteval int K(int index) { // index -> [0, 64)
auto i = index >> 4;
const int step[] = {1, 5, 3, 7}; const int step[] = {1, 5, 3, 7};
const int begin[] = {0, 1, 5, 0}; const int begin[] = {0, 1, 5, 0};
return (begin[i] + step[i] * index) & 0b1111; return (begin[i] + step[i] * index) & 0b1111;
} }
consteval int S(int index) { consteval int S(int index) { // index -> [0, 64)
const int map[][4] = { const int map[][4] = {
{7, 12, 17, 22}, {7, 12, 17, 22},
{5, 9, 14, 20}, {5, 9, 14, 20},
@ -50,12 +53,12 @@ consteval int S(int index) {
return map[index >> 4][index & 0b11]; return map[index >> 4][index & 0b11];
} }
consteval uint32_t T(int index) { consteval uint32_t T(int index) { // index -> [0, 64)
double val = math::sin(index + 1); auto val = math::sin(index + 1);
return uint32_t(std::abs(val) * 0x100000000); return static_cast<uint32_t>(std::abs(val) * 0x100000000);
} }
void md5_reset(struct md5_ctx *ctx) { void md5_reset(md5_ctx *ctx) {
ctx->A = MD5_A; ctx->A = MD5_A;
ctx->B = MD5_B; ctx->B = MD5_B;
ctx->C = MD5_C; ctx->C = MD5_C;
@ -63,40 +66,58 @@ void md5_reset(struct md5_ctx *ctx) {
ctx->size = 0; ctx->size = 0;
} }
void md5_process(struct md5_ctx *ctx, const void *buffer, uint64_t len) { void md5_update(md5_ctx *ctx, const void *data, uint64_t len) {
const auto *data = (uint32_t *)buffer; auto *block = reinterpret_cast<const uint32_t *>(data);
const auto *limit = data + (len >> 2); auto *limit = block + (len >> 2);
auto A = ctx->A;
uint32_t A = ctx->A; auto B = ctx->B;
uint32_t B = ctx->B; auto C = ctx->C;
uint32_t C = ctx->C; auto D = ctx->D;
uint32_t D = ctx->D;
while (block < limit) {
while (data < limit) { auto A_ = A;
uint32_t A_ = A; auto B_ = B;
uint32_t B_ = B; auto C_ = C;
uint32_t C_ = C; auto D_ = D;
uint32_t D_ = D;
MD5_ROUND(FF) MD5_ROUND(FF)
MD5_ROUND(GG) MD5_ROUND(GG)
MD5_ROUND(HH) MD5_ROUND(HH)
MD5_ROUND(II) MD5_ROUND(II)
A += A_; A += A_;
B += B_; B += B_;
C += C_; C += C_;
D += D_; D += D_;
block += 16; // move to next block
data += 16; // 512 bits
} }
ctx->A = A; ctx->A = A;
ctx->B = B; ctx->B = B;
ctx->C = C; ctx->C = C;
ctx->D = D; ctx->D = D;
ctx->size += len; // processed size in byte
}
ctx->size += len; // processed size void md5_final(md5_ctx *ctx, const void *data, uint64_t len) {
if (len >= 120) { // len -> [64 + 56, INF)
auto size = len & ~(uint64_t)0b111111;
md5_update(ctx, data, size);
data = reinterpret_cast<const char*>(data) + size;
len &= 0b111111; // len -> [0, 64)
}
unsigned char buffer[128]; // 2 blocks
std::memcpy(buffer, data, len);
uint64_t total = (ctx->size + len) << 3; // total number in bit
if (len < 56) { // len -> [0, 56)
std::memcpy(buffer + len, Padding, 56 - len);
std::memcpy(buffer + 56, &total, 8);
md5_update(ctx, buffer, 64); // update 1 block
} else { // len -> [56, 64 + 56)
std::memcpy(buffer + len, Padding, 120 - len);
std::memcpy(buffer + 120, &total, 8);
md5_update(ctx, buffer, 128); // update 2 blocks
}
} }
} // namespace md5 } // namespace md5

10
md5_core.h

@ -17,7 +17,13 @@ struct md5_ctx {
uint64_t size = 0; uint64_t size = 0;
}; };
void md5_reset(struct md5_ctx *ctx); /// Reset md5 ctx with algorithm constants.
void md5_process(struct md5_ctx *ctx, const void *buffer, uint64_t len); void md5_reset(md5_ctx *ctx);
/// Update md5 ctx with specified data, note that `len` is a multiple of 64.
void md5_update(md5_ctx *ctx, const void *buffer, uint64_t len);
/// Update and end the md5 hash with the specified data, the value of `len` has no limit.
void md5_final(md5_ctx *ctx, const void *buffer, uint64_t len);
} // namespace md5 } // namespace md5

Loading…
Cancel
Save