Browse Source

update: independent impl folder

master
Dnomd343 8 months ago
parent
commit
3f0fa58374
  1. 4
      CMakeLists.txt
  2. 114
      src/core.cc
  3. 62
      src/impl/algorithm.inc
  4. 66
      src/impl/core.cc
  5. 0
      src/impl/inline.inc
  6. 2
      src/impl/sine.inc
  7. 33
      src/impl/wrapper.cc
  8. 2
      src/md5.h

4
CMakeLists.txt

@ -7,9 +7,9 @@ option(MD5_ENABLE_BENCHMARK "Enable benchmark of the md5sum library." ON)
set(CMAKE_CXX_STANDARD 20)
add_compile_options(-Wall -Wextra)
add_library(md5sum STATIC src/core.cc src/wrapper.cc)
add_library(md5sum STATIC src/impl/core.cc src/impl/wrapper.cc)
target_compile_options(md5sum PRIVATE -fno-rtti -fno-exceptions)
target_include_directories(md5sum INTERFACE src/)
target_include_directories(md5sum PUBLIC src/)
include(third_party/ThirdParty.cmake)
add_library(md5sum::md5sum ALIAS md5sum)

114
src/core.cc

@ -1,114 +0,0 @@
#include <cstring>
#include "md5.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) + block[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 {
static const unsigned char Padding[64] {0x80, /* 0x00, ... */};
consteval int K(int index) { // index -> [0, 64)
const int step[] = {1, 5, 3, 7};
const int begin[] = {0, 1, 5, 0};
return (begin[index >> 4] + step[index >> 4] * index) & 0b1111;
}
consteval int S(int index) { // index -> [0, 64)
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) { // index -> [0, 64)
auto val = math::sin(index + 1);
return static_cast<uint32_t>(std::abs(val) * 0x100000000);
}
const void* MD5::UpdateImpl(const void *data, uint64_t len) {
auto *block = static_cast<const uint32_t *>(data);
auto *limit = block + ((len &= ~0b111111ULL) >> 2);
auto A = ctx_.A;
auto B = ctx_.B;
auto C = ctx_.C;
auto D = ctx_.D;
while (block < limit) {
auto A_ = A;
auto B_ = B;
auto C_ = C;
auto D_ = D;
MD5_ROUND(FF)
MD5_ROUND(GG)
MD5_ROUND(HH)
MD5_ROUND(II)
A += A_;
B += B_;
C += C_;
D += D_;
block += 16; // move to next block
}
ctx_.A = A;
ctx_.B = B;
ctx_.C = C;
ctx_.D = D;
ctx_.size += len;
return static_cast<const void *>(limit);
}
void MD5::FinalImpl(const void *data, uint64_t len) {
if (len >= 120) { // len -> [64 + 56, INF)
data = UpdateImpl(data, len);
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);
UpdateImpl(buffer, 64); // update 1 block
} else { // len -> [56, 64 + 56)
std::memcpy(buffer + len, Padding, 120 - len);
std::memcpy(buffer + 120, &total, 8);
UpdateImpl(buffer, 128); // update 2 blocks
}
}
} // namespace md5

62
src/impl/algorithm.inc

@ -0,0 +1,62 @@
#pragma once
#define MD5_R1 A, B, C, D
#define MD5_R2 D, A, B, C
#define MD5_R3 C, D, A, B
#define MD5_R4 B, C, D, A
#define MD5_F(x, y, z) (z ^ (x & (y ^ z)))
#define MD5_G(x, y, z) (y ^ (z & (x ^ y)))
#define MD5_H(x, y, z) (x ^ y ^ z)
#define MD5_I(x, y, z) (y ^ (x | ~z))
#define MD5_CYC(w, s) (w = (w << s) | (w >> (32 - s)))
#define MD5_STEP(i, f, a, b, c, d) \
do { \
a += f(b, c, d) + MD5_DATA(i) + MD5_T(i); \
MD5_CYC(a, MD5_S(i)); \
a += b; \
} while (0)
#define MD5_FF(i, ...) MD5_STEP((0x00 | i), MD5_F, __VA_ARGS__)
#define MD5_GG(i, ...) MD5_STEP((0x10 | i), MD5_G, __VA_ARGS__)
#define MD5_HH(i, ...) MD5_STEP((0x20 | i), MD5_H, __VA_ARGS__)
#define MD5_II(i, ...) MD5_STEP((0x30 | i), MD5_I, __VA_ARGS__)
#define MD5_ROUND(OP) \
OP(0x0, MD5_R1); OP(0x1, MD5_R2); OP(0x2, MD5_R3); OP(0x3, MD5_R4); \
OP(0x4, MD5_R1); OP(0x5, MD5_R2); OP(0x6, MD5_R3); OP(0x7, MD5_R4); \
OP(0x8, MD5_R1); OP(0x9, MD5_R2); OP(0xa, MD5_R3); OP(0xb, MD5_R4); \
OP(0xc, MD5_R1); OP(0xd, MD5_R2); OP(0xe, MD5_R3); OP(0xf, MD5_R4);
#define MD5_UPDATE \
MD5_ROUND(MD5_FF) MD5_ROUND(MD5_GG) MD5_ROUND(MD5_HH) MD5_ROUND(MD5_II)
namespace md5::value {
/// MD5 data block index, input between 0 and 63.
consteval int K(int i) {
const int step[] = {1, 5, 3, 7};
const int begin[] = {0, 1, 5, 0};
return (begin[i >> 4] + step[i >> 4] * i) & 0b1111;
}
/// MD5 circular shift times, input between 0 and 63.
consteval int S(int i) {
const int shift[][4] = {
{7, 12, 17, 22},
{5, 9, 14, 20},
{4, 11, 16, 23},
{6, 10, 15, 21},
};
return shift[i >> 4][i & 0b11];
}
/// MD5 T-table constant, input between 0 and 63.
consteval uint32_t T(int i) {
auto val = math::sin(i + 1);
return static_cast<uint32_t>(std::abs(val) * 0x100000000);
}
} // namespace md5::value

