mirror of https://github.com/dnomd343/md5sum.git
Dnomd343
8 months ago
commit
36c026d26b
4 changed files with 210 additions and 0 deletions
@ -0,0 +1,35 @@ |
|||
#include <iostream> |
|||
|
|||
#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); |
|||
} |
@ -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
|
@ -0,0 +1,23 @@ |
|||
#pragma once |
|||
|
|||
#include <cstdint> |
|||
|
|||
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
|
@ -0,0 +1,50 @@ |
|||
#pragma once |
|||
|
|||
#include <cmath> |
|||
|
|||
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
|
Loading…
Reference in new issue