1 /*
2  *  Chocobo1/Hash
3  *
4  *   Copyright 2017-2020 by Mike Tzou (Chocobo1)
5  *     https://github.com/Chocobo1/Hash
6  *
7  *   Licensed under GNU General Public License 3 or later.
8  *
9  *  @license GPL3 <https://www.gnu.org/licenses/gpl-3.0-standalone.html>
10  */
11 
12 #ifndef CHOCOBO1_RIPEMD_320_H
13 #define CHOCOBO1_RIPEMD_320_H
14 
15 #include <array>
16 #include <cassert>
17 #include <climits>
18 #include <cmath>
19 #include <cstdint>
20 #include <initializer_list>
21 #include <string>
22 #include <type_traits>
23 #include <utility>
24 #include <vector>
25 
26 #if (__cplusplus > 201703L)
27 #include <version>
28 #endif
29 
30 #ifndef USE_STD_SPAN_CHOCOBO1_HASH
31 #if (__cpp_lib_span >= 202002L)
32 #define USE_STD_SPAN_CHOCOBO1_HASH 1
33 #else
34 #define USE_STD_SPAN_CHOCOBO1_HASH 0
35 #endif
36 #endif
37 
38 #if (USE_STD_SPAN_CHOCOBO1_HASH == 1)
39 #include <span>
40 #else
41 #include "gsl/span"
42 #endif
43 
44 
45 namespace Chocobo1
46 {
47 	// Use these!!
48 	// RIPEMD_320();
49 }
50 
51 
52 namespace Chocobo1
53 {
54 // users should ignore things in this namespace
55 
56 namespace Hash
57 {
58 #ifndef CONSTEXPR_CPP17_CHOCOBO1_HASH
59 #if __cplusplus >= 201703L
60 #define CONSTEXPR_CPP17_CHOCOBO1_HASH constexpr
61 #else
62 #define CONSTEXPR_CPP17_CHOCOBO1_HASH
63 #endif
64 #endif
65 
66 #if (USE_STD_SPAN_CHOCOBO1_HASH == 1)
67 	using IndexType = std::size_t;
68 #else
69 	using IndexType = gsl::index;
70 #endif
71 
72 #ifndef CHOCOBO1_HASH_BUFFER_IMPL
73 #define CHOCOBO1_HASH_BUFFER_IMPL
74 	template <typename T, IndexType N>
75 	class Buffer
76 	{
77 		public:
78 			using value_type = T;
79 			using index_type = IndexType;
80 			using size_type = std::size_t;
81 
82 			constexpr Buffer() = default;
83 			constexpr Buffer(const Buffer &) = default;
84 
Buffer(const std::initializer_list<T> initList)85 			CONSTEXPR_CPP17_CHOCOBO1_HASH Buffer(const std::initializer_list<T> initList)
86 			{
87 #if !defined(NDEBUG)
88 				// check if out-of-bounds
89 				static_cast<void>(m_array.at(m_dataEndIdx + initList.size() - 1));
90 #endif
91 
92 				for (const auto &i : initList)
93 				{
94 					m_array[m_dataEndIdx] = i;
95 					++m_dataEndIdx;
96 				}
97 			}
98 
99 			template <typename InputIt>
Buffer(const InputIt first,const InputIt last)100 			constexpr Buffer(const InputIt first, const InputIt last)
101 			{
102 				for (InputIt iter = first; iter != last; ++iter)
103 				{
104 					this->fill(*iter);
105 				}
106 			}
107 
108 			constexpr T& operator[](const index_type pos)
109 			{
110 				return m_array[pos];
111 			}
112 
113 			constexpr T operator[](const index_type pos) const
114 			{
115 				return m_array[pos];
116 			}
117 
118 			CONSTEXPR_CPP17_CHOCOBO1_HASH void fill(const T &value, const index_type count = 1)
119 			{
120 #if !defined(NDEBUG)
121 				// check if out-of-bounds
122 				static_cast<void>(m_array.at(m_dataEndIdx + count - 1));
123 #endif
124 
125 				for (index_type i = 0; i < count; ++i)
126 				{
127 					m_array[m_dataEndIdx] = value;
128 					++m_dataEndIdx;
129 				}
130 			}
131 
132 			template <typename InputIt>
push_back(const InputIt first,const InputIt last)133 			constexpr void push_back(const InputIt first, const InputIt last)
134 			{
135 				for (InputIt iter = first; iter != last; ++iter)
136 				{
137 					this->fill(*iter);
138 				}
139 			}
140 
clear()141 			constexpr void clear()
142 			{
143 				m_array = {};
144 				m_dataEndIdx = 0;
145 			}
146 
empty()147 			constexpr bool empty() const
148 			{
149 				return (m_dataEndIdx == 0);
150 			}
151 
size()152 			constexpr size_type size() const
153 			{
154 				return m_dataEndIdx;
155 			}
156 
data()157 			constexpr const T* data() const
158 			{
159 				return m_array.data();
160 			}
161 
162 		private:
163 			std::array<T, N> m_array {};
164 			index_type m_dataEndIdx = 0;
165 	};
166 #endif
167 
168 
169 namespace RIPEMD_320_NS
170 {
171 	class RIPEMD_320
172 	{
173 		// https://homes.esat.kuleuven.be/~bosselae/ripemd160.html
174 
175 		public:
176 			using Byte = uint8_t;
177 			using ResultArrayType = std::array<Byte, 40>;
178 
179 #if (USE_STD_SPAN_CHOCOBO1_HASH == 1)
180 			template <typename T, std::size_t Extent = std::dynamic_extent>
181 			using Span = std::span<T, Extent>;
182 #else
183 			template <typename T, std::size_t Extent = gsl::dynamic_extent>
184 			using Span = gsl::span<T, Extent>;
185 #endif
186 
187 
188 			constexpr RIPEMD_320();
189 
190 			constexpr void reset();
191 			CONSTEXPR_CPP17_CHOCOBO1_HASH RIPEMD_320& finalize();  // after this, only `toArray()`, `toString()`, `toVector()`, `reset()` are available
192 
193 			std::string toString() const;
194 			std::vector<Byte> toVector() const;
195 			CONSTEXPR_CPP17_CHOCOBO1_HASH ResultArrayType toArray() const;
196 
197 			CONSTEXPR_CPP17_CHOCOBO1_HASH RIPEMD_320& addData(const Span<const Byte> inData);
198 			CONSTEXPR_CPP17_CHOCOBO1_HASH RIPEMD_320& addData(const void *ptr, const std::size_t length);
199 			template <std::size_t N>
200 			CONSTEXPR_CPP17_CHOCOBO1_HASH RIPEMD_320& addData(const Byte (&array)[N]);
201 			template <typename T, std::size_t N>
202 			RIPEMD_320& addData(const T (&array)[N]);
203 			template <typename T>
204 			RIPEMD_320& addData(const Span<T> inSpan);
205 
206 		private:
207 			CONSTEXPR_CPP17_CHOCOBO1_HASH void addDataImpl(const Span<const Byte> data);
208 
209 			static constexpr int BLOCK_SIZE = 64;
210 
211 			Buffer<Byte, (BLOCK_SIZE * 2)> m_buffer;  // x2 for paddings
212 			uint64_t m_sizeCounter = 0;
213 
214 			uint32_t m_h[10] = {};
215 	};
216 
217 
218 	// helpers
219 	template <typename T>
220 	class Loader
221 	{
222 		// this class workaround loading data from unaligned memory boundaries
223 		// also eliminate endianness issues
224 		public:
Loader(const uint8_t * ptr)225 			explicit constexpr Loader(const uint8_t *ptr)
226 				: m_ptr(ptr)
227 			{
228 			}
229 
230 			constexpr T operator[](const IndexType idx) const
231 			{
232 				static_assert(std::is_same<T, uint32_t>::value, "");
233 				// handle specific endianness here
234 				const uint8_t *ptr = m_ptr + (sizeof(T) * idx);
235 				return  ( (static_cast<T>(*(ptr + 0)) <<  0)
236 						| (static_cast<T>(*(ptr + 1)) <<  8)
237 						| (static_cast<T>(*(ptr + 2)) << 16)
238 						| (static_cast<T>(*(ptr + 3)) << 24));
239 			}
240 
241 		private:
242 			const uint8_t *m_ptr;
243 	};
244 
245 	template <typename R, typename T>
ror(const T x,const unsigned int s)246 	constexpr R ror(const T x, const unsigned int s)
247 	{
248 		static_assert(std::is_unsigned<R>::value, "");
249 		static_assert(std::is_unsigned<T>::value, "");
250 		return static_cast<R>(x >> s);
251 	}
252 
253 	template <typename T>
rotl(const T x,const unsigned int s)254 	constexpr T rotl(const T x, const unsigned int s)
255 	{
256 		static_assert(std::is_unsigned<T>::value, "");
257 		if (s == 0)
258 			return x;
259 		return ((x << s) | (x >> ((sizeof(T) * 8) - s)));
260 	}
261 
262 
263 	//
RIPEMD_320()264 	constexpr RIPEMD_320::RIPEMD_320()
265 	{
266 		static_assert((CHAR_BIT == 8), "Sorry, we don't support exotic CPUs");
267 		reset();
268 	}
269 
reset()270 	constexpr void RIPEMD_320::reset()
271 	{
272 		m_buffer.clear();
273 		m_sizeCounter = 0;
274 
275 		m_h[0] = 0x67452301;
276 		m_h[1] = 0xEFCDAB89;
277 		m_h[2] = 0x98BADCFE;
278 		m_h[3] = 0x10325476;
279 		m_h[4] = 0xC3D2E1F0;
280 		m_h[5] = 0x76543210;
281 		m_h[6] = 0xFEDCBA98;
282 		m_h[7] = 0x89ABCDEF;
283 		m_h[8] = 0x01234567;
284 		m_h[9] = 0x3C2D1E0F;
285 	}
286 
finalize()287 	CONSTEXPR_CPP17_CHOCOBO1_HASH RIPEMD_320& RIPEMD_320::finalize()
288 	{
289 		m_sizeCounter += m_buffer.size();
290 
291 		// append 1 bit
292 		m_buffer.fill(1 << 7);
293 
294 		// append paddings
295 		const size_t len = BLOCK_SIZE - ((m_buffer.size() + 8) % BLOCK_SIZE);
296 		m_buffer.fill(0, (len + 8));
297 
298 		// append size in bits
299 		const uint64_t sizeCounterBits = m_sizeCounter * 8;
300 		const uint32_t sizeCounterBitsL = ror<uint32_t>(sizeCounterBits, 0);
301 		const uint32_t sizeCounterBitsH = ror<uint32_t>(sizeCounterBits, 32);
302 		for (int i = 0; i < 4; ++i)
303 		{
304 			m_buffer[m_buffer.size() - 8 + i] = ror<Byte>(sizeCounterBitsL, (8 * i));
305 			m_buffer[m_buffer.size() - 4 + i] = ror<Byte>(sizeCounterBitsH, (8 * i));
306 		}
307 
308 		addDataImpl({m_buffer.data(), m_buffer.size()});
309 		m_buffer.clear();
310 
311 		return (*this);
312 	}
313 
toString()314 	std::string RIPEMD_320::toString() const
315 	{
316 		const auto a = toArray();
317 		std::string ret;
318 		ret.resize(2 * a.size());
319 
320 		auto retPtr = &ret.front();
321 		for (const auto c : a)
322 		{
323 			const Byte upper = ror<Byte>(c, 4);
324 			*(retPtr++) = static_cast<char>((upper < 10) ? (upper + '0') : (upper - 10 + 'a'));
325 
326 			const Byte lower = c & 0xf;
327 			*(retPtr++) = static_cast<char>((lower < 10) ? (lower + '0') : (lower - 10 + 'a'));
328 		}
329 
330 		return ret;
331 	}
332 
toVector()333 	std::vector<RIPEMD_320::Byte> RIPEMD_320::toVector() const
334 	{
335 		const auto a = toArray();
336 		return {a.begin(), a.end()};
337 	}
338 
toArray()339 	CONSTEXPR_CPP17_CHOCOBO1_HASH RIPEMD_320::ResultArrayType RIPEMD_320::toArray() const
340 	{
341 		const Span<const uint32_t> state(m_h);
342 		const int dataSize = sizeof(decltype(state)::value_type);
343 
344 		ResultArrayType ret {};
345 		auto retPtr = ret.data();
346 		for (const auto i : state)
347 		{
348 			for (int j = 0; j < dataSize; ++j)
349 				*(retPtr++) = ror<Byte>(i, (j * 8));
350 		}
351 
352 		return ret;
353 	}
354 
addData(const Span<const Byte> inData)355 	CONSTEXPR_CPP17_CHOCOBO1_HASH RIPEMD_320& RIPEMD_320::addData(const Span<const Byte> inData)
356 	{
357 		Span<const Byte> data = inData;
358 
359 		if (!m_buffer.empty())
360 		{
361 			const size_t len = std::min<size_t>((BLOCK_SIZE - m_buffer.size()), data.size());  // try fill to BLOCK_SIZE bytes
362 			m_buffer.push_back(data.begin(), (data.begin() + len));
363 
364 			if (m_buffer.size() < BLOCK_SIZE)  // still doesn't fill the buffer
365 				return (*this);
366 
367 			addDataImpl({m_buffer.data(), m_buffer.size()});
368 			m_buffer.clear();
369 
370 			data = data.subspan(len);
371 		}
372 
373 		const size_t dataSize = data.size();
374 		if (dataSize < BLOCK_SIZE)
375 		{
376 			m_buffer = {data.begin(), data.end()};
377 			return (*this);
378 		}
379 
380 		const size_t len = dataSize - (dataSize % BLOCK_SIZE);  // align on BLOCK_SIZE bytes
381 		addDataImpl(data.first(len));
382 
383 		if (len < dataSize)  // didn't consume all data
384 			m_buffer = {(data.begin() + len), data.end()};
385 
386 		return (*this);
387 	}
388 
addData(const void * ptr,const std::size_t length)389 	CONSTEXPR_CPP17_CHOCOBO1_HASH RIPEMD_320& RIPEMD_320::addData(const void *ptr, const std::size_t length)
390 	{
391 		// Span::size_type = std::size_t
392 		return addData({static_cast<const Byte*>(ptr), length});
393 	}
394 
395 	template <std::size_t N>
addData(const Byte (& array)[N])396 	CONSTEXPR_CPP17_CHOCOBO1_HASH RIPEMD_320& RIPEMD_320::addData(const Byte (&array)[N])
397 	{
398 		return addData({array, N});
399 	}
400 
401 	template <typename T, std::size_t N>
addData(const T (& array)[N])402 	RIPEMD_320& RIPEMD_320::addData(const T (&array)[N])
403 	{
404 		return addData({reinterpret_cast<const Byte*>(array), (sizeof(T) * N)});
405 	}
406 
407 	template <typename T>
addData(const Span<T> inSpan)408 	RIPEMD_320& RIPEMD_320::addData(const Span<T> inSpan)
409 	{
410 		return addData({reinterpret_cast<const Byte*>(inSpan.data()), inSpan.size_bytes()});
411 	}
412 
addDataImpl(const Span<const Byte> data)413 	CONSTEXPR_CPP17_CHOCOBO1_HASH void RIPEMD_320::addDataImpl(const Span<const Byte> data)
414 	{
415 		assert((data.size() % BLOCK_SIZE) == 0);
416 
417 		m_sizeCounter += data.size();
418 
419 		for (size_t i = 0, iend = static_cast<size_t>(data.size() / BLOCK_SIZE); i < iend; ++i)
420 		{
421 			const Loader<uint32_t> x(static_cast<const Byte *>(data.data() + (i * BLOCK_SIZE)));
422 
423 			const auto f1 = [](const uint32_t x, const uint32_t y, const uint32_t z) -> uint32_t
424 			{
425 				return (x ^ y ^ z);
426 			};
427 			const auto f2 = [](const uint32_t x, const uint32_t y, const uint32_t z) -> uint32_t
428 			{
429 				return ((x & (y ^ z)) ^ z);  // alternative
430 			};
431 			const auto f3 = [](const uint32_t x, const uint32_t y, const uint32_t z) -> uint32_t
432 			{
433 				return ((x | (~y)) ^ z);
434 			};
435 			const auto f4 = [](const uint32_t x, const uint32_t y, const uint32_t z) -> uint32_t
436 			{
437 				return (((x ^ y) & z) ^ y);  // alternative
438 			};
439 			const auto f5 = [](const uint32_t x, const uint32_t y, const uint32_t z) -> uint32_t
440 			{
441 				return (x ^ (y | (~z)));
442 			};
443 
444 			uint32_t a = m_h[0];
445 			uint32_t b = m_h[1];
446 			uint32_t c = m_h[2];
447 			uint32_t d = m_h[3];
448 			uint32_t e = m_h[4];
449 			const auto lineLeft = [x](uint32_t &a, uint32_t &b, uint32_t &c, uint32_t &d, uint32_t &e, const auto &f, const uint32_t k, const unsigned int r, const unsigned int s) -> void
450 			{
451 				a = rotl((a + f(b, c, d) + x[r] + k), s) + e;
452 				c = rotl(c, 10);
453 			};
454 
455 			uint32_t aa = m_h[5];
456 			uint32_t bb = m_h[6];
457 			uint32_t cc = m_h[7];
458 			uint32_t dd = m_h[8];
459 			uint32_t ee = m_h[9];
460 			const auto &lineRight = lineLeft;
461 
462 			const auto swap = [](auto &left, auto &right)
463 			{
464 				// TODO: std::swap is finally constexpr at c++20
465 				const auto temp = left;
466 				left = right;
467 				right = temp;
468 			};
469 
470 			lineLeft(a, b, c, d, e, f1, 0x00000000, 0, 11);
471 			lineLeft(e, a, b, c, d, f1, 0x00000000, 1, 14);
472 			lineRight(aa, bb, cc, dd, ee, f5, 0x50A28BE6, 5, 8);
473 			lineRight(ee, aa, bb, cc, dd, f5, 0x50A28BE6, 14, 9);
474 			lineLeft(d, e, a, b, c, f1, 0x00000000, 2, 15);
475 			lineLeft(c, d, e, a, b, f1, 0x00000000, 3, 12);
476 			lineRight(dd, ee, aa, bb, cc, f5, 0x50A28BE6, 7, 9);
477 			lineRight(cc, dd, ee, aa, bb, f5, 0x50A28BE6, 0, 11);
478 			lineLeft(b, c, d, e, a, f1, 0x00000000, 4, 5);
479 			lineLeft(a, b, c, d, e, f1, 0x00000000, 5, 8);
480 			lineRight(bb, cc, dd, ee, aa, f5, 0x50A28BE6, 9, 13);
481 			lineRight(aa, bb, cc, dd, ee, f5, 0x50A28BE6, 2, 15);
482 			lineLeft(e, a, b, c, d, f1, 0x00000000, 6, 7);
483 			lineLeft(d, e, a, b, c, f1, 0x00000000, 7, 9);
484 			lineRight(ee, aa, bb, cc, dd, f5, 0x50A28BE6, 11, 15);
485 			lineRight(dd, ee, aa, bb, cc, f5, 0x50A28BE6, 4, 5);
486 			lineLeft(c, d, e, a, b, f1, 0x00000000, 8, 11);
487 			lineLeft(b, c, d, e, a, f1, 0x00000000, 9, 13);
488 			lineRight(cc, dd, ee, aa, bb, f5, 0x50A28BE6, 13, 7);
489 			lineRight(bb, cc, dd, ee, aa, f5, 0x50A28BE6, 6, 7);
490 			lineLeft(a, b, c, d, e, f1, 0x00000000, 10, 14);
491 			lineLeft(e, a, b, c, d, f1, 0x00000000, 11, 15);
492 			lineRight(aa, bb, cc, dd, ee, f5, 0x50A28BE6, 15, 8);
493 			lineRight(ee, aa, bb, cc, dd, f5, 0x50A28BE6, 8, 11);
494 			lineLeft(d, e, a, b, c, f1, 0x00000000, 12, 6);
495 			lineLeft(c, d, e, a, b, f1, 0x00000000, 13, 7);
496 			lineRight(dd, ee, aa, bb, cc, f5, 0x50A28BE6, 1, 14);
497 			lineRight(cc, dd, ee, aa, bb, f5, 0x50A28BE6, 10, 14);
498 			lineLeft(b, c, d, e, a, f1, 0x00000000, 14, 9);
499 			lineLeft(a, b, c, d, e, f1, 0x00000000, 15, 8);
500 			lineRight(bb, cc, dd, ee, aa, f5, 0x50A28BE6, 3, 12);
501 			lineRight(aa, bb, cc, dd, ee, f5, 0x50A28BE6, 12, 6);
502 			swap(a, aa);
503 
504 			lineLeft(e, a, b, c, d, f2, 0x5A827999, 7, 7);
505 			lineLeft(d, e, a, b, c, f2, 0x5A827999, 4, 6);
506 			lineRight(ee, aa, bb, cc, dd, f4, 0x5C4DD124, 6, 9);
507 			lineRight(dd, ee, aa, bb, cc, f4, 0x5C4DD124, 11, 13);
508 			lineLeft(c, d, e, a, b, f2, 0x5A827999, 13, 8);
509 			lineLeft(b, c, d, e, a, f2, 0x5A827999, 1, 13);
510 			lineRight(cc, dd, ee, aa, bb, f4, 0x5C4DD124, 3, 15);
511 			lineRight(bb, cc, dd, ee, aa, f4, 0x5C4DD124, 7, 7);
512 			lineLeft(a, b, c, d, e, f2, 0x5A827999, 10, 11);
513 			lineLeft(e, a, b, c, d, f2, 0x5A827999, 6, 9);
514 			lineRight(aa, bb, cc, dd, ee, f4, 0x5C4DD124, 0, 12);
515 			lineRight(ee, aa, bb, cc, dd, f4, 0x5C4DD124, 13, 8);
516 			lineLeft(d, e, a, b, c, f2, 0x5A827999, 15, 7);
517 			lineLeft(c, d, e, a, b, f2, 0x5A827999, 3, 15);
518 			lineRight(dd, ee, aa, bb, cc, f4, 0x5C4DD124, 5, 9);
519 			lineRight(cc, dd, ee, aa, bb, f4, 0x5C4DD124, 10, 11);
520 			lineLeft(b, c, d, e, a, f2, 0x5A827999, 12, 7);
521 			lineLeft(a, b, c, d, e, f2, 0x5A827999, 0, 12);
522 			lineRight(bb, cc, dd, ee, aa, f4, 0x5C4DD124, 14, 7);
523 			lineRight(aa, bb, cc, dd, ee, f4, 0x5C4DD124, 15, 7);
524 			lineLeft(e, a, b, c, d, f2, 0x5A827999, 9, 15);
525 			lineLeft(d, e, a, b, c, f2, 0x5A827999, 5, 9);
526 			lineRight(ee, aa, bb, cc, dd, f4, 0x5C4DD124, 8, 12);
527 			lineRight(dd, ee, aa, bb, cc, f4, 0x5C4DD124, 12, 7);
528 			lineLeft(c, d, e, a, b, f2, 0x5A827999, 2, 11);
529 			lineLeft(b, c, d, e, a, f2, 0x5A827999, 14, 7);
530 			lineRight(cc, dd, ee, aa, bb, f4, 0x5C4DD124, 4, 6);
531 			lineRight(bb, cc, dd, ee, aa, f4, 0x5C4DD124, 9, 15);
532 			lineLeft(a, b, c, d, e, f2, 0x5A827999, 11, 13);
533 			lineLeft(e, a, b, c, d, f2, 0x5A827999, 8, 12);
534 			lineRight(aa, bb, cc, dd, ee, f4, 0x5C4DD124, 1, 13);
535 			lineRight(ee, aa, bb, cc, dd, f4, 0x5C4DD124, 2, 11);
536 			swap(b, bb);
537 
538 			lineLeft(d, e, a, b, c, f3, 0x6ED9EBA1, 3, 11);
539 			lineLeft(c, d, e, a, b, f3, 0x6ED9EBA1, 10, 13);
540 			lineRight(dd, ee, aa, bb, cc, f3, 0x6D703EF3, 15, 9);
541 			lineRight(cc, dd, ee, aa, bb, f3, 0x6D703EF3, 5, 7);
542 			lineLeft(b, c, d, e, a, f3, 0x6ED9EBA1, 14, 6);
543 			lineLeft(a, b, c, d, e, f3, 0x6ED9EBA1, 4, 7);
544 			lineRight(bb, cc, dd, ee, aa, f3, 0x6D703EF3, 1, 15);
545 			lineRight(aa, bb, cc, dd, ee, f3, 0x6D703EF3, 3, 11);
546 			lineLeft(e, a, b, c, d, f3, 0x6ED9EBA1, 9, 14);
547 			lineLeft(d, e, a, b, c, f3, 0x6ED9EBA1, 15, 9);
548 			lineRight(ee, aa, bb, cc, dd, f3, 0x6D703EF3, 7, 8);
549 			lineRight(dd, ee, aa, bb, cc, f3, 0x6D703EF3, 14, 6);
550 			lineLeft(c, d, e, a, b, f3, 0x6ED9EBA1, 8, 13);
551 			lineLeft(b, c, d, e, a, f3, 0x6ED9EBA1, 1, 15);
552 			lineRight(cc, dd, ee, aa, bb, f3, 0x6D703EF3, 6, 6);
553 			lineRight(bb, cc, dd, ee, aa, f3, 0x6D703EF3, 9, 14);
554 			lineLeft(a, b, c, d, e, f3, 0x6ED9EBA1, 2, 14);
555 			lineLeft(e, a, b, c, d, f3, 0x6ED9EBA1, 7, 8);
556 			lineRight(aa, bb, cc, dd, ee, f3, 0x6D703EF3, 11, 12);
557 			lineRight(ee, aa, bb, cc, dd, f3, 0x6D703EF3, 8, 13);
558 			lineLeft(d, e, a, b, c, f3, 0x6ED9EBA1, 0, 13);
559 			lineLeft(c, d, e, a, b, f3, 0x6ED9EBA1, 6, 6);
560 			lineRight(dd, ee, aa, bb, cc, f3, 0x6D703EF3, 12, 5);
561 			lineRight(cc, dd, ee, aa, bb, f3, 0x6D703EF3, 2, 14);
562 			lineLeft(b, c, d, e, a, f3, 0x6ED9EBA1, 13, 5);
563 			lineLeft(a, b, c, d, e, f3, 0x6ED9EBA1, 11, 12);
564 			lineRight(bb, cc, dd, ee, aa, f3, 0x6D703EF3, 10, 13);
565 			lineRight(aa, bb, cc, dd, ee, f3, 0x6D703EF3, 0, 13);
566 			lineLeft(e, a, b, c, d, f3, 0x6ED9EBA1, 5, 7);
567 			lineLeft(d, e, a, b, c, f3, 0x6ED9EBA1, 12, 5);
568 			lineRight(ee, aa, bb, cc, dd, f3, 0x6D703EF3, 4, 7);
569 			lineRight(dd, ee, aa, bb, cc, f3, 0x6D703EF3, 13, 5);
570 			swap(c, cc);
571 
572 			lineLeft(c, d, e, a, b, f4, 0x8F1BBCDC, 1, 11);
573 			lineLeft(b, c, d, e, a, f4, 0x8F1BBCDC, 9, 12);
574 			lineRight(cc, dd, ee, aa, bb, f2, 0x7A6D76E9, 8, 15);
575 			lineRight(bb, cc, dd, ee, aa, f2, 0x7A6D76E9, 6, 5);
576 			lineLeft(a, b, c, d, e, f4, 0x8F1BBCDC, 11, 14);
577 			lineLeft(e, a, b, c, d, f4, 0x8F1BBCDC, 10, 15);
578 			lineRight(aa, bb, cc, dd, ee, f2, 0x7A6D76E9, 4, 8);
579 			lineRight(ee, aa, bb, cc, dd, f2, 0x7A6D76E9, 1, 11);
580 			lineLeft(d, e, a, b, c, f4, 0x8F1BBCDC, 0, 14);
581 			lineLeft(c, d, e, a, b, f4, 0x8F1BBCDC, 8, 15);
582 			lineRight(dd, ee, aa, bb, cc, f2, 0x7A6D76E9, 3, 14);
583 			lineRight(cc, dd, ee, aa, bb, f2, 0x7A6D76E9, 11, 14);
584 			lineLeft(b, c, d, e, a, f4, 0x8F1BBCDC, 12, 9);
585 			lineLeft(a, b, c, d, e, f4, 0x8F1BBCDC, 4, 8);
586 			lineRight(bb, cc, dd, ee, aa, f2, 0x7A6D76E9, 15, 6);
587 			lineRight(aa, bb, cc, dd, ee, f2, 0x7A6D76E9, 0, 14);
588 			lineLeft(e, a, b, c, d, f4, 0x8F1BBCDC, 13, 9);
589 			lineLeft(d, e, a, b, c, f4, 0x8F1BBCDC, 3, 14);
590 			lineRight(ee, aa, bb, cc, dd, f2, 0x7A6D76E9, 5, 6);
591 			lineRight(dd, ee, aa, bb, cc, f2, 0x7A6D76E9, 12, 9);
592 			lineLeft(c, d, e, a, b, f4, 0x8F1BBCDC, 7, 5);
593 			lineLeft(b, c, d, e, a, f4, 0x8F1BBCDC, 15, 6);
594 			lineRight(cc, dd, ee, aa, bb, f2, 0x7A6D76E9, 2, 12);
595 			lineRight(bb, cc, dd, ee, aa, f2, 0x7A6D76E9, 13, 9);
596 			lineLeft(a, b, c, d, e, f4, 0x8F1BBCDC, 14, 8);
597 			lineLeft(e, a, b, c, d, f4, 0x8F1BBCDC, 5, 6);
598 			lineRight(aa, bb, cc, dd, ee, f2, 0x7A6D76E9, 9, 12);
599 			lineRight(ee, aa, bb, cc, dd, f2, 0x7A6D76E9, 7, 5);
600 			lineLeft(d, e, a, b, c, f4, 0x8F1BBCDC, 6, 5);
601 			lineLeft(c, d, e, a, b, f4, 0x8F1BBCDC, 2, 12);
602 			lineRight(dd, ee, aa, bb, cc, f2, 0x7A6D76E9, 10, 15);
603 			lineRight(cc, dd, ee, aa, bb, f2, 0x7A6D76E9, 14, 8);
604 			swap(d, dd);
605 
606 			lineLeft(b, c, d, e, a, f5, 0xA953FD4E, 4, 9);
607 			lineLeft(a, b, c, d, e, f5, 0xA953FD4E, 0, 15);
608 			lineRight(bb, cc, dd, ee, aa, f1, 0x00000000, 12, 8);
609 			lineRight(aa, bb, cc, dd, ee, f1, 0x00000000, 15, 5);
610 			lineLeft(e, a, b, c, d, f5, 0xA953FD4E, 5, 5);
611 			lineLeft(d, e, a, b, c, f5, 0xA953FD4E, 9, 11);
612 			lineRight(ee, aa, bb, cc, dd, f1, 0x00000000, 10, 12);
613 			lineRight(dd, ee, aa, bb, cc, f1, 0x00000000, 4, 9);
614 			lineLeft(c, d, e, a, b, f5, 0xA953FD4E, 7, 6);
615 			lineLeft(b, c, d, e, a, f5, 0xA953FD4E, 12, 8);
616 			lineRight(cc, dd, ee, aa, bb, f1, 0x00000000, 1, 12);
617 			lineRight(bb, cc, dd, ee, aa, f1, 0x00000000, 5, 5);
618 			lineLeft(a, b, c, d, e, f5, 0xA953FD4E, 2, 13);
619 			lineLeft(e, a, b, c, d, f5, 0xA953FD4E, 10, 12);
620 			lineRight(aa, bb, cc, dd, ee, f1, 0x00000000, 8, 14);
621 			lineRight(ee, aa, bb, cc, dd, f1, 0x00000000, 7, 6);
622 			lineLeft(d, e, a, b, c, f5, 0xA953FD4E, 14, 5);
623 			lineLeft(c, d, e, a, b, f5, 0xA953FD4E, 1, 12);
624 			lineRight(dd, ee, aa, bb, cc, f1, 0x00000000, 6, 8);
625 			lineRight(cc, dd, ee, aa, bb, f1, 0x00000000, 2, 13);
626 			lineLeft(b, c, d, e, a, f5, 0xA953FD4E, 3, 13);
627 			lineLeft(a, b, c, d, e, f5, 0xA953FD4E, 8, 14);
628 			lineRight(bb, cc, dd, ee, aa, f1, 0x00000000, 13, 6);
629 			lineRight(aa, bb, cc, dd, ee, f1, 0x00000000, 14, 5);
630 			lineLeft(e, a, b, c, d, f5, 0xA953FD4E, 11, 11);
631 			lineLeft(d, e, a, b, c, f5, 0xA953FD4E, 6, 8);
632 			lineRight(ee, aa, bb, cc, dd, f1, 0x00000000, 0, 15);
633 			lineRight(dd, ee, aa, bb, cc, f1, 0x00000000, 3, 13);
634 			lineLeft(c, d, e, a, b, f5, 0xA953FD4E, 15, 5);
635 			lineLeft(b, c, d, e, a, f5, 0xA953FD4E, 13, 6);
636 			lineRight(cc, dd, ee, aa, bb, f1, 0x00000000, 9, 11);
637 			lineRight(bb, cc, dd, ee, aa, f1, 0x00000000, 11, 11);
638 			swap(e, ee);
639 
640 			m_h[0] += a;
641 			m_h[1] += b;
642 			m_h[2] += c;
643 			m_h[3] += d;
644 			m_h[4] += e;
645 			m_h[5] += aa;
646 			m_h[6] += bb;
647 			m_h[7] += cc;
648 			m_h[8] += dd;
649 			m_h[9] += ee;
650 		}
651 	}
652 }
653 }
654 	using RIPEMD_320 = Hash::RIPEMD_320_NS::RIPEMD_320;
655 }
656 
657 #endif  // CHOCOBO1_RIPEMD_320_H
658