66
src/impl/core.cc

@ -0,0 +1,66 @@
#include <cstring>
#include "md5.h"
#include "sine.inc"
#include "algorithm.inc"
#define MD5_S(i) value::S(i)
#define MD5_T(i) value::T(i)
#define MD5_DATA(i) block[value::K(i)]
namespace md5 {
static constexpr unsigned char Padding[64] { 0x80, /* 0x00, ... */ };
const void* MD5::UpdateImpl(const void *data, uint64_t len) {
auto *block = static_cast<const uint32_t *>(data);
auto *limit = block + ((len &= ~0b111111ULL) >> 2);
auto A = ctx_.A;
auto B = ctx_.B;
auto C = ctx_.C;
auto D = ctx_.D;
while (block < limit) {
auto A_ = A;
auto B_ = B;
auto C_ = C;
auto D_ = D;
MD5_UPDATE
A += A_;
B += B_;
C += C_;
D += D_;
block += 16; // move to next block
}
ctx_.A = A;
ctx_.B = B;
ctx_.C = C;
ctx_.D = D;
ctx_.size += len;
return static_cast<const void *>(limit);
}
void MD5::FinalImpl(const void *data, uint64_t len) {
if (len >= 120) { // len -> [64 + 56, INF)
data = UpdateImpl(data, len);
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);
UpdateImpl(buffer, 64); // update 1 block
} else { // len -> [56, 64 + 56)
std::memcpy(buffer + len, Padding, 120 - len);
std::memcpy(buffer + 120, &total, 8);
UpdateImpl(buffer, 128); // update 2 blocks
}
}
} // namespace md5

0
src/md5.inc → src/impl/inline.inc

2
src/md5_math.h → src/impl/sine.inc

@ -4,7 +4,7 @@
namespace md5::math {
constexpr double PI = 3.141592653589793238462643L;
constexpr double PI = 3.14159265358979323846264338327950;
consteval double pow(double x, int n) {
double res = 1;

33
src/wrapper.cc → src/impl/wrapper.cc

@ -4,6 +4,22 @@
namespace md5 {
static constexpr char HexTable[] = {
'0','1','2','3','4','5','6','7',
'8','9','a','b','c','d','e','f',
};
std::string MD5::Digest() const {
std::string result {};
result.resize(32);
auto *ptr = reinterpret_cast<const uint8_t *>(&ctx_);
for (int i = 0; i < 32; ++ptr) {
result[i++] = HexTable[*ptr >> 4];
result[i++] = HexTable[*ptr & 0b1111];
}
return result;
}
MD5& MD5::Update(const void *data, uint64_t len) {
if (buffer_size_ != 0) {
if (buffer_size_ + len < 64) { // buffer not filled
@ -22,7 +38,6 @@ MD5& MD5::Update(const void *data, uint64_t len) {
data = UpdateImpl(data, len);
len &= 0b111111; // len -> [0, 64)
if (len != 0) {
std::memcpy(buffer_, data, len); // save remain data into buffer
buffer_size_ = len;
@ -30,20 +45,4 @@ MD5& MD5::Update(const void *data, uint64_t len) {
return *this;
}
static constexpr char HexTable[] = {
'0','1','2','3','4','5','6','7',
'8','9','a','b','c','d','e','f',
};
std::string MD5::Digest() const {
std::string result {};
result.resize(32);
auto *src = reinterpret_cast<const uint8_t *>(&ctx_);
for (int i = 0; i < 32; ++src) {
result[i++] = HexTable[*src >> 4];
result[i++] = HexTable[*src & 0b1111];
}
return result;
}
} // namespace md5

2
src/md5.h

@ -65,4 +65,4 @@ private:
} // namespace md5
#include "md5.inc"
#include "impl/inline.inc"

Loading…
Cancel
Save