Kemena3D
Loading...
Searching...
No Matches
kmd5.h
Go to the documentation of this file.
1#ifndef KMD5_H_INCLUDED
2#define KMD5_H_INCLUDED
3
4// kmd5.h
5#pragma once
6#include <string>
7#include <cstring>
8#include <sstream>
9#include <iomanip>
10#include <cstdint>
11
12namespace kemena
13{
14
26class kMD5 {
27public:
29 kMD5() { init(); }
30
36 void update(const uint8_t* input, size_t length);
37
42 void update(const std::string& input);
43
48 std::string final();
49
55 static std::string hash(const std::string& input);
56
57private:
59 void init();
60
65 void transform(const uint8_t block[64]);
66
67 uint32_t state[4];
68 uint64_t count;
69 uint8_t buffer[64];
70};
71
79inline uint32_t F(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (~x & z); }
80
88inline uint32_t G(uint32_t x, uint32_t y, uint32_t z) { return (x & z) | (y & ~z); }
89
97inline uint32_t H(uint32_t x, uint32_t y, uint32_t z) { return x ^ y ^ z; }
98
106inline uint32_t I(uint32_t x, uint32_t y, uint32_t z) { return y ^ (x | ~z); }
107
114inline uint32_t rotate_left(uint32_t x, int n) { return (x << n) | (x >> (32 - n)); }
115
126inline void FF(uint32_t &a, uint32_t b, uint32_t c, uint32_t d,
127 uint32_t x, uint32_t s, uint32_t ac)
128{
129 a += F(b, c, d) + x + ac;
130 a = rotate_left(a, s);
131 a += b;
132}
133
144inline void GG(uint32_t &a, uint32_t b, uint32_t c, uint32_t d,
145 uint32_t x, uint32_t s, uint32_t ac)
146{
147 a += G(b, c, d) + x + ac;
148 a = rotate_left(a, s);
149 a += b;
150}
151
162inline void HH(uint32_t &a, uint32_t b, uint32_t c, uint32_t d,
163 uint32_t x, uint32_t s, uint32_t ac)
164{
165 a += H(b, c, d) + x + ac;
166 a = rotate_left(a, s);
167 a += b;
168}
169
180inline void II(uint32_t &a, uint32_t b, uint32_t c, uint32_t d,
181 uint32_t x, uint32_t s, uint32_t ac)
182{
183 a += I(b, c, d) + x + ac;
184 a = rotate_left(a, s);
185 a += b;
186}
187
194inline void encode(uint8_t* output, const uint32_t* input, size_t length) {
195 for (size_t i = 0, j = 0; j < length; ++i, j += 4) {
196 output[j] = input[i] & 0xff;
197 output[j + 1] = (input[i] >> 8) & 0xff;
198 output[j + 2] = (input[i] >> 16) & 0xff;
199 output[j + 3] = (input[i] >> 24) & 0xff;
200 }
201}
202
209inline void decode(uint32_t* output, const uint8_t* input, size_t length) {
210 for (size_t i = 0, j = 0; j < length; ++i, j += 4) {
211 output[i] = ((uint32_t)input[j]) |
212 (((uint32_t)input[j + 1]) << 8) |
213 (((uint32_t)input[j + 2]) << 16) |
214 (((uint32_t)input[j + 3]) << 24);
215 }
216}
217
218inline void kMD5::init() {
219 count = 0;
220 state[0] = 0x67452301;
221 state[1] = 0xefcdab89;
222 state[2] = 0x98badcfe;
223 state[3] = 0x10325476;
224}
225
226inline void kMD5::update(const uint8_t* input, size_t length) {
227 size_t i = 0, index = (size_t)((count >> 3) & 0x3F);
228 count += ((uint64_t)length) << 3;
229
230 size_t partLen = 64 - index;
231
232 if (length >= partLen) {
233 std::memcpy(&buffer[index], input, partLen);
234 transform(buffer);
235 for (i = partLen; i + 63 < length; i += 64)
236 transform(&input[i]);
237 index = 0;
238 } else {
239 i = 0;
240 }
241 std::memcpy(&buffer[index], &input[i], length - i);
242}
243
244inline void kMD5::update(const std::string& input) {
245 update(reinterpret_cast<const uint8_t*>(input.c_str()), input.length());
246}
247
248inline std::string kMD5::final() {
249 static uint8_t PADDING[64] = { 0x80 };
250 uint8_t bits[8];
251 encode(bits, reinterpret_cast<uint32_t*>(&count), 8);
252
253 size_t index = (size_t)((count >> 3) & 0x3f);
254 size_t padLen = (index < 56) ? (56 - index) : (120 - index);
255 update(PADDING, padLen);
256 update(bits, 8);
257
258 uint8_t digest[16];
259 encode(digest, state, 16);
260
261 std::ostringstream oss;
262 for (int i = 0; i < 16; ++i)
263 oss << std::hex << std::setw(2) << std::setfill('0') << (int)digest[i];
264 return oss.str();
265}
266
267inline std::string kMD5::hash(const std::string& input) {
268 kMD5 md5;
269 md5.update(input);
270 return md5.final();
271}
272
273inline void kMD5::transform(const uint8_t block[64]) {
274 uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
275 decode(x, block, 64);
276
277 FF(a, b, c, d, x[ 0], 7, 0xd76aa478);
278 FF(d, a, b, c, x[ 1], 12, 0xe8c7b756);
279 FF(c, d, a, b, x[ 2], 17, 0x242070db);
280 FF(b, c, d, a, x[ 3], 22, 0xc1bdceee);
281 FF(a, b, c, d, x[ 4], 7, 0xf57c0faf);
282 FF(d, a, b, c, x[ 5], 12, 0x4787c62a);
283 FF(c, d, a, b, x[ 6], 17, 0xa8304613);
284 FF(b, c, d, a, x[ 7], 22, 0xfd469501);
285 FF(a, b, c, d, x[ 8], 7, 0x698098d8);
286 FF(d, a, b, c, x[ 9], 12, 0x8b44f7af);
287 FF(c, d, a, b, x[10], 17, 0xffff5bb1);
288 FF(b, c, d, a, x[11], 22, 0x895cd7be);
289 FF(a, b, c, d, x[12], 7, 0x6b901122);
290 FF(d, a, b, c, x[13], 12, 0xfd987193);
291 FF(c, d, a, b, x[14], 17, 0xa679438e);
292 FF(b, c, d, a, x[15], 22, 0x49b40821);
293
294 GG(a, b, c, d, x[ 1], 5, 0xf61e2562);
295 GG(d, a, b, c, x[ 6], 9, 0xc040b340);
296 GG(c, d, a, b, x[11], 14, 0x265e5a51);
297 GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa);
298 GG(a, b, c, d, x[ 5], 5, 0xd62f105d);
299 GG(d, a, b, c, x[10], 9, 0x02441453);
300 GG(c, d, a, b, x[15], 14, 0xd8a1e681);
301 GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8);
302 GG(a, b, c, d, x[ 9], 5, 0x21e1cde6);
303 GG(d, a, b, c, x[14], 9, 0xc33707d6);
304 GG(c, d, a, b, x[ 3], 14, 0xf4d50d87);
305 GG(b, c, d, a, x[ 8], 20, 0x455a14ed);
306 GG(a, b, c, d, x[13], 5, 0xa9e3e905);
307 GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8);
308 GG(c, d, a, b, x[ 7], 14, 0x676f02d9);
309 GG(b, c, d, a, x[12], 20, 0x8d2a4c8a);
310
311 HH(a, b, c, d, x[ 5], 4, 0xfffa3942);
312 HH(d, a, b, c, x[ 8], 11, 0x8771f681);
313 HH(c, d, a, b, x[11], 16, 0x6d9d6122);
314 HH(b, c, d, a, x[14], 23, 0xfde5380c);
315 HH(a, b, c, d, x[ 1], 4, 0xa4beea44);
316 HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9);
317 HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60);
318 HH(b, c, d, a, x[10], 23, 0xbebfbc70);
319 HH(a, b, c, d, x[13], 4, 0x289b7ec6);
320 HH(d, a, b, c, x[ 0], 11, 0xeaa127fa);
321 HH(c, d, a, b, x[ 3], 16, 0xd4ef3085);
322 HH(b, c, d, a, x[ 6], 23, 0x04881d05);
323 HH(a, b, c, d, x[ 9], 4, 0xd9d4d039);
324 HH(d, a, b, c, x[12], 11, 0xe6db99e5);
325 HH(c, d, a, b, x[15], 16, 0x1fa27cf8);
326 HH(b, c, d, a, x[ 2], 23, 0xc4ac5665);
327
328 II(a, b, c, d, x[ 0], 6, 0xf4292244);
329 II(d, a, b, c, x[ 7], 10, 0x432aff97);
330 II(c, d, a, b, x[14], 15, 0xab9423a7);
331 II(b, c, d, a, x[ 5], 21, 0xfc93a039);
332 II(a, b, c, d, x[12], 6, 0x655b59c3);
333 II(d, a, b, c, x[ 3], 10, 0x8f0ccc92);
334 II(c, d, a, b, x[10], 15, 0xffeff47d);
335 II(b, c, d, a, x[ 1], 21, 0x85845dd1);
336 II(a, b, c, d, x[ 8], 6, 0x6fa87e4f);
337 II(d, a, b, c, x[15], 10, 0xfe2ce6e0);
338 II(c, d, a, b, x[ 6], 15, 0xa3014314);
339 II(b, c, d, a, x[13], 21, 0x4e0811a1);
340 II(a, b, c, d, x[ 4], 6, 0xf7537e82);
341 II(d, a, b, c, x[11], 10, 0xbd3af235);
342 II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb);
343 II(b, c, d, a, x[ 9], 21, 0xeb86d391);
344
345 state[0] += a;
346 state[1] += b;
347 state[2] += c;
348 state[3] += d;
349}
350
351} // namespace kemena
352
353#endif // KMD5_H_INCLUDED
void update(const uint8_t *input, size_t length)
Feeds a block of raw bytes into the running digest.
Definition kmd5.h:226
static std::string hash(const std::string &input)
One-shot helper that hashes an entire string.
Definition kmd5.h:267
std::string final()
Finalises the digest and returns it as a lowercase hex string.
Definition kmd5.h:248
kMD5()
Constructs the context and initialises it to the MD5 starting state.
Definition kmd5.h:29
Top-level Kemena3D engine namespace.
Definition kanimation.h:23
uint32_t I(uint32_t x, uint32_t y, uint32_t z)
MD5 auxiliary function I used in round 4: y ^ (x | ~z).
Definition kmd5.h:106
void decode(uint32_t *output, const uint8_t *input, size_t length)
Reassembles bytes into 32-bit words assuming little-endian order.
Definition kmd5.h:209
uint32_t G(uint32_t x, uint32_t y, uint32_t z)
MD5 auxiliary function G used in round 2: (x & z) | (y & ~z).
Definition kmd5.h:88
void encode(uint8_t *output, const uint32_t *input, size_t length)
Serialises 32-bit words into bytes in little-endian order.
Definition kmd5.h:194
void HH(uint32_t &a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac)
Round-3 transformation step using the H mixing function.
Definition kmd5.h:162
void GG(uint32_t &a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac)
Round-2 transformation step using the G mixing function.
Definition kmd5.h:144
uint32_t H(uint32_t x, uint32_t y, uint32_t z)
MD5 auxiliary function H used in round 3: x ^ y ^ z.
Definition kmd5.h:97
uint32_t F(uint32_t x, uint32_t y, uint32_t z)
MD5 auxiliary function F used in round 1: (x & y) | (~x & z).
Definition kmd5.h:79
uint32_t rotate_left(uint32_t x, int n)
Performs a circular left rotation of a 32-bit value.
Definition kmd5.h:114
void II(uint32_t &a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac)
Round-4 transformation step using the I mixing function.
Definition kmd5.h:180
void FF(uint32_t &a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac)
Round-1 transformation step using the F mixing function.
Definition kmd5.h:126