RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
md5.cpp
Go to the documentation of this file.
1/*
2 * MD5 hash in C and x86 assembly
3 *
4 * Copyright (c) 2016 Project Nayuki
5 * https://www.nayuki.io/page/fast-md5-hash-implementation-in-x86-assembly
6 *
7 * (MIT License)
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of
10 * this software and associated documentation files (the "Software"), to deal in
11 * the Software without restriction, including without limitation the rights to
12 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
13 * of
14 * the Software, and to permit persons to whom the Software is furnished to do
15 * so,
16 * subject to the following conditions:
17 * - The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 * - The Software is provided "as is", without warranty of any kind, express or
20 * implied, including but not limited to the warranties of merchantability,
21 * fitness for a particular purpose and noninfringement. In no event shall the
22 * authors or copyright holders be liable for any claim, damages or other
23 * liability, whether in an action of contract, tort or otherwise, arising
24 * from,
25 * out of or in connection with the Software or the use or other dealings in
26 * the
27 * Software.
28 */
29
30#include "md5.h"
31#include "adt/Array1DRef.h"
32#include "adt/Casts.h"
33#include "adt/Invariant.h"
34#include <array>
35#include <cstddef>
36#include <cstdint>
37#include <cstdio>
38#include <cstring>
39#include <string>
40
41namespace rawspeed::md5 {
42
44MD5Hasher::compress(state_type state,
45 Array1DRef<const uint8_t> block) noexcept {
47
48 std::array<uint32_t, 16> schedule = {{}};
49
50 auto LOADSCHEDULE = [block, &schedule](int i) {
51 for (int k = 3; k >= 0; k--)
52 schedule[i] |= uint32_t(block((4 * i) + k)) << (8 * k);
53 };
54
55 for (int i = 0; i < 16; i++)
56 LOADSCHEDULE(i);
57
58 // Assumes that x is uint32_t and 0 < n < 32
59 auto ROTL32 = [](uint32_t x, int n) __attribute__((pure)) {
60 return (x << n) | (x >> (32 - n));
61 };
62
63 auto ROUND_TAIL = [ROTL32, &schedule](uint32_t& a, uint32_t b, uint32_t expr,
65 a = uint32_t(0UL + a + expr + t + schedule[k]);
66 a = uint32_t(0UL + b + ROTL32(a, s));
67 };
68
69 auto ROUND0 = [ROUND_TAIL](uint32_t& a, uint32_t b, uint32_t c, uint32_t d,
71 ROUND_TAIL(a, b, d ^ (b & (c ^ d)), k, s, t);
72 };
73
74 auto ROUND1 = [ROUND_TAIL](uint32_t& a, uint32_t b, uint32_t c, uint32_t d,
76 ROUND_TAIL(a, b, c ^ (d & (b ^ c)), k, s, t);
77 };
78
79 auto ROUND2 = [ROUND_TAIL](uint32_t& a, uint32_t b, uint32_t c, uint32_t d,
81 ROUND_TAIL(a, b, b ^ c ^ d, k, s, t);
82 };
83
84 auto ROUND3 = [ROUND_TAIL](uint32_t& a, uint32_t b, uint32_t c, uint32_t d,
86 ROUND_TAIL(a, b, c ^ (b | ~d), k, s, t);
87 };
88
89 std::array<uint32_t, 4> tmp;
90 for (int i = 0; i != 4; ++i)
91 tmp[i] = state[i];
92 uint32_t& a = tmp[0];
93 uint32_t& b = tmp[1];
94 uint32_t& c = tmp[2];
95 uint32_t& d = tmp[3];
96
97 ROUND0(a, b, c, d, 0, 7, 0xD76AA478);
98 ROUND0(d, a, b, c, 1, 12, 0xE8C7B756);
99 ROUND0(c, d, a, b, 2, 17, 0x242070DB);
100 ROUND0(b, c, d, a, 3, 22, 0xC1BDCEEE);
101 ROUND0(a, b, c, d, 4, 7, 0xF57C0FAF);
102 ROUND0(d, a, b, c, 5, 12, 0x4787C62A);
103 ROUND0(c, d, a, b, 6, 17, 0xA8304613);
104 ROUND0(b, c, d, a, 7, 22, 0xFD469501);
105 ROUND0(a, b, c, d, 8, 7, 0x698098D8);
106 ROUND0(d, a, b, c, 9, 12, 0x8B44F7AF);
107 ROUND0(c, d, a, b, 10, 17, 0xFFFF5BB1);
108 ROUND0(b, c, d, a, 11, 22, 0x895CD7BE);
109 ROUND0(a, b, c, d, 12, 7, 0x6B901122);
110 ROUND0(d, a, b, c, 13, 12, 0xFD987193);
111 ROUND0(c, d, a, b, 14, 17, 0xA679438E);
112 ROUND0(b, c, d, a, 15, 22, 0x49B40821);
113 ROUND1(a, b, c, d, 1, 5, 0xF61E2562);
114 ROUND1(d, a, b, c, 6, 9, 0xC040B340);
115 ROUND1(c, d, a, b, 11, 14, 0x265E5A51);
116 ROUND1(b, c, d, a, 0, 20, 0xE9B6C7AA);
117 ROUND1(a, b, c, d, 5, 5, 0xD62F105D);
118 ROUND1(d, a, b, c, 10, 9, 0x02441453);
119 ROUND1(c, d, a, b, 15, 14, 0xD8A1E681);
120 ROUND1(b, c, d, a, 4, 20, 0xE7D3FBC8);
121 ROUND1(a, b, c, d, 9, 5, 0x21E1CDE6);
122 ROUND1(d, a, b, c, 14, 9, 0xC33707D6);
123 ROUND1(c, d, a, b, 3, 14, 0xF4D50D87);
124 ROUND1(b, c, d, a, 8, 20, 0x455A14ED);
125 ROUND1(a, b, c, d, 13, 5, 0xA9E3E905);
126 ROUND1(d, a, b, c, 2, 9, 0xFCEFA3F8);
127 ROUND1(c, d, a, b, 7, 14, 0x676F02D9);
128 ROUND1(b, c, d, a, 12, 20, 0x8D2A4C8A);
129 ROUND2(a, b, c, d, 5, 4, 0xFFFA3942);
130 ROUND2(d, a, b, c, 8, 11, 0x8771F681);
131 ROUND2(c, d, a, b, 11, 16, 0x6D9D6122);
132 ROUND2(b, c, d, a, 14, 23, 0xFDE5380C);
133 ROUND2(a, b, c, d, 1, 4, 0xA4BEEA44);
134 ROUND2(d, a, b, c, 4, 11, 0x4BDECFA9);
135 ROUND2(c, d, a, b, 7, 16, 0xF6BB4B60);
136 ROUND2(b, c, d, a, 10, 23, 0xBEBFBC70);
137 ROUND2(a, b, c, d, 13, 4, 0x289B7EC6);
138 ROUND2(d, a, b, c, 0, 11, 0xEAA127FA);
139 ROUND2(c, d, a, b, 3, 16, 0xD4EF3085);
140 ROUND2(b, c, d, a, 6, 23, 0x04881D05);
141 ROUND2(a, b, c, d, 9, 4, 0xD9D4D039);
142 ROUND2(d, a, b, c, 12, 11, 0xE6DB99E5);
143 ROUND2(c, d, a, b, 15, 16, 0x1FA27CF8);
144 ROUND2(b, c, d, a, 2, 23, 0xC4AC5665);
145 ROUND3(a, b, c, d, 0, 6, 0xF4292244);
146 ROUND3(d, a, b, c, 7, 10, 0x432AFF97);
147 ROUND3(c, d, a, b, 14, 15, 0xAB9423A7);
148 ROUND3(b, c, d, a, 5, 21, 0xFC93A039);
149 ROUND3(a, b, c, d, 12, 6, 0x655B59C3);
150 ROUND3(d, a, b, c, 3, 10, 0x8F0CCC92);
151 ROUND3(c, d, a, b, 10, 15, 0xFFEFF47D);
152 ROUND3(b, c, d, a, 1, 21, 0x85845DD1);
153 ROUND3(a, b, c, d, 8, 6, 0x6FA87E4F);
154 ROUND3(d, a, b, c, 15, 10, 0xFE2CE6E0);
155 ROUND3(c, d, a, b, 6, 15, 0xA3014314);
156 ROUND3(b, c, d, a, 13, 21, 0x4E0811A1);
157 ROUND3(a, b, c, d, 4, 6, 0xF7537E82);
158 ROUND3(d, a, b, c, 11, 10, 0xBD3AF235);
159 ROUND3(c, d, a, b, 2, 15, 0x2AD7D2BB);
160 ROUND3(b, c, d, a, 9, 21, 0xEB86D391);
161
162 for (int i = 0; i != 4; ++i)
163 state[i] = uint32_t(uint64_t(0) + state[i] + tmp[i]);
164
165 return state;
166}
167
168/* Full message hasher */
169MD5Hasher::state_type md5_hash(const uint8_t* message, size_t len) noexcept {
170 MD5 hasher;
171
172 hasher.take(message, len);
173
174 return hasher.flush();
175}
176
177std::string hash_to_string(const MD5Hasher::state_type& hash) noexcept {
178 std::array<char, (2 * sizeof(hash)) + 1> res;
180 Array1DRef(hash.data(), implicit_cast<int>(hash.size()));
181 for (int i = 0; i < static_cast<int>(sizeof(hash)); ++i)
182 snprintf(&res[2 * i], 3, "%02x", static_cast<uint8_t>(h(i)));
183 res[32] = 0;
184 return res.data();
185}
186
187} // namespace rawspeed::md5
#define s
#define invariant(expr)
Definition Invariant.h:27
dim x
Definition Common.cpp:50
int RAWSPEED_READONLY size() const
static state_type compress(state_type state, Array1DRef< const uint8_t > block) noexcept
std::array< uint32_t, 4 > state_type
Definition md5.h:52
static constexpr int block_size
Definition md5.h:54
MD5Hasher::state_type flush() noexcept
MD5 & take(const T *message, size_t len) noexcept
__attribute__((always_inline)) inline void MD5 std::string hash_to_string(const MD5Hasher::state_type &hash) noexcept
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32
__attribute__((noinline)) __attribute__((visibility("default"))) JPEGStuffedByteStreamGenerator
Array1DRef(T *data_, int numElts_) -> Array1DRef< T >