Branch data Line data Source code
1 : : #pragma once
2 : :
3 : : /*
4 : : MIT License
5 : :
6 : : Copyright (c) 2014-2024 Stephane Cuillerdier (aka aiekick)
7 : :
8 : : Permission is hereby granted, free of charge, to any person obtaining a copy
9 : : of this software and associated documentation files (the "Software"), to deal
10 : : in the Software without restriction, including without limitation the rights
11 : : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 : : copies of the Software, and to permit persons to whom the Software is
13 : : furnished to do so, subject to the following conditions:
14 : :
15 : : The above copyright notice and this permission notice shall be included in all
16 : : copies or substantial portions of the Software.
17 : :
18 : : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 : : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 : : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 : : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 : : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 : : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 : : SOFTWARE.
25 : : */
26 : :
27 : : // ezSha is part of the ezLibs project : https://github.com/aiekick/ezLibs.git
28 : : // and base on https://github.com/983/SHA1.git - Unlicense
29 : :
30 : : #include <cstdint>
31 : : #include <cstring>
32 : : #include <sstream>
33 : : #include <string>
34 : : #include <array>
35 : :
36 : : namespace ez {
37 : :
38 : : class sha1 {
39 : : public:
40 : : static size_t constexpr SHA1_HEX_SIZE{40};
41 : :
42 : : private:
43 : : std::array<uint32_t, 5> m_state{};
44 : : std::array<uint8_t, 64> m_buf{};
45 : : uint32_t m_index{};
46 : : uint64_t m_countBits{};
47 : :
48 : : public:
49 : 4 : sha1() : m_index(0), m_countBits(0) {
50 : 4 : m_state[0] = 0x67452301;
51 : 4 : m_state[1] = 0xEFCDAB89;
52 : 4 : m_state[2] = 0x98BADCFE;
53 : 4 : m_state[3] = 0x10325476;
54 : 4 : m_state[4] = 0xC3D2E1F0;
55 : 4 : }
56 : 0 : explicit sha1(const std::string &vText) : sha1() { add(vText); }
57 : 4 : explicit sha1(const char *vText) : sha1() { add(vText); }
58 : :
59 : : /*
60 : : sha1 &add(char c) { return add(*(uint8_t *)&c); }
61 : : */
62 : :
63 : 10 : sha1 &add(const void *data, uint32_t n) {
64 [ - + ]: 10 : if (!data) {
65 : 0 : return *this;
66 : 0 : }
67 : :
68 : 10 : const uint8_t *ptr = (const uint8_t *)data;
69 : :
70 : : // fill up block if not full
71 [ + + ][ + + ]: 30 : for (; n && m_index % sizeof(m_buf); n--) {
72 : 20 : m_add(*ptr++);
73 : 20 : }
74 : :
75 : : // process full blocks
76 [ - + ]: 10 : for (; n >= sizeof(m_buf); n -= sizeof(m_buf)) {
77 : 0 : m_processBlock(ptr);
78 : 0 : ptr += sizeof(m_buf);
79 : 0 : m_countBits += sizeof(m_buf) * 8;
80 : 0 : }
81 : :
82 : : // process remaining part of block
83 [ + + ]: 26 : for (; n; n--) {
84 : 16 : m_add(*ptr++);
85 : 16 : }
86 : :
87 : 10 : return *this;
88 : 10 : }
89 : :
90 : 10 : sha1 &add(const std::string &vText) {
91 [ - + ]: 10 : if (vText.empty()) {
92 : 0 : return *this;
93 : 0 : }
94 : 10 : return add(vText.data(), static_cast<uint32_t>(vText.size()));
95 : 10 : }
96 : :
97 : : template <typename T>
98 : 2 : sha1 &addValue(const T &vValue) {
99 : 2 : std::stringstream ss;
100 : 2 : ss << vValue;
101 : 2 : return add(ss.str());
102 : 2 : }
103 : :
104 : 4 : sha1 &finalize() {
105 : : // hashed text ends with 0x80, some padding 0x00 and the length in bits
106 : 4 : m_addByteDontCountBits(0x80);
107 [ + + ]: 188 : while (m_index % 64 != 56) {
108 : 184 : m_addByteDontCountBits(0x00);
109 : 184 : }
110 [ + + ]: 36 : for (int32_t j = 7; j >= 0; j--) {
111 : 32 : m_addByteDontCountBits(static_cast<uint8_t>(m_countBits >> j * 8));
112 : 32 : }
113 : :
114 : 4 : return *this;
115 : 4 : }
116 : :
117 : 4 : const std::string getHex(const char *alphabet = "0123456789abcdef") {
118 : 4 : std::string ret(SHA1_HEX_SIZE, 0);
119 : 4 : int k = 0;
120 [ + + ]: 24 : for (int m_index = 0; m_index < 5; m_index++) {
121 [ + + ]: 180 : for (int j = 7; j >= 0; j--) {
122 : 160 : ret[k++] = alphabet[(m_state[m_index] >> j * 4) & 0xf];
123 : 160 : }
124 : 20 : }
125 : 4 : return ret;
126 : 4 : }
127 : :
128 : : private:
129 : 36 : sha1 &m_add(uint8_t x) {
130 : 36 : m_addByteDontCountBits(x);
131 : 36 : m_countBits += 8;
132 : 36 : return *this;
133 : 36 : }
134 : 256 : void m_addByteDontCountBits(uint8_t x) {
135 : 256 : m_buf[m_index++] = x;
136 [ + + ]: 256 : if (m_index >= sizeof(m_buf)) {
137 : 4 : m_index = 0;
138 : 4 : m_processBlock(m_buf.data());
139 : 4 : }
140 : 256 : }
141 : :
142 : 896 : static uint32_t m_rol32(uint32_t x, uint32_t n) { return (x << n) | (x >> (32 - n)); }
143 : :
144 : 64 : static uint32_t m_makeWord(const uint8_t *p) { return ((uint32_t)p[0] << 3 * 8) | ((uint32_t)p[1] << 2 * 8) | ((uint32_t)p[2] << 1 * 8) | ((uint32_t)p[3] << 0 * 8); }
145 : :
146 : 4 : void m_processBlock(const uint8_t *ptr) {
147 : 4 : const uint32_t c0 = 0x5a827999;
148 : 4 : const uint32_t c1 = 0x6ed9eba1;
149 : 4 : const uint32_t c2 = 0x8f1bbcdc;
150 : 4 : const uint32_t c3 = 0xca62c1d6;
151 : :
152 : 4 : uint32_t a = m_state[0];
153 : 4 : uint32_t b = m_state[1];
154 : 4 : uint32_t c = m_state[2];
155 : 4 : uint32_t d = m_state[3];
156 : 4 : uint32_t e = m_state[4];
157 : :
158 : 4 : uint32_t w[16];
159 : :
160 [ + + ]: 68 : for (int m_index = 0; m_index < 16; m_index++) {
161 : 64 : w[m_index] = m_makeWord(ptr + m_index * 4);
162 : 64 : }
163 : :
164 : 256 : #define SHA1_LOAD(m_index) w[m_index & 15] = m_rol32(w[(m_index + 13) & 15] ^ w[(m_index + 8) & 15] ^ w[(m_index + 2) & 15] ^ w[m_index & 15], 1);
165 : 4 : #define SHA1_ROUND_0(v, u, x, y, z, m_index) \
166 : 64 : z += ((u & (x ^ y)) ^ y) + w[m_index & 15] + c0 + m_rol32(v, 5); \
167 : 64 : u = m_rol32(u, 30);
168 : 4 : #define SHA1_ROUND_1(v, u, x, y, z, m_index) \
169 : 16 : SHA1_LOAD(m_index) z += ((u & (x ^ y)) ^ y) + w[m_index & 15] + c0 + m_rol32(v, 5); \
170 : 16 : u = m_rol32(u, 30);
171 : 4 : #define SHA1_ROUND_2(v, u, x, y, z, m_index) \
172 : 80 : SHA1_LOAD(m_index) z += (u ^ x ^ y) + w[m_index & 15] + c1 + m_rol32(v, 5); \
173 : 80 : u = m_rol32(u, 30);
174 : 4 : #define SHA1_ROUND_3(v, u, x, y, z, m_index) \
175 : 80 : SHA1_LOAD(m_index) z += (((u | x) & y) | (u & x)) + w[m_index & 15] + c2 + m_rol32(v, 5); \
176 : 80 : u = m_rol32(u, 30);
177 : 4 : #define SHA1_ROUND_4(v, u, x, y, z, m_index) \
178 : 80 : SHA1_LOAD(m_index) z += (u ^ x ^ y) + w[m_index & 15] + c3 + m_rol32(v, 5); \
179 : 80 : u = m_rol32(u, 30);
180 : :
181 : 4 : SHA1_ROUND_0(a, b, c, d, e, 0);
182 : 4 : SHA1_ROUND_0(e, a, b, c, d, 1);
183 : 4 : SHA1_ROUND_0(d, e, a, b, c, 2);
184 : 4 : SHA1_ROUND_0(c, d, e, a, b, 3);
185 : 4 : SHA1_ROUND_0(b, c, d, e, a, 4);
186 : 4 : SHA1_ROUND_0(a, b, c, d, e, 5);
187 : 4 : SHA1_ROUND_0(e, a, b, c, d, 6);
188 : 4 : SHA1_ROUND_0(d, e, a, b, c, 7);
189 : 4 : SHA1_ROUND_0(c, d, e, a, b, 8);
190 : 4 : SHA1_ROUND_0(b, c, d, e, a, 9);
191 : 4 : SHA1_ROUND_0(a, b, c, d, e, 10);
192 : 4 : SHA1_ROUND_0(e, a, b, c, d, 11);
193 : 4 : SHA1_ROUND_0(d, e, a, b, c, 12);
194 : 4 : SHA1_ROUND_0(c, d, e, a, b, 13);
195 : 4 : SHA1_ROUND_0(b, c, d, e, a, 14);
196 : 4 : SHA1_ROUND_0(a, b, c, d, e, 15);
197 : 4 : SHA1_ROUND_1(e, a, b, c, d, 16);
198 : 4 : SHA1_ROUND_1(d, e, a, b, c, 17);
199 : 4 : SHA1_ROUND_1(c, d, e, a, b, 18);
200 : 4 : SHA1_ROUND_1(b, c, d, e, a, 19);
201 : 4 : SHA1_ROUND_2(a, b, c, d, e, 20);
202 : 4 : SHA1_ROUND_2(e, a, b, c, d, 21);
203 : 4 : SHA1_ROUND_2(d, e, a, b, c, 22);
204 : 4 : SHA1_ROUND_2(c, d, e, a, b, 23);
205 : 4 : SHA1_ROUND_2(b, c, d, e, a, 24);
206 : 4 : SHA1_ROUND_2(a, b, c, d, e, 25);
207 : 4 : SHA1_ROUND_2(e, a, b, c, d, 26);
208 : 4 : SHA1_ROUND_2(d, e, a, b, c, 27);
209 : 4 : SHA1_ROUND_2(c, d, e, a, b, 28);
210 : 4 : SHA1_ROUND_2(b, c, d, e, a, 29);
211 : 4 : SHA1_ROUND_2(a, b, c, d, e, 30);
212 : 4 : SHA1_ROUND_2(e, a, b, c, d, 31);
213 : 4 : SHA1_ROUND_2(d, e, a, b, c, 32);
214 : 4 : SHA1_ROUND_2(c, d, e, a, b, 33);
215 : 4 : SHA1_ROUND_2(b, c, d, e, a, 34);
216 : 4 : SHA1_ROUND_2(a, b, c, d, e, 35);
217 : 4 : SHA1_ROUND_2(e, a, b, c, d, 36);
218 : 4 : SHA1_ROUND_2(d, e, a, b, c, 37);
219 : 4 : SHA1_ROUND_2(c, d, e, a, b, 38);
220 : 4 : SHA1_ROUND_2(b, c, d, e, a, 39);
221 : 4 : SHA1_ROUND_3(a, b, c, d, e, 40);
222 : 4 : SHA1_ROUND_3(e, a, b, c, d, 41);
223 : 4 : SHA1_ROUND_3(d, e, a, b, c, 42);
224 : 4 : SHA1_ROUND_3(c, d, e, a, b, 43);
225 : 4 : SHA1_ROUND_3(b, c, d, e, a, 44);
226 : 4 : SHA1_ROUND_3(a, b, c, d, e, 45);
227 : 4 : SHA1_ROUND_3(e, a, b, c, d, 46);
228 : 4 : SHA1_ROUND_3(d, e, a, b, c, 47);
229 : 4 : SHA1_ROUND_3(c, d, e, a, b, 48);
230 : 4 : SHA1_ROUND_3(b, c, d, e, a, 49);
231 : 4 : SHA1_ROUND_3(a, b, c, d, e, 50);
232 : 4 : SHA1_ROUND_3(e, a, b, c, d, 51);
233 : 4 : SHA1_ROUND_3(d, e, a, b, c, 52);
234 : 4 : SHA1_ROUND_3(c, d, e, a, b, 53);
235 : 4 : SHA1_ROUND_3(b, c, d, e, a, 54);
236 : 4 : SHA1_ROUND_3(a, b, c, d, e, 55);
237 : 4 : SHA1_ROUND_3(e, a, b, c, d, 56);
238 : 4 : SHA1_ROUND_3(d, e, a, b, c, 57);
239 : 4 : SHA1_ROUND_3(c, d, e, a, b, 58);
240 : 4 : SHA1_ROUND_3(b, c, d, e, a, 59);
241 : 4 : SHA1_ROUND_4(a, b, c, d, e, 60);
242 : 4 : SHA1_ROUND_4(e, a, b, c, d, 61);
243 : 4 : SHA1_ROUND_4(d, e, a, b, c, 62);
244 : 4 : SHA1_ROUND_4(c, d, e, a, b, 63);
245 : 4 : SHA1_ROUND_4(b, c, d, e, a, 64);
246 : 4 : SHA1_ROUND_4(a, b, c, d, e, 65);
247 : 4 : SHA1_ROUND_4(e, a, b, c, d, 66);
248 : 4 : SHA1_ROUND_4(d, e, a, b, c, 67);
249 : 4 : SHA1_ROUND_4(c, d, e, a, b, 68);
250 : 4 : SHA1_ROUND_4(b, c, d, e, a, 69);
251 : 4 : SHA1_ROUND_4(a, b, c, d, e, 70);
252 : 4 : SHA1_ROUND_4(e, a, b, c, d, 71);
253 : 4 : SHA1_ROUND_4(d, e, a, b, c, 72);
254 : 4 : SHA1_ROUND_4(c, d, e, a, b, 73);
255 : 4 : SHA1_ROUND_4(b, c, d, e, a, 74);
256 : 4 : SHA1_ROUND_4(a, b, c, d, e, 75);
257 : 4 : SHA1_ROUND_4(e, a, b, c, d, 76);
258 : 4 : SHA1_ROUND_4(d, e, a, b, c, 77);
259 : 4 : SHA1_ROUND_4(c, d, e, a, b, 78);
260 : 4 : SHA1_ROUND_4(b, c, d, e, a, 79);
261 : :
262 : 4 : #undef SHA1_LOAD
263 : 4 : #undef SHA1_ROUND_0
264 : 4 : #undef SHA1_ROUND_1
265 : 4 : #undef SHA1_ROUND_2
266 : 4 : #undef SHA1_ROUND_3
267 : 4 : #undef SHA1_ROUND_4
268 : :
269 : 4 : m_state[0] += a;
270 : 4 : m_state[1] += b;
271 : 4 : m_state[2] += c;
272 : 4 : m_state[3] += d;
273 : 4 : m_state[4] += e;
274 : 4 : }
275 : : };
276 : :
277 : : } // namespace ez
|