commit 36c026d26bc26904e7a488859e0b5aba4020fded Author: Dnomd343 Date: Thu Mar 14 22:16:02 2024 +0800 feat: md5 algorithm of blocks diff --git a/main.cc b/main.cc new file mode 100644 index 0000000..c443927 --- /dev/null +++ b/main.cc @@ -0,0 +1,35 @@ +#include + +#include "md5_core.h" + +std::string test_data() { + char data[64]; + for (char i = 0; i < 64; ++i) { + data[i] = i; + } + return {data, data + 64}; +} + +void dump_ctx(const md5::md5_ctx *c) { + std::cout << std::hex << c->A << std::endl; + std::cout << std::hex << c->B << std::endl; + std::cout << std::hex << c->C << std::endl; + std::cout << std::hex << c->D << std::endl; + std::cout << std::dec << c->size << std::endl; +} + +int main() { + auto data = test_data() + test_data() + test_data() + test_data(); + + md5::md5_ctx c; + dump_ctx(&c); + + md5::md5_process(&c, data.c_str(), data.size()); + md5::md5_process(&c, data.c_str(), data.size()); + dump_ctx(&c); + + md5::md5_reset(&c); + md5::md5_process(&c, data.c_str(), data.size()); + md5::md5_process(&c, data.c_str(), data.size()); + dump_ctx(&c); +} diff --git a/md5_core.cc b/md5_core.cc new file mode 100644 index 0000000..40d780e --- /dev/null +++ b/md5_core.cc @@ -0,0 +1,102 @@ +#include "md5_core.h" +#include "md5_math.h" + +#define RA A, B, C, D +#define RB D, A, B, C +#define RC C, D, A, B +#define RD B, C, D, A + +#define F(x, y, z) (z ^ (x & (y ^ z))) +#define G(x, y, z) (y ^ (z & (x ^ y))) +#define H(x, y, z) (x ^ y ^ z) +#define I(x, y, z) (y ^ (x | ~z)) + +#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) + +#define STEP(i, f, a, b, c, d) \ + do { \ + a += f(b, c, d) + data[K(i)] + T(i); \ + CYCLIC(a, S(i)); \ + a += b; \ + } while (0) + +#define FF(i, ...) STEP((0x00 | i), F, __VA_ARGS__) +#define GG(i, ...) STEP((0x10 | i), G, __VA_ARGS__) +#define HH(i, ...) STEP((0x20 | i), H, __VA_ARGS__) +#define II(i, ...) STEP((0x30 | i), I, __VA_ARGS__) + +#define MD5_ROUND(OP) \ + OP(0x0, RA); OP(0x1, RB); OP(0x2, RC); OP(0x3, RD); \ + OP(0x4, RA); OP(0x5, RB); OP(0x6, RC); OP(0x7, RD); \ + OP(0x8, RA); OP(0x9, RB); OP(0xa, RC); OP(0xb, RD); \ + OP(0xc, RA); OP(0xd, RB); OP(0xe, RC); OP(0xf, RD); + +namespace md5 { + +consteval int K(int index) { + int i = index >> 4; + const int step[] = {1, 5, 3, 7}; + const int begin[] = {0, 1, 5, 0}; + return (begin[i] + step[i] * index) & 0b1111; +} + +consteval int S(int index) { + const int map[][4] = { + {7, 12, 17, 22}, + {5, 9, 14, 20}, + {4, 11, 16, 23}, + {6, 10, 15, 21}, + }; + return map[index >> 4][index & 0b11]; +} + +consteval uint32_t T(int index) { + double val = math::sin(index + 1); + return uint32_t(std::abs(val) * 0x100000000); +} + +void md5_reset(struct md5_ctx *ctx) { + ctx->A = MD5_A; + ctx->B = MD5_B; + ctx->C = MD5_C; + ctx->D = MD5_D; + ctx->size = 0; +} + +void md5_process(struct md5_ctx *ctx, const void *buffer, uint64_t len) { + const auto *data = (uint32_t *)buffer; + const auto *limit = data + (len >> 2); + + uint32_t A = ctx->A; + uint32_t B = ctx->B; + uint32_t C = ctx->C; + uint32_t D = ctx->D; + + while (data < limit) { + uint32_t A_ = A; + uint32_t B_ = B; + uint32_t C_ = C; + uint32_t D_ = D; + + MD5_ROUND(FF) + MD5_ROUND(GG) + MD5_ROUND(HH) + MD5_ROUND(II) + + A += A_; + B += B_; + C += C_; + D += D_; + + data += 16; // 512 bits + } + + ctx->A = A; + ctx->B = B; + ctx->C = C; + ctx->D = D; + + ctx->size += len; // processed size +} + +} // namespace md5 diff --git a/md5_core.h b/md5_core.h new file mode 100644 index 0000000..8de27dd --- /dev/null +++ b/md5_core.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +namespace md5 { + +constexpr uint32_t MD5_A = 0x67452301; +constexpr uint32_t MD5_B = 0xefcdab89; +constexpr uint32_t MD5_C = 0x98badcfe; +constexpr uint32_t MD5_D = 0x10325476; + +struct md5_ctx { + uint32_t A = MD5_A; + uint32_t B = MD5_B; + uint32_t C = MD5_C; + uint32_t D = MD5_D; + uint64_t size = 0; +}; + +void md5_reset(struct md5_ctx *ctx); +void md5_process(struct md5_ctx *ctx, const void *buffer, uint64_t len); + +} // namespace md5 diff --git a/md5_math.h b/md5_math.h new file mode 100644 index 0000000..dcc26d9 --- /dev/null +++ b/md5_math.h @@ -0,0 +1,50 @@ +#pragma once + +#include + +namespace md5::math { + +constexpr double PI = 3.141592653589793238462643L; + +consteval double pow(double x, int n) { + double res = 1; + for (int i = 0; i < n; ++i) { + res *= x; + } + return res; +} + +consteval double factorial(int n) { + double res = 1; + for (int i = 2 ; i <= n ; ++i) { + res *= i; + } + return res; +} + +/// Calculate sin(x) value with Maclaurin series. +consteval double sin_core(double x) { + double res = x; + for (int i = 1; i < 80; ++i) { + const int n = i * 2 + 1; + const int sign = (i & 1) ? -1 : 1; + res += sign * pow(x, n) / factorial(n); + } + return res; +} + +/// Calculate the sin(x) value in radians. +consteval double sin(double x) { + x = std::fmod(x, 2 * PI); // -2PI < x < 2PI + + if (std::abs(x) > PI) { + x -= ((x > 0) ? 2 : -2) * PI; // -PI < x < PI + } + + if (std::abs(x) > PI / 2) { + x = ((x > 0) ? 1 : -1) * PI - x; // -PI / 2 < x < PI / 2 + } + return sin_core(x); +} + +} // namespace md5::math