Arion 1.0.2-alpha
A high-performance C++ framework for emulating executable binaries.
 
Loading...
Searching...
No Matches
md5.hpp
Go to the documentation of this file.
1// Credits to https://github.com/Zunawe for this MD5 implementation : https://github.com/Zunawe/md5-c
2
3#ifndef ARION_MD5_HPP
4#define ARION_MD5_HPP
5
6#include <stdint.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11#define MD5_DIGEST_LEN 16
12
13#define ARION_MD5_A 0x67452301
14#define ARION_MD5_B 0xefcdab89
15#define ARION_MD5_C 0x98badcfe
16#define ARION_MD5_D 0x10325476
17
18#define ARION_MD5_F(X, Y, Z) ((X & Y) | (~X & Z))
19#define ARION_MD5_G(X, Y, Z) ((X & Z) | (Y & ~Z))
20#define ARION_MD5_H(X, Y, Z) (X ^ Y ^ Z)
21#define ARION_MD5_I(X, Y, Z) (Y ^ (X | ~Z))
22
23namespace arion
24{
25
28{
30 uint64_t size;
32 uint32_t buffer[4];
34 uint8_t input[64];
36 uint8_t digest[16];
37};
38
40static uint32_t S[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9,
41 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
42 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21};
43
45static uint32_t K[] = {0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
46 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
47 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
48 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
49 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
50 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
51 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
52 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391};
53
55static uint8_t PADDING[] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
60
67inline uint32_t rotate_left(uint32_t x, uint32_t n)
68{
69 return (x << n) | (x >> (32 - n));
70}
71
76inline void md5_init(MD5_CTXT *ctx)
77{
78 ctx->size = (uint64_t)0;
79
80 ctx->buffer[0] = (uint32_t)ARION_MD5_A;
81 ctx->buffer[1] = (uint32_t)ARION_MD5_B;
82 ctx->buffer[2] = (uint32_t)ARION_MD5_C;
83 ctx->buffer[3] = (uint32_t)ARION_MD5_D;
84}
85
91inline void md5_step(uint32_t *buffer, uint32_t *input)
92{
93 uint32_t AA = buffer[0];
94 uint32_t BB = buffer[1];
95 uint32_t CC = buffer[2];
96 uint32_t DD = buffer[3];
97
98 uint32_t E;
99
100 unsigned int j;
101
102 for (unsigned int i = 0; i < 64; ++i)
103 {
104 switch (i / 16)
105 {
106 case 0:
107 E = ARION_MD5_F(BB, CC, DD);
108 j = i;
109 break;
110 case 1:
111 E = ARION_MD5_G(BB, CC, DD);
112 j = ((i * 5) + 1) % 16;
113 break;
114 case 2:
115 E = ARION_MD5_H(BB, CC, DD);
116 j = ((i * 3) + 5) % 16;
117 break;
118 default:
119 E = ARION_MD5_I(BB, CC, DD);
120 j = (i * 7) % 16;
121 break;
122 }
123
124 uint32_t temp = DD;
125 DD = CC;
126 CC = BB;
127 BB = BB + rotate_left(AA + E + K[i] + input[j], S[i]);
128 AA = temp;
129 }
130
131 buffer[0] += AA;
132 buffer[1] += BB;
133 buffer[2] += CC;
134 buffer[3] += DD;
135}
136
144inline void md5_update(MD5_CTXT *ctx, uint8_t *input_buffer, size_t input_len)
145{
146 uint32_t input[16];
147 unsigned int offset = ctx->size % 64;
148 ctx->size += (uint64_t)input_len;
149
150 for (unsigned int i = 0; i < input_len; ++i)
151 {
152 ctx->input[offset++] = (uint8_t)*(input_buffer + i);
153
154 if (offset % 64 == 0)
155 {
156 for (unsigned int j = 0; j < 16; ++j)
157 {
158 input[j] = (uint32_t)(ctx->input[(j * 4) + 3]) << 24 | (uint32_t)(ctx->input[(j * 4) + 2]) << 16 |
159 (uint32_t)(ctx->input[(j * 4) + 1]) << 8 | (uint32_t)(ctx->input[(j * 4)]);
160 }
161 md5_step(ctx->buffer, input);
162 offset = 0;
163 }
164 }
165}
166
171inline void md5_finalize(MD5_CTXT *ctx)
172{
173 uint32_t input[16];
174 unsigned int offset = ctx->size % 64;
175 unsigned int padding_length = offset < 56 ? 56 - offset : (56 + 64) - offset;
176
177 md5_update(ctx, PADDING, padding_length);
178 ctx->size -= (uint64_t)padding_length;
179
180 for (unsigned int j = 0; j < 14; ++j)
181 {
182 input[j] = (uint32_t)(ctx->input[(j * 4) + 3]) << 24 | (uint32_t)(ctx->input[(j * 4) + 2]) << 16 |
183 (uint32_t)(ctx->input[(j * 4) + 1]) << 8 | (uint32_t)(ctx->input[(j * 4)]);
184 }
185 input[14] = (uint32_t)(ctx->size * 8);
186 input[15] = (uint32_t)((ctx->size * 8) >> 32);
187
188 md5_step(ctx->buffer, input);
189
190 for (unsigned int i = 0; i < 4; ++i)
191 {
192 ctx->digest[(i * 4) + 0] = (uint8_t)((ctx->buffer[i] & 0x000000FF));
193 ctx->digest[(i * 4) + 1] = (uint8_t)((ctx->buffer[i] & 0x0000FF00) >> 8);
194 ctx->digest[(i * 4) + 2] = (uint8_t)((ctx->buffer[i] & 0x00FF0000) >> 16);
195 ctx->digest[(i * 4) + 3] = (uint8_t)((ctx->buffer[i] & 0xFF000000) >> 24);
196 }
197}
198
204inline void md5_string(char *input, uint8_t *result)
205{
206 MD5_CTXT ctx;
207 md5_init(&ctx);
208 md5_update(&ctx, (uint8_t *)input, strlen(input));
209 md5_finalize(&ctx);
210
211 memcpy(result, ctx.digest, 16);
212}
213
220inline void md5_file(FILE *file, uint8_t *result)
221{
222 char *input_buffer = (char *)malloc(1024);
223 size_t input_size = 0;
224
225 MD5_CTXT ctx;
226 md5_init(&ctx);
227
228 while ((input_size = fread(input_buffer, 1, 1024, file)) > 0)
229 {
230 md5_update(&ctx, (uint8_t *)input_buffer, input_size);
231 }
232
233 md5_finalize(&ctx);
234
235 free(input_buffer);
236
237 memcpy(result, ctx.digest, 16);
238}
239
240}; // namespace arion
241
242#endif // ARION_MD5_HPP
#define ARION_MD5_C
Definition md5.hpp:15
#define ARION_MD5_B
Definition md5.hpp:14
#define ARION_MD5_G(X, Y, Z)
Definition md5.hpp:19
#define ARION_MD5_I(X, Y, Z)
Definition md5.hpp:21
#define ARION_MD5_D
Definition md5.hpp:16
#define ARION_MD5_H(X, Y, Z)
Definition md5.hpp:20
#define ARION_MD5_A
Definition md5.hpp:13
#define ARION_MD5_F(X, Y, Z)
Definition md5.hpp:18
Definition arch_x86-64.hpp:11
void md5_string(char *input, uint8_t *result)
Definition md5.hpp:204
void md5_step(uint32_t *buffer, uint32_t *input)
Definition md5.hpp:91
void md5_init(MD5_CTXT *ctx)
Definition md5.hpp:76
uint32_t rotate_left(uint32_t x, uint32_t n)
Definition md5.hpp:67
static uint32_t S[]
Array of shift amounts S[i] used in the MD5 algorithm.
Definition md5.hpp:40
static uint32_t K[]
Array of 64 pre-calculated sine constants K[i] used in the MD5 algorithm.
Definition md5.hpp:45
void md5_update(MD5_CTXT *ctx, uint8_t *input_buffer, size_t input_len)
Definition md5.hpp:144
static uint8_t PADDING[]
The MD5 padding constant array.
Definition md5.hpp:55
void md5_finalize(MD5_CTXT *ctx)
Definition md5.hpp:171
void md5_file(FILE *file, uint8_t *result)
Definition md5.hpp:220
This structure holds the context for MD5 calculation.
Definition md5.hpp:28
uint8_t input[64]
Temporary input buffer (64 bytes or 512 bits).
Definition md5.hpp:34
uint32_t buffer[4]
The four 32-bit buffers/registers (A, B, C, D) used in the hash calculation.
Definition md5.hpp:32
uint64_t size
Total size of the input data in bits.
Definition md5.hpp:30
uint8_t digest[16]
The resulting 16-byte (128-bit) MD5 digest.
Definition md5.hpp:36