├── LICENSE.md ├── README.md ├── sha1.hh ├── md4.hh ├── md5.hh ├── hmac.hh ├── sha2.hh └── rmd.hh /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License 2 | 3 | Copyright 2018 Quasis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Crypto 2 | 3 | Small, fast, header only, zero dependency cryptographic library written in C++2a. 4 | 5 | ## Cryptographic hash functions 6 | 7 | Cryptographic Hash Functions (CHFs) are a family of algorithms that take an input (or message) and produce a fixed-size output, known as the hash value or digest. This process is a one-way function, meaning it is computationally infeasible to reverse the hash value to obtain the original input. Additionally, small changes in the input will result in significantly different hash values. 8 | 9 | ### Algorithms 10 | 11 | |Class |Word bits|Size bits|Block bits|Rounds|State bits|Output bits| 12 | |-------------------------|--------:|--------:|---------:|-----:|---------:|----------:| 13 | |[MD4](md4.hh) | 32| 64| 512| 3| 128| 128| 14 | |[MD5](md5.hh) | 32| 64| 512| 64| 128| 128| 15 | |[RMD<128>](rmd.hh) | 32| 64| 512| 64| 128| 128| 16 | |[RMD<160>](rmd.hh) | 32| 64| 512| 80| 160| 160| 17 | |[RMD<256>](rmd.hh) | 32| 64| 512| 64| 256| 256| 18 | |[RMD<320>](rmd.hh) | 32| 64| 512| 80| 320| 320| 19 | |[SHA1](sha1.hh) | 32| 64| 512| 80| 160| 160| 20 | |[SHA2<256,224>](sha2.hh) | 32| 64| 512| 64| 256| 224| 21 | |[SHA2<256,256>](sha2.hh) | 32| 64| 512| 64| 256| 256| 22 | |[SHA2<512,224>](sha2.hh) | 64| 128| 1024| 80| 512| 224| 23 | |[SHA2<512,256>](sha2.hh) | 64| 128| 1024| 80| 512| 256| 24 | |[SHA2<512,384>](sha2.hh) | 64| 128| 1024| 80| 512| 384| 25 | |[SHA2<512,512>](sha2.hh) | 64| 128| 1024| 80| 512| 512| 26 | 27 | 28 | ### Examples 29 | 30 | Double hashing the contents of a container holding trivially copyable objects with the help of `SHA2<256>` and `RMD<160>`. Note that `rmd<160>(message)` is an alias for `RMD<160>().update(message).digest()`. 31 | 32 | ```cpp 33 | #include 34 | #include 35 | 36 | using namespace crypto; 37 | 38 | auto 39 | hash(const auto &trivially_copyable_objects) { 40 | 41 | auto hasher = SHA2<256>(); 42 | 43 | for (const auto &entry: trivially_copyable_objects) { 44 | hasher.update(entry); 45 | } 46 | 47 | return rmd<160>(hasher.update("secret").digest()); 48 | } 49 | ``` 50 | 51 | ## Message authentication codes 52 | 53 | Message Authentication Codes (MACs) are cryptographic mechanisms used to ensure the integrity and authenticity of a message or data transmission. They provide a way to verify that a message has not been tampered with during transmission and that it originates from a trusted source. 54 | 55 | ### Algorithms 56 | 57 | Only the hash-based message authentication code ([HMAC](hmac.hh)) is supported at the moment. 58 | 59 | ### Examples 60 | 61 | Double hashing the contents of a container holding trivially copyable objects with the help of `HMAC`, `SHA2<256>` and `RMD<160>`. Note that `hmac>(secret, message)` is an alias for `HMAC>(secret).update(message).digest()`. 62 | 63 | ```cpp 64 | #include 65 | #include 66 | #include 67 | 68 | using namespace crypto; 69 | 70 | auto 71 | hash(const auto &trivially_copyable_objects) { 72 | 73 | auto hasher = HMAC>("secret 1"); 74 | 75 | for (const auto &entry: trivially_copyable_objects) { 76 | hasher.update(entry); 77 | } 78 | 79 | return hmac>("secret 2", hasher.digest()); 80 | } 81 | ``` 82 | 83 | 84 | ## Installation 85 | 86 | Download the sources to the folder of choice and include the desired headers. 87 | 88 | 89 | ## Contributing 90 | 91 | Feature requests, bug reports and success stories are most welcome. 92 | 93 | 94 | ## Copyright 95 | 96 | Copyright 2018 Quasis - The MIT License 97 | -------------------------------------------------------------------------------- /sha1.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * NAME 3 | * 4 | * sha1 - secure hash algorithm 1 5 | * 6 | * SYNOPSIS 7 | * 8 | * auto digest = SHA1().update(...).digest(); 9 | * 10 | * DESCRIPTION 11 | * 12 | * SHA-1 (Secure Hash Algorithm 1) is a cryptographic hash function 13 | * that produces a 160-bit hash value. The algorithm was designed by 14 | * the National Security Agency (NSA) and published by the National 15 | * Institute of Standards and Technology (NIST) in 1995. 16 | * 17 | * EXAMPLES 18 | * 19 | * #include 20 | * using namespace crypto; 21 | * 22 | * auto 23 | * hash(const auto &trivially_copyable_objects) { 24 | * 25 | * auto hasher = SHA1(); 26 | * 27 | * for (const auto &object: trivially_copyable_objects) { 28 | * hasher.update(object); 29 | * } 30 | * 31 | * return sha1(hasher.update("secret").digest()); 32 | * } 33 | * 34 | * COPYRIGHT 35 | * 36 | * Copyright 2022 Quasis - The MIT License 37 | */ 38 | 39 | namespace crypto { 40 | 41 | template 42 | class SHA1 { 43 | 44 | using uint8_type = __UINT8_TYPE__; 45 | using uint16_type = __UINT16_TYPE__; 46 | using uint32_type = __UINT32_TYPE__; 47 | using uint64_type = __UINT64_TYPE__; 48 | 49 | template 50 | struct buffer { 51 | 52 | value_type m_data[count]; 53 | 54 | using size_type = decltype(sizeof(void*)); 55 | using pointer = uint8_type*; 56 | using const_pointer = const uint8_type*; 57 | using reference = value_type&; 58 | using const_reference = const value_type&; 59 | 60 | constexpr size_type 61 | size() const noexcept { 62 | return count; 63 | } 64 | 65 | constexpr const_pointer 66 | data() const noexcept { 67 | return reinterpret_cast(m_data); 68 | } 69 | 70 | constexpr pointer 71 | data() noexcept { 72 | return reinterpret_cast(m_data); 73 | } 74 | 75 | constexpr reference 76 | operator[](size_type index) noexcept { 77 | return m_data[index]; 78 | } 79 | 80 | constexpr const_reference 81 | operator[](size_type index) const noexcept { 82 | return m_data[index]; 83 | } 84 | }; 85 | 86 | public: 87 | 88 | using size_type = uint64_type; 89 | using word_type = uint32_type; 90 | using state_type = buffer; 91 | using block_type = buffer; 92 | using round_type = buffer; 93 | using output_type = buffer; 94 | 95 | constexpr 96 | SHA1() noexcept : m_state{0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0} { 97 | static_assert(state_bits == 160); 98 | } 99 | 100 | constexpr 101 | ~SHA1() noexcept { 102 | __builtin_memset(m_block.data(), 0, sizeof(block_type)); 103 | } 104 | 105 | constexpr size_type 106 | size() const noexcept { 107 | return m_count; 108 | } 109 | 110 | constexpr SHA1& 111 | update(size_type count, uint8_type input) noexcept { 112 | 113 | auto cursor = m_count % sizeof(block_type); 114 | auto excess = (cursor + count) % sizeof(block_type); 115 | auto blocks = (cursor + count) / sizeof(block_type); 116 | 117 | while (blocks-- != 0) { 118 | 119 | while (cursor < sizeof(block_type)) { 120 | m_block.data()[cursor++] = input; 121 | } 122 | 123 | cursor = (compress(m_block), 0); 124 | } 125 | 126 | while (cursor < excess) { 127 | m_block.data()[cursor++] = input; 128 | } 129 | 130 | return (m_count += count, *this); 131 | } 132 | 133 | constexpr SHA1& 134 | update(const uint8_type *input, size_type count) noexcept { 135 | 136 | auto cursor = m_count % sizeof(block_type); 137 | auto excess = (cursor + count) % sizeof(block_type); 138 | auto blocks = (cursor + count) / sizeof(block_type); 139 | 140 | while (blocks-- != 0) { 141 | 142 | while (cursor < sizeof(block_type)) { 143 | m_block.data()[cursor++] = *input++; 144 | } 145 | 146 | cursor = (compress(m_block), 0); 147 | } 148 | 149 | while (cursor < excess) { 150 | m_block.data()[cursor++] = *input++; 151 | } 152 | 153 | return (m_count += count, *this); 154 | } 155 | 156 | template constexpr SHA1& 157 | update(const input_type *input, size_type count) noexcept requires (__is_trivially_copyable(input_type)) { 158 | return update(reinterpret_cast(input), sizeof(input_type) * count); 159 | } 160 | 161 | template constexpr SHA1& 162 | update(const input_type (&input)[count]) noexcept requires (__is_trivially_copyable(input_type)) { 163 | return update(reinterpret_cast(input), sizeof(input_type) * count); 164 | } 165 | 166 | template constexpr SHA1& 167 | update(const input_type *begin, const input_type *end) noexcept requires (__is_trivially_copyable(input_type)) { 168 | return update(reinterpret_cast(begin), sizeof(input_type) * (end - begin)); 169 | } 170 | 171 | template constexpr SHA1& 172 | update(const input_type &input) noexcept requires (__is_trivially_copyable(input_type)) { 173 | return update(reinterpret_cast(&input), sizeof(input_type)); 174 | } 175 | 176 | constexpr SHA1& 177 | update(const char *input) noexcept { 178 | return update(reinterpret_cast(input), __builtin_strlen(input)); 179 | } 180 | 181 | template constexpr SHA1& 182 | update(const size_type count, input_type &&input) noexcept { 183 | for (size_type i = 0; i < count; ++i) update(static_cast(input)); return *this; 184 | } 185 | 186 | constexpr output_type 187 | digest() const noexcept { 188 | 189 | auto hasher = SHA1{*this}; 190 | 191 | hasher.update(size_type{1}, uint8_type{0x80}); 192 | 193 | auto length = hasher.size() % sizeof(block_type) + sizeof(size_type); 194 | auto factor = (length + sizeof(block_type) - 1) / sizeof(block_type); 195 | 196 | hasher.update(factor * sizeof(block_type) - length, uint8_type{0x00}); 197 | hasher.update(h2be(m_count << 3)); 198 | 199 | for (auto i = 0U; i < hasher.m_state.size(); ++i) { 200 | hasher.m_state[i] = h2be(hasher.m_state[i]); 201 | } 202 | 203 | return *reinterpret_cast(&hasher.m_state); 204 | } 205 | 206 | private: 207 | 208 | size_type m_count = {}; 209 | block_type m_block = {}; 210 | state_type m_state = {}; 211 | 212 | static constexpr uint32_type 213 | h2be(uint32_type value) noexcept { 214 | return __builtin_bswap32(value); 215 | } 216 | 217 | static constexpr uint64_type 218 | h2be(uint64_type value) noexcept { 219 | return __builtin_bswap64(value); 220 | } 221 | 222 | static constexpr uint32_type 223 | rotl(uint32_type value, int count) noexcept { 224 | return __builtin_rotateleft32(value, count); 225 | } 226 | 227 | static constexpr word_type 228 | bop150(word_type word1, word_type word2, word_type word3) noexcept { 229 | return word1 ^ word2 ^ word3; 230 | } 231 | 232 | static constexpr word_type 233 | bop202(word_type word1, word_type word2, word_type word3) noexcept { 234 | return (word1 & (word2 ^ word3)) ^ word3; 235 | } 236 | 237 | static constexpr word_type 238 | bop232(word_type word1, word_type word2, word_type word3) noexcept { 239 | return (word1 & word2) | ((word1 ^ word2) & word3); 240 | } 241 | 242 | static constexpr void 243 | unshift(state_type &state, word_type value) { 244 | 245 | state[4] = state[3]; 246 | state[3] = state[2]; 247 | state[2] = rotl(state[1], 30); 248 | state[1] = state[0]; 249 | state[0] = value; 250 | } 251 | 252 | constexpr void 253 | compress(const block_type &block) noexcept { 254 | 255 | round_type round; 256 | state_type state = m_state; 257 | 258 | for (auto i = 0U; i < block.size(); ++i) { 259 | round[i] = h2be(block[i]); 260 | } 261 | 262 | for (auto i = block.size(); i < round.size(); ++i) { 263 | round[i] = rotl(round[i - 16] ^ round[i - 14] ^ round[i - 8] ^ round[i - 3], 1); 264 | } 265 | 266 | for (auto i = 0; i < 20; ++i) { 267 | unshift(state, rotl(state[0], 5) + bop202(state[1], state[2], state[3]) + state[4] + round[i] + 0x5A827999); 268 | } 269 | 270 | for (auto i = 20; i < 40; ++i) { 271 | unshift(state, rotl(state[0], 5) + bop150(state[1], state[2], state[3]) + state[4] + round[i] + 0x6ED9EBA1); 272 | } 273 | 274 | for (auto i = 40; i < 60; ++i) { 275 | unshift(state, rotl(state[0], 5) + bop232(state[1], state[2], state[3]) + state[4] + round[i] + 0x8F1BBCDC); 276 | } 277 | 278 | for (auto i = 60; i < 80; ++i) { 279 | unshift(state, rotl(state[0], 5) + bop150(state[1], state[2], state[3]) + state[4] + round[i] + 0xCA62C1D6); 280 | } 281 | 282 | for (auto i = 0U; i < state.size(); ++i) { 283 | m_state[i] += state[i]; 284 | } 285 | } 286 | }; 287 | 288 | template constexpr decltype(auto) 289 | sha1(input_type &&...input) noexcept { 290 | return SHA1().update(static_cast(input)...).digest(); 291 | } 292 | } 293 | 294 | #if __INCLUDE_LEVEL__ 295 | 296 | #pragma once 297 | 298 | #else 299 | 300 | #include 301 | using namespace crypto; 302 | 303 | template constexpr bool 304 | operator==(const char (&left)[count], const right_type &right) noexcept { 305 | return count - 1 == sizeof(right_type) && __builtin_memcmp(&left, &right, sizeof(right_type)) == 0; 306 | } 307 | 308 | int 309 | main() { 310 | 311 | assert("\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09" == sha1("")); 312 | assert("\xa9\x99\x3e\x36\x47\x06\x81\x6a\xba\x3e\x25\x71\x78\x50\xc2\x6c\x9c\xd0\xd8\x9d" == sha1("abc")); 313 | assert("\x84\x98\x3e\x44\x1c\x3b\xd2\x6e\xba\xae\x4a\xa1\xf9\x51\x29\xe5\xe5\x46\x70\xf1" == sha1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")); 314 | assert("\xa4\x9b\x24\x46\xa0\x2c\x64\x5b\xf4\x19\xf9\x95\xb6\x70\x91\x25\x3a\x04\xa2\x59" == sha1("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")); 315 | assert("\x34\xaa\x97\x3c\xd4\xc4\xda\xa4\xf6\x1e\xeb\x2b\xdb\xad\x27\x31\x65\x34\x01\x6f" == sha1(1000000, 'a')); 316 | assert("\x77\x89\xf0\xc9\xef\x7b\xfc\x40\xd9\x33\x11\x14\x3d\xfb\xe6\x9e\x20\x17\xf5\x92" == sha1(16777216, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno")); 317 | 318 | return 0; 319 | } 320 | 321 | #endif 322 | -------------------------------------------------------------------------------- /md4.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * NAME 3 | * 4 | * md4 - message digest algorithm 4 5 | * 6 | * SYNOPSIS 7 | * 8 | * auto digest = crypto::MD4().update(...).digest(); 9 | * 10 | * DESCRIPTION 11 | * 12 | * MD4 (Message Digest Algorithm 4) is a cryptographic hash function, 13 | * that calculates a 128-bit hash value for a given input. MD4 is an 14 | * older algorithm that is now considered insecure and unsuitable for 15 | * cryptographic purposes. 16 | * 17 | * EXAMPLES 18 | * 19 | * #include 20 | * using namespace crypto; 21 | * 22 | * auto 23 | * hash(const auto &trivially_copyable_objects) { 24 | * 25 | * auto hasher = MD4(); 26 | * 27 | * for (const auto &object: trivially_copyable_objects) { 28 | * hasher.update(object); 29 | * } 30 | * 31 | * return md4(hasher.update("secret").digest()); 32 | * } 33 | * 34 | * COPYRIGHT 35 | * 36 | * Copyright 2022 Quasis - The MIT License 37 | */ 38 | 39 | namespace crypto { 40 | 41 | template 42 | class MD4 { 43 | 44 | using uint8_type = __UINT8_TYPE__; 45 | using uint16_type = __UINT16_TYPE__; 46 | using uint32_type = __UINT32_TYPE__; 47 | using uint64_type = __UINT64_TYPE__; 48 | 49 | template 50 | struct buffer { 51 | 52 | value_type m_data[count]; 53 | 54 | using size_type = decltype(sizeof(void*)); 55 | using pointer = uint8_type*; 56 | using const_pointer = const uint8_type*; 57 | using reference = value_type&; 58 | using const_reference = const value_type&; 59 | 60 | constexpr size_type 61 | size() const noexcept { 62 | return count; 63 | } 64 | 65 | constexpr const_pointer 66 | data() const noexcept { 67 | return reinterpret_cast(m_data); 68 | } 69 | 70 | constexpr pointer 71 | data() noexcept { 72 | return reinterpret_cast(m_data); 73 | } 74 | 75 | constexpr reference 76 | operator[](size_type index) noexcept { 77 | return m_data[index]; 78 | } 79 | 80 | constexpr const_reference 81 | operator[](size_type index) const noexcept { 82 | return m_data[index]; 83 | } 84 | }; 85 | 86 | public: 87 | 88 | using size_type = uint64_type; 89 | using word_type = uint32_type; 90 | using state_type = buffer; 91 | using block_type = buffer; 92 | using round_type = buffer; 93 | using output_type = buffer; 94 | 95 | constexpr 96 | MD4() noexcept : m_state{0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476} { 97 | static_assert(state_bits == 128); 98 | } 99 | 100 | constexpr 101 | ~MD4() noexcept { 102 | __builtin_memset(m_block.data(), 0, sizeof(block_type)); 103 | } 104 | 105 | constexpr size_type 106 | size() const noexcept { 107 | return m_count; 108 | } 109 | 110 | constexpr MD4& 111 | update(size_type count, uint8_type input) noexcept { 112 | 113 | auto cursor = m_count % sizeof(block_type); 114 | auto excess = (cursor + count) % sizeof(block_type); 115 | auto blocks = (cursor + count) / sizeof(block_type); 116 | 117 | while (blocks-- != 0) { 118 | 119 | while (cursor < sizeof(block_type)) { 120 | m_block.data()[cursor++] = input; 121 | } 122 | 123 | cursor = (compress(m_block), 0); 124 | } 125 | 126 | while (cursor < excess) { 127 | m_block.data()[cursor++] = input; 128 | } 129 | 130 | return (m_count += count, *this); 131 | } 132 | 133 | constexpr MD4& 134 | update(const uint8_type *input, size_type count) noexcept { 135 | 136 | auto cursor = m_count % sizeof(block_type); 137 | auto excess = (cursor + count) % sizeof(block_type); 138 | auto blocks = (cursor + count) / sizeof(block_type); 139 | 140 | while (blocks-- != 0) { 141 | 142 | while (cursor < sizeof(block_type)) { 143 | m_block.data()[cursor++] = *input++; 144 | } 145 | 146 | cursor = (compress(m_block), 0); 147 | } 148 | 149 | while (cursor < excess) { 150 | m_block.data()[cursor++] = *input++; 151 | } 152 | 153 | return (m_count += count, *this); 154 | } 155 | 156 | template constexpr MD4& 157 | update(const input_type *input, size_type count) noexcept requires (__is_trivially_copyable(input_type)) { 158 | return update(reinterpret_cast(input), sizeof(input_type) * count); 159 | } 160 | 161 | template constexpr MD4& 162 | update(const input_type (&input)[count]) noexcept requires (__is_trivially_copyable(input_type)) { 163 | return update(reinterpret_cast(input), sizeof(input_type) * count); 164 | } 165 | 166 | template constexpr MD4& 167 | update(const input_type *begin, const input_type *end) noexcept requires (__is_trivially_copyable(input_type)) { 168 | return update(reinterpret_cast(begin), sizeof(input_type) * (end - begin)); 169 | } 170 | 171 | template constexpr MD4& 172 | update(const input_type &input) noexcept requires (__is_trivially_copyable(input_type)) { 173 | return update(reinterpret_cast(&input), sizeof(input_type)); 174 | } 175 | 176 | constexpr MD4& 177 | update(const char *input) noexcept { 178 | return update(reinterpret_cast(input), __builtin_strlen(input)); 179 | } 180 | 181 | template constexpr MD4& 182 | update(const size_type count, input_type &&input) noexcept { 183 | for (size_type i = 0; i < count; ++i) update(static_cast(input)); return *this; 184 | } 185 | 186 | constexpr output_type 187 | digest() const noexcept { 188 | 189 | auto hasher = MD4{*this}; 190 | 191 | hasher.update(size_type{1}, uint8_type{0x80}); 192 | 193 | auto length = hasher.size() % sizeof(block_type) + sizeof(size_type); 194 | auto factor = (length + sizeof(block_type) - 1) / sizeof(block_type); 195 | 196 | hasher.update(factor * sizeof(block_type) - length, uint8_type{0x00}); 197 | hasher.update(m_count << 3); 198 | 199 | return *reinterpret_cast(&hasher.m_state); 200 | } 201 | 202 | private: 203 | 204 | size_type m_count = {}; 205 | block_type m_block = {}; 206 | state_type m_state = {}; 207 | 208 | static constexpr uint32_type 209 | rotl(uint32_type value, int count) noexcept { 210 | return __builtin_rotateleft32(value, count); 211 | } 212 | 213 | static constexpr word_type 214 | bop150(word_type word1, word_type word2, word_type word3) noexcept { 215 | return word1 ^ word2 ^ word3; 216 | } 217 | 218 | static constexpr word_type 219 | bop202(word_type word1, word_type word2, word_type word3) noexcept { 220 | return (word1 & (word2 ^ word3)) ^ word3; 221 | } 222 | 223 | static constexpr word_type 224 | bop232(word_type word1, word_type word2, word_type word3) noexcept { 225 | return (word1 & word2) | ((word1 ^ word2) & word3); 226 | } 227 | 228 | static constexpr void 229 | unshift(state_type &state, word_type value) { 230 | 231 | state[0] = state[3]; 232 | state[3] = state[2]; 233 | state[2] = state[1]; 234 | state[1] = value; 235 | } 236 | 237 | constexpr void 238 | compress(const block_type &block) noexcept { 239 | 240 | state_type state = m_state; 241 | 242 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x00000000 + block[ 0], 3)); 243 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x00000000 + block[ 1], 7)); 244 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x00000000 + block[ 2], 11)); 245 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x00000000 + block[ 3], 19)); 246 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x00000000 + block[ 4], 3)); 247 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x00000000 + block[ 5], 7)); 248 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x00000000 + block[ 6], 11)); 249 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x00000000 + block[ 7], 19)); 250 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x00000000 + block[ 8], 3)); 251 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x00000000 + block[ 9], 7)); 252 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x00000000 + block[10], 11)); 253 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x00000000 + block[11], 19)); 254 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x00000000 + block[12], 3)); 255 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x00000000 + block[13], 7)); 256 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x00000000 + block[14], 11)); 257 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x00000000 + block[15], 19)); 258 | 259 | unshift(state, rotl(state[0] + bop232(state[1], state[2], state[3]) + 0x5A827999 + block[ 0], 3)); 260 | unshift(state, rotl(state[0] + bop232(state[1], state[2], state[3]) + 0x5A827999 + block[ 4], 5)); 261 | unshift(state, rotl(state[0] + bop232(state[1], state[2], state[3]) + 0x5A827999 + block[ 8], 9)); 262 | unshift(state, rotl(state[0] + bop232(state[1], state[2], state[3]) + 0x5A827999 + block[12], 13)); 263 | unshift(state, rotl(state[0] + bop232(state[1], state[2], state[3]) + 0x5A827999 + block[ 1], 3)); 264 | unshift(state, rotl(state[0] + bop232(state[1], state[2], state[3]) + 0x5A827999 + block[ 5], 5)); 265 | unshift(state, rotl(state[0] + bop232(state[1], state[2], state[3]) + 0x5A827999 + block[ 9], 9)); 266 | unshift(state, rotl(state[0] + bop232(state[1], state[2], state[3]) + 0x5A827999 + block[13], 13)); 267 | unshift(state, rotl(state[0] + bop232(state[1], state[2], state[3]) + 0x5A827999 + block[ 2], 3)); 268 | unshift(state, rotl(state[0] + bop232(state[1], state[2], state[3]) + 0x5A827999 + block[ 6], 5)); 269 | unshift(state, rotl(state[0] + bop232(state[1], state[2], state[3]) + 0x5A827999 + block[10], 9)); 270 | unshift(state, rotl(state[0] + bop232(state[1], state[2], state[3]) + 0x5A827999 + block[14], 13)); 271 | unshift(state, rotl(state[0] + bop232(state[1], state[2], state[3]) + 0x5A827999 + block[ 3], 3)); 272 | unshift(state, rotl(state[0] + bop232(state[1], state[2], state[3]) + 0x5A827999 + block[ 7], 5)); 273 | unshift(state, rotl(state[0] + bop232(state[1], state[2], state[3]) + 0x5A827999 + block[11], 9)); 274 | unshift(state, rotl(state[0] + bop232(state[1], state[2], state[3]) + 0x5A827999 + block[15], 13)); 275 | 276 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x6ED9EBA1 + block[ 0], 3)); 277 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x6ED9EBA1 + block[ 8], 9)); 278 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x6ED9EBA1 + block[ 4], 11)); 279 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x6ED9EBA1 + block[12], 15)); 280 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x6ED9EBA1 + block[ 2], 3)); 281 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x6ED9EBA1 + block[10], 9)); 282 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x6ED9EBA1 + block[ 6], 11)); 283 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x6ED9EBA1 + block[14], 15)); 284 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x6ED9EBA1 + block[ 1], 3)); 285 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x6ED9EBA1 + block[ 9], 9)); 286 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x6ED9EBA1 + block[ 5], 11)); 287 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x6ED9EBA1 + block[13], 15)); 288 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x6ED9EBA1 + block[ 3], 3)); 289 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x6ED9EBA1 + block[11], 9)); 290 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x6ED9EBA1 + block[ 7], 11)); 291 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x6ED9EBA1 + block[15], 15)); 292 | 293 | for (auto i = 0U; i < state.size(); ++i) { 294 | m_state[i] += state[i]; 295 | } 296 | } 297 | }; 298 | 299 | template constexpr decltype(auto) 300 | md4(input_type &&...input) noexcept { 301 | return MD4().update(static_cast(input)...).digest(); 302 | } 303 | } 304 | 305 | #if __INCLUDE_LEVEL__ 306 | 307 | #pragma once 308 | 309 | #else 310 | 311 | #include 312 | using namespace crypto; 313 | 314 | template constexpr bool 315 | operator==(const char (&left)[count], const right_type &right) noexcept { 316 | return count - 1 == sizeof(right_type) && __builtin_memcmp(&left, &right, sizeof(right_type)) == 0; 317 | } 318 | 319 | int 320 | main() { 321 | 322 | assert("\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31\xb7\x3c\x59\xd7\xe0\xc0\x89\xc0" == md4("")); 323 | assert("\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46\x24\x5e\x05\xfb\xdb\xd6\xfb\x24" == md4("a")); 324 | assert("\xa4\x48\x01\x7a\xaf\x21\xd8\x52\x5f\xc1\x0a\xe8\x7a\xa6\x72\x9d" == md4("abc")); 325 | assert("\xd9\x13\x0a\x81\x64\x54\x9f\xe8\x18\x87\x48\x06\xe1\xc7\x01\x4b" == md4("message digest")); 326 | assert("\xd7\x9e\x1c\x30\x8a\xa5\xbb\xcd\xee\xa8\xed\x63\xdf\x41\x2d\xa9" == md4("abcdefghijklmnopqrstuvwxyz")); 327 | assert("\x46\x91\xa9\xec\x81\xb1\xa6\xbd\x1a\xb8\x55\x72\x40\xb2\x45\xc5" == md4("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")); 328 | assert("\x04\x3f\x85\x82\xf2\x41\xdb\x35\x1c\xe6\x27\xe1\x53\xe7\xf0\xe4" == md4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")); 329 | assert("\xe3\x3b\x4d\xdc\x9c\x38\xf2\x19\x9c\x3e\x7b\x16\x4f\xcc\x05\x36" == md4("12345678901234567890123456789012345678901234567890123456789012345678901234567890")); 330 | assert("\xbb\xce\x80\xcc\x6b\xb6\x5e\x5c\x67\x45\xe3\x0d\x4e\xec\xa9\xa4" == md4(1000000, 'a')); 331 | 332 | return 0; 333 | } 334 | 335 | #endif 336 | -------------------------------------------------------------------------------- /md5.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * NAME 3 | * 4 | * md5 - message digest algorithm 5 5 | * 6 | * SYNOPSIS 7 | * 8 | * auto digest = MD5().update(...).digest(); 9 | * 10 | * DESCRIPTION 11 | * 12 | * MD5 (Message Digest Algorithm 5) is a cryptographic hash function, 13 | * that calculates a 128-bit hash value for a given input. MD5 is an 14 | * older algorithm that is now considered insecure and unsuitable for 15 | * cryptographic purposes. 16 | * 17 | * EXAMPLES 18 | * 19 | * #include 20 | * using namespace crypto; 21 | * 22 | * auto 23 | * hash(const auto &trivially_copyable_objects) { 24 | * 25 | * auto hasher = MD5(); 26 | * 27 | * for (const auto &object: trivially_copyable_objects) { 28 | * hasher.update(object); 29 | * } 30 | * 31 | * return md5(hasher.update("secret").digest()); 32 | * } 33 | * 34 | * COPYRIGHT 35 | * 36 | * Copyright 2022 Quasis - The MIT License 37 | */ 38 | 39 | namespace crypto { 40 | 41 | template 42 | class MD5 { 43 | 44 | using uint8_type = __UINT8_TYPE__; 45 | using uint16_type = __UINT16_TYPE__; 46 | using uint32_type = __UINT32_TYPE__; 47 | using uint64_type = __UINT64_TYPE__; 48 | 49 | template 50 | struct buffer { 51 | 52 | value_type m_data[count]; 53 | 54 | using size_type = decltype(sizeof(void*)); 55 | using pointer = uint8_type*; 56 | using const_pointer = const uint8_type*; 57 | using reference = value_type&; 58 | using const_reference = const value_type&; 59 | 60 | constexpr size_type 61 | size() const noexcept { 62 | return count; 63 | } 64 | 65 | constexpr const_pointer 66 | data() const noexcept { 67 | return reinterpret_cast(m_data); 68 | } 69 | 70 | constexpr pointer 71 | data() noexcept { 72 | return reinterpret_cast(m_data); 73 | } 74 | 75 | constexpr reference 76 | operator[](size_type index) noexcept { 77 | return m_data[index]; 78 | } 79 | 80 | constexpr const_reference 81 | operator[](size_type index) const noexcept { 82 | return m_data[index]; 83 | } 84 | }; 85 | 86 | public: 87 | 88 | using size_type = uint64_type; 89 | using word_type = uint32_type; 90 | using state_type = buffer; 91 | using block_type = buffer; 92 | using round_type = buffer; 93 | using output_type = buffer; 94 | 95 | constexpr 96 | MD5() noexcept : m_state{0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476} { 97 | static_assert(state_bits == 128); 98 | } 99 | 100 | constexpr 101 | ~MD5() noexcept { 102 | __builtin_memset(m_block.data(), 0, sizeof(block_type)); 103 | } 104 | 105 | constexpr size_type 106 | size() const noexcept { 107 | return m_count; 108 | } 109 | 110 | constexpr MD5& 111 | update(size_type count, uint8_type input) noexcept { 112 | 113 | auto cursor = m_count % sizeof(block_type); 114 | auto excess = (cursor + count) % sizeof(block_type); 115 | auto blocks = (cursor + count) / sizeof(block_type); 116 | 117 | while (blocks-- != 0) { 118 | 119 | while (cursor < sizeof(block_type)) { 120 | m_block.data()[cursor++] = input; 121 | } 122 | 123 | cursor = (compress(m_block), 0); 124 | } 125 | 126 | while (cursor < excess) { 127 | m_block.data()[cursor++] = input; 128 | } 129 | 130 | return (m_count += count, *this); 131 | } 132 | 133 | constexpr MD5& 134 | update(const uint8_type *input, size_type count) noexcept { 135 | 136 | auto cursor = m_count % sizeof(block_type); 137 | auto excess = (cursor + count) % sizeof(block_type); 138 | auto blocks = (cursor + count) / sizeof(block_type); 139 | 140 | while (blocks-- != 0) { 141 | 142 | while (cursor < sizeof(block_type)) { 143 | m_block.data()[cursor++] = *input++; 144 | } 145 | 146 | cursor = (compress(m_block), 0); 147 | } 148 | 149 | while (cursor < excess) { 150 | m_block.data()[cursor++] = *input++; 151 | } 152 | 153 | return (m_count += count, *this); 154 | } 155 | 156 | template constexpr MD5& 157 | update(const input_type *input, size_type count) noexcept requires (__is_trivially_copyable(input_type)) { 158 | return update(reinterpret_cast(input), sizeof(input_type) * count); 159 | } 160 | 161 | template constexpr MD5& 162 | update(const input_type (&input)[count]) noexcept requires (__is_trivially_copyable(input_type)) { 163 | return update(reinterpret_cast(input), sizeof(input_type) * count); 164 | } 165 | 166 | template constexpr MD5& 167 | update(const input_type *begin, const input_type *end) noexcept requires (__is_trivially_copyable(input_type)) { 168 | return update(reinterpret_cast(begin), sizeof(input_type) * (end - begin)); 169 | } 170 | 171 | template constexpr MD5& 172 | update(const input_type &input) noexcept requires (__is_trivially_copyable(input_type)) { 173 | return update(reinterpret_cast(&input), sizeof(input_type)); 174 | } 175 | 176 | constexpr MD5& 177 | update(const char *input) noexcept { 178 | return update(reinterpret_cast(input), __builtin_strlen(input)); 179 | } 180 | 181 | template constexpr MD5& 182 | update(const size_type count, input_type &&input) noexcept { 183 | for (size_type i = 0; i < count; ++i) update(static_cast(input)); return *this; 184 | } 185 | 186 | constexpr output_type 187 | digest() const noexcept { 188 | 189 | auto hasher = MD5{*this}; 190 | 191 | hasher.update(size_type{1}, uint8_type{0x80}); 192 | 193 | auto length = hasher.size() % sizeof(block_type) + sizeof(size_type); 194 | auto factor = (length + sizeof(block_type) - 1) / sizeof(block_type); 195 | 196 | hasher.update(factor * sizeof(block_type) - length, uint8_type{0x00}); 197 | hasher.update(m_count << 3); 198 | 199 | return *reinterpret_cast(&hasher.m_state); 200 | } 201 | 202 | private: 203 | 204 | size_type m_count = {}; 205 | block_type m_block = {}; 206 | state_type m_state = {}; 207 | 208 | static constexpr uint32_type 209 | rotl(uint32_type value, int count) noexcept { 210 | return __builtin_rotateleft32(value, count); 211 | } 212 | 213 | static constexpr word_type 214 | bop057(word_type word1, word_type word2, word_type word3) noexcept { 215 | return (word1 | ~word3) ^ word2; 216 | } 217 | 218 | static constexpr word_type 219 | bop150(word_type word1, word_type word2, word_type word3) noexcept { 220 | return word1 ^ word2 ^ word3; 221 | } 222 | 223 | static constexpr word_type 224 | bop202(word_type word1, word_type word2, word_type word3) noexcept { 225 | return (word1 & (word2 ^ word3)) ^ word3; 226 | } 227 | 228 | static constexpr word_type 229 | bop228(word_type word1, word_type word2, word_type word3) noexcept { 230 | return (word1 & word3) | (word2 & ~word3); 231 | } 232 | 233 | static constexpr void 234 | unshift(state_type &state, word_type value) { 235 | 236 | state[0] = state[3]; 237 | state[3] = state[2]; 238 | state[2] = state[1]; 239 | state[1] += value; 240 | } 241 | 242 | constexpr void 243 | compress(const block_type &block) noexcept { 244 | 245 | state_type state = m_state; 246 | 247 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0xD76AA478 + block[ 0], 7)); 248 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0xE8C7B756 + block[ 1], 12)); 249 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x242070DB + block[ 2], 17)); 250 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0xC1BDCEEE + block[ 3], 22)); 251 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0xF57C0FAF + block[ 4], 7)); 252 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x4787C62A + block[ 5], 12)); 253 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0xA8304613 + block[ 6], 17)); 254 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0xFD469501 + block[ 7], 22)); 255 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x698098D8 + block[ 8], 7)); 256 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x8B44F7AF + block[ 9], 12)); 257 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0xFFFF5BB1 + block[10], 17)); 258 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x895CD7BE + block[11], 22)); 259 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x6B901122 + block[12], 7)); 260 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0xFD987193 + block[13], 12)); 261 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0xA679438E + block[14], 17)); 262 | unshift(state, rotl(state[0] + bop202(state[1], state[2], state[3]) + 0x49B40821 + block[15], 22)); 263 | 264 | unshift(state, rotl(state[0] + bop228(state[1], state[2], state[3]) + 0xF61E2562 + block[ 1], 5)); 265 | unshift(state, rotl(state[0] + bop228(state[1], state[2], state[3]) + 0xC040B340 + block[ 6], 9)); 266 | unshift(state, rotl(state[0] + bop228(state[1], state[2], state[3]) + 0x265E5A51 + block[11], 14)); 267 | unshift(state, rotl(state[0] + bop228(state[1], state[2], state[3]) + 0xE9B6C7AA + block[ 0], 20)); 268 | unshift(state, rotl(state[0] + bop228(state[1], state[2], state[3]) + 0xD62F105D + block[ 5], 5)); 269 | unshift(state, rotl(state[0] + bop228(state[1], state[2], state[3]) + 0x02441453 + block[10], 9)); 270 | unshift(state, rotl(state[0] + bop228(state[1], state[2], state[3]) + 0xD8A1E681 + block[15], 14)); 271 | unshift(state, rotl(state[0] + bop228(state[1], state[2], state[3]) + 0xE7D3FBC8 + block[ 4], 20)); 272 | unshift(state, rotl(state[0] + bop228(state[1], state[2], state[3]) + 0x21E1CDE6 + block[ 9], 5)); 273 | unshift(state, rotl(state[0] + bop228(state[1], state[2], state[3]) + 0xC33707D6 + block[14], 9)); 274 | unshift(state, rotl(state[0] + bop228(state[1], state[2], state[3]) + 0xF4D50D87 + block[ 3], 14)); 275 | unshift(state, rotl(state[0] + bop228(state[1], state[2], state[3]) + 0x455A14ED + block[ 8], 20)); 276 | unshift(state, rotl(state[0] + bop228(state[1], state[2], state[3]) + 0xA9E3E905 + block[13], 5)); 277 | unshift(state, rotl(state[0] + bop228(state[1], state[2], state[3]) + 0xFCEFA3F8 + block[ 2], 9)); 278 | unshift(state, rotl(state[0] + bop228(state[1], state[2], state[3]) + 0x676F02D9 + block[ 7], 14)); 279 | unshift(state, rotl(state[0] + bop228(state[1], state[2], state[3]) + 0x8D2A4C8A + block[12], 20)); 280 | 281 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0xFFFA3942 + block[ 5], 4)); 282 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x8771F681 + block[ 8], 11)); 283 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x6D9D6122 + block[11], 16)); 284 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0xFDE5380C + block[14], 23)); 285 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0xA4BEEA44 + block[ 1], 4)); 286 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x4BDECFA9 + block[ 4], 11)); 287 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0xF6BB4B60 + block[ 7], 16)); 288 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0xBEBFBC70 + block[10], 23)); 289 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x289B7EC6 + block[13], 4)); 290 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0xEAA127FA + block[ 0], 11)); 291 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0xD4EF3085 + block[ 3], 16)); 292 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x04881D05 + block[ 6], 23)); 293 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0xD9D4D039 + block[ 9], 4)); 294 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0xE6DB99E5 + block[12], 11)); 295 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0x1FA27CF8 + block[15], 16)); 296 | unshift(state, rotl(state[0] + bop150(state[1], state[2], state[3]) + 0xC4AC5665 + block[ 2], 23)); 297 | 298 | unshift(state, rotl(state[0] + bop057(state[1], state[2], state[3]) + 0xF4292244 + block[ 0], 6)); 299 | unshift(state, rotl(state[0] + bop057(state[1], state[2], state[3]) + 0x432AFF97 + block[ 7], 10)); 300 | unshift(state, rotl(state[0] + bop057(state[1], state[2], state[3]) + 0xAB9423A7 + block[14], 15)); 301 | unshift(state, rotl(state[0] + bop057(state[1], state[2], state[3]) + 0xFC93A039 + block[ 5], 21)); 302 | unshift(state, rotl(state[0] + bop057(state[1], state[2], state[3]) + 0x655B59C3 + block[12], 6)); 303 | unshift(state, rotl(state[0] + bop057(state[1], state[2], state[3]) + 0x8F0CCC92 + block[ 3], 10)); 304 | unshift(state, rotl(state[0] + bop057(state[1], state[2], state[3]) + 0xFFEFF47D + block[10], 15)); 305 | unshift(state, rotl(state[0] + bop057(state[1], state[2], state[3]) + 0x85845DD1 + block[ 1], 21)); 306 | unshift(state, rotl(state[0] + bop057(state[1], state[2], state[3]) + 0x6FA87E4F + block[ 8], 6)); 307 | unshift(state, rotl(state[0] + bop057(state[1], state[2], state[3]) + 0xFE2CE6E0 + block[15], 10)); 308 | unshift(state, rotl(state[0] + bop057(state[1], state[2], state[3]) + 0xA3014314 + block[ 6], 15)); 309 | unshift(state, rotl(state[0] + bop057(state[1], state[2], state[3]) + 0x4E0811A1 + block[13], 21)); 310 | unshift(state, rotl(state[0] + bop057(state[1], state[2], state[3]) + 0xF7537E82 + block[ 4], 6)); 311 | unshift(state, rotl(state[0] + bop057(state[1], state[2], state[3]) + 0xBD3AF235 + block[11], 10)); 312 | unshift(state, rotl(state[0] + bop057(state[1], state[2], state[3]) + 0x2AD7D2BB + block[ 2], 15)); 313 | unshift(state, rotl(state[0] + bop057(state[1], state[2], state[3]) + 0xEB86D391 + block[ 9], 21)); 314 | 315 | for (auto i = 0U; i < state.size(); ++i) { 316 | m_state[i] += state[i]; 317 | } 318 | } 319 | }; 320 | 321 | template constexpr decltype(auto) 322 | md5(input_type &&...input) noexcept { 323 | return MD5().update(static_cast(input)...).digest(); 324 | } 325 | } 326 | 327 | #if __INCLUDE_LEVEL__ 328 | 329 | #pragma once 330 | 331 | #else 332 | 333 | #include 334 | using namespace crypto; 335 | 336 | template constexpr bool 337 | operator==(const char (&left)[count], const right_type &right) noexcept { 338 | return count - 1 == sizeof(right_type) && __builtin_memcmp(&left, &right, sizeof(right_type)) == 0; 339 | } 340 | 341 | int 342 | main() { 343 | 344 | assert("\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42\x7e" == md5("")); 345 | assert("\x0c\xc1\x75\xb9\xc0\xf1\xb6\xa8\x31\xc3\x99\xe2\x69\x77\x26\x61" == md5("a")); 346 | assert("\x90\x01\x50\x98\x3c\xd2\x4f\xb0\xd6\x96\x3f\x7d\x28\xe1\x7f\x72" == md5("abc")); 347 | assert("\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d\x52\x5a\x2f\x31\xaa\xf1\x61\xd0" == md5("message digest")); 348 | assert("\xc3\xfc\xd3\xd7\x61\x92\xe4\x00\x7d\xfb\x49\x6c\xca\x67\xe1\x3b" == md5("abcdefghijklmnopqrstuvwxyz")); 349 | assert("\x82\x15\xef\x07\x96\xa2\x0b\xca\xaa\xe1\x16\xd3\x87\x6c\x66\x4a" == md5("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")); 350 | assert("\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f" == md5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")); 351 | assert("\x57\xed\xf4\xa2\x2b\xe3\xc9\x55\xac\x49\xda\x2e\x21\x07\xb6\x7a" == md5("12345678901234567890123456789012345678901234567890123456789012345678901234567890")); 352 | assert("\x77\x07\xd6\xae\x4e\x02\x7c\x70\xee\xa2\xa9\x35\xc2\x29\x6f\x21" == md5(1000000, 'a')); 353 | 354 | return 0; 355 | } 356 | 357 | #endif 358 | -------------------------------------------------------------------------------- /hmac.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * NAME 3 | * 4 | * hmac - hash-based message authentication code 5 | * 6 | * SYNOPSIS 7 | * 8 | * auto digest = HMAC<...>(key).update(...).digest(); 9 | * 10 | * DESCRIPTION 11 | * 12 | * HMAC (Hash-based Message Authentication Code) is a specific type 13 | * of message authentication code that provides a way to verify the 14 | * integrity and authenticity of a message/data transmission using 15 | * a cryptographic hash function and a secret key. HMAC is widely 16 | * used in various security protocols and applications, including 17 | * SSL/TLS, IPsec, SSH, and OAuth. 18 | * 19 | * EXAMPLES 20 | * 21 | * #include 22 | * #include 23 | * #include 24 | * using namespace crypto; 25 | * 26 | * auto 27 | * hash(const auto &trivially_copyable_objects) { 28 | * 29 | * auto hasher = HMAC>("secret 1"); 30 | * 31 | * for (const auto &object: trivially_copyable_objects) { 32 | * hasher.update(object); 33 | * } 34 | * 35 | * return hmac>("secret 2", hasher.digest()); 36 | * } 37 | * 38 | * COPYRIGHT 39 | * 40 | * Copyright 2022 Quasis - The MIT License 41 | */ 42 | 43 | namespace crypto { 44 | 45 | template 46 | class HMAC { 47 | 48 | using uint8_type = __UINT8_TYPE__; 49 | 50 | public: 51 | 52 | using size_type = typename hash_type::size_type; 53 | using word_type = typename hash_type::word_type; 54 | using state_type = typename hash_type::state_type; 55 | using block_type = typename hash_type::block_type; 56 | using output_type = typename hash_type::output_type; 57 | 58 | constexpr 59 | HMAC(const uint8_type *input, size_type count) noexcept { 60 | 61 | uint8_type secret[sizeof(block_type)] = {}; 62 | 63 | if (count > sizeof(block_type)) { 64 | *reinterpret_cast(secret) = hash_type{}.update(input, count).digest(); 65 | } 66 | else { 67 | __builtin_memcpy(&secret, input, count); 68 | } 69 | 70 | for (size_type i = 0; i < sizeof(block_type); ++i) { 71 | m_seed[i] = 0x5C ^ secret[i]; secret[i] ^= 0x36; 72 | } 73 | 74 | m_hash.update(secret); 75 | __builtin_memset(&secret, 0x00, sizeof(block_type)); 76 | } 77 | 78 | template constexpr 79 | HMAC(const input_type *input, size_type count) noexcept requires (__is_trivially_copyable(input_type)) : 80 | HMAC(reinterpret_cast(input), sizeof(input_type) * count) { 81 | } 82 | 83 | template constexpr 84 | HMAC(const input_type (&input)[count]) noexcept requires (__is_trivially_copyable(input_type)) : 85 | HMAC(reinterpret_cast(input), sizeof(input_type) * count) { 86 | } 87 | 88 | template constexpr 89 | HMAC(const input_type *begin, const input_type *end) noexcept requires (__is_trivially_copyable(input_type)) : 90 | HMAC(reinterpret_cast(begin), sizeof(input_type) * (end - begin)) { 91 | } 92 | 93 | template constexpr 94 | HMAC(const input_type &input) noexcept requires (__is_trivially_copyable(input_type)) : 95 | HMAC(reinterpret_cast(&input), sizeof(input_type)) { 96 | } 97 | 98 | constexpr 99 | HMAC(const char *input) noexcept : 100 | HMAC(reinterpret_cast(input), __builtin_strlen(input)) { 101 | } 102 | 103 | constexpr 104 | ~HMAC() noexcept { 105 | __builtin_memset(&m_seed, 0x00, sizeof(block_type)); 106 | } 107 | 108 | constexpr size_type 109 | capacity() const noexcept { 110 | return m_hash.capacity(); 111 | } 112 | 113 | constexpr size_type 114 | size() const noexcept { 115 | return m_hash.size(); 116 | } 117 | 118 | template constexpr HMAC& 119 | update(input_type &&...input) noexcept { 120 | return (m_hash.update(static_cast(input)...), *this); 121 | } 122 | 123 | constexpr output_type 124 | digest() const noexcept { 125 | return hash_type{}.update(m_seed).update(m_hash.digest()).digest(); 126 | } 127 | 128 | private: 129 | 130 | hash_type m_hash; 131 | uint8_type m_seed[sizeof(block_type)]; 132 | }; 133 | 134 | template constexpr decltype(auto) 135 | hmac(key_type &&key, input_type &&...input) noexcept { 136 | return HMAC(static_cast(key)).update(static_cast(input)...).digest(); 137 | } 138 | } 139 | 140 | #if __INCLUDE_LEVEL__ 141 | 142 | #pragma once 143 | 144 | #else 145 | 146 | #include "md4.hh" 147 | #include "md5.hh" 148 | #include "rmd.hh" 149 | #include "sha1.hh" 150 | #include "sha2.hh" 151 | #include 152 | using namespace crypto; 153 | 154 | template constexpr bool 155 | operator==(const char (&left)[count], const right_type &right) noexcept { 156 | return count - 1 == sizeof(right_type) && __builtin_memcmp(&left, &right, sizeof(right_type)) == 0; 157 | } 158 | 159 | int 160 | main() { 161 | 162 | assert(("\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d" == hmac>("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", "Hi There"))); 163 | assert(("\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38" == hmac>("Jefe", "what do ya want for nothing?"))); 164 | assert(("\x56\xbe\x34\x52\x1d\x14\x4c\x88\xdb\xb8\xc7\x33\xf0\xe8\xb3\xf6" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 50, '\xdd'))); 165 | assert(("\x69\x7e\xaf\x0a\xca\x3a\x3a\xea\x3a\x75\x16\x47\x46\xff\xaa\x79" == hmac>("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", 50, '\xcd'))); 166 | assert(("\x6b\x1a\xb7\xfe\x4b\xd7\xbf\x8f\x0b\x62\xe6\xce\x61\xb9\xd0\xcd" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "Test Using Larger Than Block-Size Key - Hash Key First"))); 167 | assert(("\x6f\x63\x0f\xad\x67\xcd\xa0\xee\x1f\xb1\xf5\x62\xdb\x3a\xa5\x3e" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"))); 168 | 169 | assert(("\xfb\xf6\x1f\x94\x92\xaa\x4b\xbf\x81\xc1\x72\xe8\x4e\x07\x34\xdb" == hmac>("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", "Hi There"))); 170 | assert(("\x87\x5f\x82\x88\x62\xb6\xb3\x34\xb4\x27\xc5\x5f\x9f\x7f\xf0\x9b" == hmac>("Jefe", "what do ya want for nothing?"))); 171 | assert(("\x09\xf0\xb2\x84\x6d\x2f\x54\x3d\xa3\x63\xcb\xec\x8d\x62\xa3\x8d" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 50, '\xdd'))); 172 | assert(("\xbd\xbb\xd7\xcf\x03\xe4\x4b\x5a\xa6\x0a\xf8\x15\xbe\x4d\x22\x94" == hmac>("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", 50, '\xcd'))); 173 | assert(("\xdc\x73\x29\x28\xde\x98\x10\x4a\x1f\x59\xd3\x73\xc1\x50\xac\xbb" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "Test Using Larger Than Block-Size Key - Hash Key First"))); 174 | assert(("\x5c\x6b\xec\x96\x79\x3e\x16\xd4\x06\x90\xc2\x37\x63\x5f\x30\xc5" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"))); 175 | 176 | assert(("\x24\xcb\x4b\xd6\x7d\x20\xfc\x1a\x5d\x2e\xd7\x73\x2d\xcc\x39\x37\x7f\x0a\x56\x68" == hmac>("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", "Hi There"))); 177 | assert(("\xdd\xa6\xc0\x21\x3a\x48\x5a\x9e\x24\xf4\x74\x20\x64\xa7\xf0\x33\xb4\x3c\x40\x69" == hmac>("Jefe", "what do ya want for nothing?"))); 178 | assert(("\xb0\xb1\x05\x36\x0d\xe7\x59\x96\x0a\xb4\xf3\x52\x98\xe1\x16\xe2\x95\xd8\xe7\xc1" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 50, '\xdd'))); 179 | assert(("\xd5\xca\x86\x2f\x4d\x21\xd5\xe6\x10\xe1\x8b\x4c\xf1\xbe\xb9\x7a\x43\x65\xec\xf4" == hmac>("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", 50, '\xcd'))); 180 | assert(("\x64\x66\xca\x07\xac\x5e\xac\x29\xe1\xbd\x52\x3e\x5a\xda\x76\x05\xb7\x91\xfd\x8b" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "Test Using Larger Than Block-Size Key - Hash Key First"))); 181 | assert(("\x69\xea\x60\x79\x8d\x71\x61\x6c\xce\x5f\xd0\x87\x1e\x23\x75\x4c\xd7\x5d\x5a\x0a" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"))); 182 | 183 | assert(("\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00" == hmac>("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", "Hi There"))); 184 | assert(("\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79" == hmac>("Jefe", "what do ya want for nothing?"))); 185 | assert(("\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 50, '\xdd'))); 186 | assert(("\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda" == hmac>("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", 50, '\xcd'))); 187 | assert(("\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "Test Using Larger Than Block-Size Key - Hash Key First"))); 188 | assert(("\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"))); 189 | 190 | assert(("\x89\x6f\xb1\x12\x8a\xbb\xdf\x19\x68\x32\x10\x7c\xd4\x9d\xf3\x3f\x47\xb4\xb1\x16\x99\x12\xba\x4f\x53\x68\x4b\x22" == hmac>("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", "Hi There"))); 191 | assert(("\xa3\x0e\x01\x09\x8b\xc6\xdb\xbf\x45\x69\x0f\x3a\x7e\x9e\x6d\x0f\x8b\xbe\xa2\xa3\x9e\x61\x48\x00\x8f\xd0\x5e\x44" == hmac>("Jefe", "what do ya want for nothing?"))); 192 | assert(("\x7f\xb3\xcb\x35\x88\xc6\xc1\xf6\xff\xa9\x69\x4d\x7d\x6a\xd2\x64\x93\x65\xb0\xc1\xf6\x5d\x69\xd1\xec\x83\x33\xea" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 50, '\xdd'))); 193 | assert(("\x6c\x11\x50\x68\x74\x01\x3c\xac\x6a\x2a\xbc\x1b\xb3\x82\x62\x7c\xec\x6a\x90\xd8\x6e\xfc\x01\x2d\xe7\xaf\xec\x5a" == hmac>("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", 50, '\xcd'))); 194 | assert(("\x95\xe9\xa0\xdb\x96\x20\x95\xad\xae\xbe\x9b\x2d\x6f\x0d\xbc\xe2\xd4\x99\xf1\x12\xf2\xd2\xb7\x27\x3f\xa6\x87\x0e" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "Test Using Larger Than Block-Size Key - Hash Key First"))); 195 | assert(("\x3a\x85\x41\x66\xac\x5d\x9f\x02\x3f\x54\xd5\x17\xd0\xb3\x9d\xbd\x94\x67\x70\xdb\x9c\x2b\x95\xc9\xf6\xf5\x65\xd1" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."))); 196 | 197 | assert(("\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7" == hmac>("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", "Hi There"))); 198 | assert(("\x5b\xdc\xc1\x46\xbf\x60\x75\x4e\x6a\x04\x24\x26\x08\x95\x75\xc7\x5a\x00\x3f\x08\x9d\x27\x39\x83\x9d\xec\x58\xb9\x64\xec\x38\x43" == hmac>("Jefe", "what do ya want for nothing?"))); 199 | assert(("\x77\x3e\xa9\x1e\x36\x80\x0e\x46\x85\x4d\xb8\xeb\xd0\x91\x81\xa7\x29\x59\x09\x8b\x3e\xf8\xc1\x22\xd9\x63\x55\x14\xce\xd5\x65\xfe" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 50, '\xdd'))); 200 | assert(("\x82\x55\x8a\x38\x9a\x44\x3c\x0e\xa4\xcc\x81\x98\x99\xf2\x08\x3a\x85\xf0\xfa\xa3\xe5\x78\xf8\x07\x7a\x2e\x3f\xf4\x67\x29\x66\x5b" == hmac>("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", 50, '\xcd'))); 201 | assert(("\x60\xe4\x31\x59\x1e\xe0\xb6\x7f\x0d\x8a\x26\xaa\xcb\xf5\xb7\x7f\x8e\x0b\xc6\x21\x37\x28\xc5\x14\x05\x46\x04\x0f\x0e\xe3\x7f\x54" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "Test Using Larger Than Block-Size Key - Hash Key First"))); 202 | assert(("\x9b\x09\xff\xa7\x1b\x94\x2f\xcb\x27\x63\x5f\xbc\xd5\xb0\xe9\x44\xbf\xdc\x63\x64\x4f\x07\x13\x93\x8a\x7f\x51\x53\x5c\x3a\x35\xe2" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."))); 203 | 204 | assert(("\xaf\xd0\x39\x44\xd8\x48\x95\x62\x6b\x08\x25\xf4\xab\x46\x90\x7f\x15\xf9\xda\xdb\xe4\x10\x1e\xc6\x82\xaa\x03\x4c\x7c\xeb\xc5\x9c\xfa\xea\x9e\xa9\x07\x6e\xde\x7f\x4a\xf1\x52\xe8\xb2\xfa\x9c\xb6" == hmac>("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", "Hi There"))); 205 | assert(("\xaf\x45\xd2\xe3\x76\x48\x40\x31\x61\x7f\x78\xd2\xb5\x8a\x6b\x1b\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47\xe4\x2e\xc3\x73\x63\x22\x44\x5e\x8e\x22\x40\xca\x5e\x69\xe2\xc7\x8b\x32\x39\xec\xfa\xb2\x16\x49" == hmac>("Jefe", "what do ya want for nothing?"))); 206 | assert(("\x88\x06\x26\x08\xd3\xe6\xad\x8a\x0a\xa2\xac\xe0\x14\xc8\xa8\x6f\x0a\xa6\x35\xd9\x47\xac\x9f\xeb\xe8\x3e\xf4\xe5\x59\x66\x14\x4b\x2a\x5a\xb3\x9d\xc1\x38\x14\xb9\x4e\x3a\xb6\xe1\x01\xa3\x4f\x27" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 50, '\xdd'))); 207 | assert(("\x3e\x8a\x69\xb7\x78\x3c\x25\x85\x19\x33\xab\x62\x90\xaf\x6c\xa7\x7a\x99\x81\x48\x08\x50\x00\x9c\xc5\x57\x7c\x6e\x1f\x57\x3b\x4e\x68\x01\xdd\x23\xc4\xa7\xd6\x79\xcc\xf8\xa3\x86\xc6\x74\xcf\xfb" == hmac>("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", 50, '\xcd'))); 208 | assert(("\x4e\xce\x08\x44\x85\x81\x3e\x90\x88\xd2\xc6\x3a\x04\x1b\xc5\xb4\x4f\x9e\xf1\x01\x2a\x2b\x58\x8f\x3c\xd1\x1f\x05\x03\x3a\xc4\xc6\x0c\x2e\xf6\xab\x40\x30\xfe\x82\x96\x24\x8d\xf1\x63\xf4\x49\x52" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "Test Using Larger Than Block-Size Key - Hash Key First"))); 209 | assert(("\x66\x17\x17\x8e\x94\x1f\x02\x0d\x35\x1e\x2f\x25\x4e\x8f\xd3\x2c\x60\x24\x20\xfe\xb0\xb8\xfb\x9a\xdc\xce\xbb\x82\x46\x1e\x99\xc5\xa6\x78\xcc\x31\xe7\x99\x17\x6d\x38\x60\xe6\x11\x0c\x46\x52\x3e" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."))); 210 | 211 | assert(("\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1\x7c\xde\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae\xa3\xf4\xe4\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20\x3a\x12\x68\x54" == hmac>("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", "Hi There"))); 212 | assert(("\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3\x87\xbd\x64\x22\x2e\x83\x1f\xd6\x10\x27\x0c\xd7\xea\x25\x05\x54\x97\x58\xbf\x75\xc0\x5a\x99\x4a\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b\x63\x6e\x07\x0a\x38\xbc\xe7\x37" == hmac>("Jefe", "what do ya want for nothing?"))); 213 | assert(("\xfa\x73\xb0\x08\x9d\x56\xa2\x84\xef\xb0\xf0\x75\x6c\x89\x0b\xe9\xb1\xb5\xdb\xdd\x8e\xe8\x1a\x36\x55\xf8\x3e\x33\xb2\x27\x9d\x39\xbf\x3e\x84\x82\x79\xa7\x22\xc8\x06\xb4\x85\xa4\x7e\x67\xc8\x07\xb9\x46\xa3\x37\xbe\xe8\x94\x26\x74\x27\x88\x59\xe1\x32\x92\xfb" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 50, '\xdd'))); 214 | assert(("\xb0\xba\x46\x56\x37\x45\x8c\x69\x90\xe5\xa8\xc5\xf6\x1d\x4a\xf7\xe5\x76\xd9\x7f\xf9\x4b\x87\x2d\xe7\x6f\x80\x50\x36\x1e\xe3\xdb\xa9\x1c\xa5\xc1\x1a\xa2\x5e\xb4\xd6\x79\x27\x5c\xc5\x78\x80\x63\xa5\xf1\x97\x41\x12\x0c\x4f\x2d\xe2\xad\xeb\xeb\x10\xa2\x98\xdd" == hmac>("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", 50, '\xcd'))); 215 | assert(("\x80\xb2\x42\x63\xc7\xc1\xa3\xeb\xb7\x14\x93\xc1\xdd\x7b\xe8\xb4\x9b\x46\xd1\xf4\x1b\x4a\xee\xc1\x12\x1b\x01\x37\x83\xf8\xf3\x52\x6b\x56\xd0\x37\xe0\x5f\x25\x98\xbd\x0f\xd2\x21\x5d\x6a\x1e\x52\x95\xe6\x4f\x73\xf6\x3f\x0a\xec\x8b\x91\x5a\x98\x5d\x78\x65\x98" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "Test Using Larger Than Block-Size Key - Hash Key First"))); 216 | assert(("\xe3\x7b\x6a\x77\x5d\xc8\x7d\xba\xa4\xdf\xa9\xf9\x6e\x5e\x3f\xfd\xde\xbd\x71\xf8\x86\x72\x89\x86\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44\xb6\x02\x2c\xac\x3c\x49\x82\xb1\x0d\x5e\xeb\x55\xc3\xe4\xde\x15\x13\x46\x76\xfb\x6d\xe0\x44\x60\x65\xc9\x74\x40\xfa\x8c\x6a\x58" == hmac>("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."))); 217 | 218 | return 0; 219 | } 220 | 221 | #endif 222 | -------------------------------------------------------------------------------- /sha2.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * NAME 3 | * 4 | * sha2 - secure hash algorithm 2 5 | * 6 | * SYNOPSIS 7 | * 8 | * auto digest = SHA2<256,224>().update(...).digest(); 9 | * auto digest = SHA2<256,256>().update(...).digest(); 10 | * auto digest = SHA2<512,224>().update(...).digest(); 11 | * auto digest = SHA2<512,256>().update(...).digest(); 12 | * auto digest = SHA2<512,384>().update(...).digest(); 13 | * auto digest = SHA2<512,512>().update(...).digest(); 14 | * 15 | * DESCRIPTION 16 | * 17 | * SHA-2 (Secure Hash Algorithm 2) is a family of cryptographic hash 18 | * functions designed to provide stronger security and resistance to 19 | * attacks compared to its predecessor, SHA-1. SHA-2 family includes 20 | * several variants, each producing different output sizes: SHA-224, 21 | * SHA-256, SHA-384, SHA-512, SHA-512/224, and SHA-512/256. 22 | * 23 | * EXAMPLES 24 | * 25 | * #include 26 | * using namespace crypto; 27 | * 28 | * auto 29 | * hash(const auto &trivially_copyable_objects) { 30 | * 31 | * auto hasher = SHA2<512, 256>(); 32 | * 33 | * for (const auto &object: trivially_copyable_objects) { 34 | * hasher.update(object); 35 | * } 36 | * 37 | * return sha2<256>(hasher.update("secret").digest()); 38 | * } 39 | * 40 | * COPYRIGHT 41 | * 42 | * Copyright 2022 Quasis - The MIT License 43 | */ 44 | 45 | namespace crypto { 46 | 47 | template 48 | class SHA2 { 49 | 50 | using uint8_type = __UINT8_TYPE__; 51 | using uint16_type = __UINT16_TYPE__; 52 | using uint32_type = __UINT32_TYPE__; 53 | using uint64_type = __UINT64_TYPE__; 54 | using uint128_type = unsigned __int128; 55 | 56 | template struct uint { 57 | using type = void; 58 | }; 59 | 60 | template<> struct uint<32> { 61 | using type = uint32_type; 62 | }; 63 | 64 | template<> struct uint<64> { 65 | using type = uint64_type; 66 | }; 67 | 68 | template<> struct uint<128> { 69 | using type = uint128_type; 70 | }; 71 | 72 | template 73 | struct buffer { 74 | 75 | value_type m_data[count]; 76 | 77 | using size_type = decltype(sizeof(void*)); 78 | using pointer = uint8_type*; 79 | using const_pointer = const uint8_type*; 80 | using reference = value_type&; 81 | using const_reference = const value_type&; 82 | 83 | constexpr size_type 84 | size() const noexcept { 85 | return count; 86 | } 87 | 88 | constexpr const_pointer 89 | data() const noexcept { 90 | return reinterpret_cast(m_data); 91 | } 92 | 93 | constexpr pointer 94 | data() noexcept { 95 | return reinterpret_cast(m_data); 96 | } 97 | 98 | constexpr reference 99 | operator[](size_type index) noexcept { 100 | return m_data[index]; 101 | } 102 | 103 | constexpr const_reference 104 | operator[](size_type index) const noexcept { 105 | return m_data[index]; 106 | } 107 | }; 108 | 109 | public: 110 | 111 | using size_type = typename uint::type; 112 | using word_type = typename uint::type; 113 | using state_type = buffer; 114 | using block_type = buffer; 115 | using round_type = buffer; 116 | using output_type = buffer; 117 | 118 | constexpr 119 | SHA2() noexcept; 120 | 121 | constexpr 122 | ~SHA2() noexcept { 123 | __builtin_memset(m_block.data(), 0, sizeof(block_type)); 124 | } 125 | 126 | constexpr size_type 127 | size() const noexcept { 128 | return m_count; 129 | } 130 | 131 | constexpr SHA2& 132 | update(size_type count, uint8_type input) noexcept { 133 | 134 | auto cursor = m_count % sizeof(block_type); 135 | auto excess = (cursor + count) % sizeof(block_type); 136 | auto blocks = (cursor + count) / sizeof(block_type); 137 | 138 | while (blocks-- != 0) { 139 | 140 | while (cursor < sizeof(block_type)) { 141 | m_block.data()[cursor++] = input; 142 | } 143 | 144 | cursor = (compress(m_block), 0); 145 | } 146 | 147 | while (cursor < excess) { 148 | m_block.data()[cursor++] = input; 149 | } 150 | 151 | return (m_count += count, *this); 152 | } 153 | 154 | constexpr SHA2& 155 | update(const uint8_type *input, size_type count) noexcept { 156 | 157 | auto cursor = m_count % sizeof(block_type); 158 | auto excess = (cursor + count) % sizeof(block_type); 159 | auto blocks = (cursor + count) / sizeof(block_type); 160 | 161 | while (blocks-- != 0) { 162 | 163 | while (cursor < sizeof(block_type)) { 164 | m_block.data()[cursor++] = *input++; 165 | } 166 | 167 | cursor = (compress(m_block), 0); 168 | } 169 | 170 | while (cursor < excess) { 171 | m_block.data()[cursor++] = *input++; 172 | } 173 | 174 | return (m_count += count, *this); 175 | } 176 | 177 | template constexpr SHA2& 178 | update(const input_type *input, size_type count) noexcept requires (__is_trivially_copyable(input_type)) { 179 | return update(reinterpret_cast(input), sizeof(input_type) * count); 180 | } 181 | 182 | template constexpr SHA2& 183 | update(const input_type (&input)[count]) noexcept requires (__is_trivially_copyable(input_type)) { 184 | return update(reinterpret_cast(input), sizeof(input_type) * count); 185 | } 186 | 187 | template constexpr SHA2& 188 | update(const input_type *begin, const input_type *end) noexcept requires (__is_trivially_copyable(input_type)) { 189 | return update(reinterpret_cast(begin), sizeof(input_type) * (end - begin)); 190 | } 191 | 192 | template constexpr SHA2& 193 | update(const input_type &input) noexcept requires (__is_trivially_copyable(input_type)) { 194 | return update(reinterpret_cast(&input), sizeof(input_type)); 195 | } 196 | 197 | constexpr SHA2& 198 | update(const char *input) noexcept { 199 | return update(reinterpret_cast(input), __builtin_strlen(input)); 200 | } 201 | 202 | template constexpr SHA2& 203 | update(const size_type count, input_type &&input) noexcept { 204 | for (size_type i = 0; i < count; ++i) update(static_cast(input)); return *this; 205 | } 206 | 207 | constexpr output_type 208 | digest() const noexcept { 209 | 210 | auto hasher = SHA2{*this}; 211 | 212 | hasher.update(size_type{1}, uint8_type{0x80}); 213 | 214 | auto length = hasher.size() % sizeof(block_type) + sizeof(size_type); 215 | auto factor = (length + sizeof(block_type) - 1) / sizeof(block_type); 216 | 217 | hasher.update(factor * sizeof(block_type) - length, uint8_type{0x00}); 218 | hasher.update(h2be(m_count << 3)); 219 | 220 | for (auto i = 0U; i < hasher.m_state.size(); ++i) { 221 | hasher.m_state[i] = h2be(hasher.m_state[i]); 222 | } 223 | 224 | return *reinterpret_cast(&hasher.m_state); 225 | } 226 | 227 | static constexpr inline round_type g_round; 228 | 229 | private: 230 | 231 | size_type m_count = {}; 232 | block_type m_block = {}; 233 | state_type m_state = {}; 234 | 235 | static constexpr uint32_type 236 | h2be(uint32_type value) noexcept { 237 | return __builtin_bswap32(value); 238 | } 239 | 240 | static constexpr uint64_type 241 | h2be(uint64_type value) noexcept { 242 | return __builtin_bswap64(value); 243 | } 244 | 245 | static constexpr uint128_type 246 | h2be(uint128_type value) noexcept { 247 | return (static_cast(h2be(static_cast(value))) << 64) | static_cast(h2be(static_cast(value >> 64))); 248 | } 249 | 250 | static constexpr uint32_type 251 | rotr(uint32_type value, int count) noexcept { 252 | return __builtin_rotateright32(value, count); 253 | } 254 | 255 | static constexpr uint64_type 256 | rotr(uint64_type value, int count) noexcept { 257 | return __builtin_rotateright64(value, count); 258 | } 259 | 260 | static constexpr uint32_type 261 | sigma0(uint32_type value) noexcept { 262 | return rotr(value, 7) ^ rotr(value,18) ^ (value >> 3); 263 | } 264 | 265 | static constexpr uint64_type 266 | sigma0(uint64_type value) noexcept { 267 | return rotr(value, 1) ^ rotr(value, 8) ^ (value >> 7); 268 | } 269 | 270 | static constexpr uint32_type 271 | sigma1(uint32_type value) noexcept { 272 | return rotr(value,17) ^ rotr(value,19) ^ (value >> 10); 273 | } 274 | 275 | static constexpr uint64_type 276 | sigma1(uint64_type value) noexcept { 277 | return rotr(value,19) ^ rotr(value,61) ^ (value >> 6); 278 | } 279 | 280 | static constexpr uint32_type 281 | delta0(uint32_type value) noexcept { 282 | return rotr(value, 2) ^ rotr(value,13) ^ rotr(value,22); 283 | } 284 | 285 | static constexpr uint64_type 286 | delta0(uint64_type value) noexcept { 287 | return rotr(value,28) ^ rotr(value,34) ^ rotr(value,39); 288 | } 289 | 290 | static constexpr uint32_type 291 | delta1(uint32_type value) noexcept { 292 | return rotr(value, 6) ^ rotr(value,11) ^ rotr(value,25); 293 | } 294 | 295 | static constexpr uint64_type 296 | delta1(uint64_type value) noexcept { 297 | return rotr(value,14) ^ rotr(value,18) ^ rotr(value,41); 298 | } 299 | 300 | static constexpr word_type 301 | bop202(word_type word1, word_type word2, word_type word3) noexcept { 302 | return (word1 & (word2 ^ word3)) ^ word3; 303 | } 304 | 305 | static constexpr word_type 306 | bop232(word_type word1, word_type word2, word_type word3) noexcept { 307 | return (word1 & word2) | ((word1 ^ word2) & word3); 308 | } 309 | 310 | static constexpr void 311 | unshift(state_type &state, word_type value1, word_type value2) { 312 | 313 | state[7] = state[6]; 314 | state[6] = state[5]; 315 | state[5] = state[4]; 316 | state[4] = state[3] + value2; 317 | state[3] = state[2]; 318 | state[2] = state[1]; 319 | state[1] = state[0]; 320 | state[0] = value1 + value2; 321 | } 322 | 323 | constexpr void 324 | compress(const block_type &block) noexcept { 325 | 326 | round_type round; 327 | state_type state = m_state; 328 | 329 | for (auto i = 0U; i < block.size(); ++i) { 330 | round[i] = h2be(block[i]); 331 | } 332 | 333 | for (auto i = block.size(); i < round.size(); ++i) { 334 | round[i] = round[i - 16] + sigma0(round[i - 15]) + round[i - 7] + sigma1(round[i - 2]); 335 | } 336 | 337 | for (auto i = 0U; i < round.size(); ++i) { 338 | unshift(state, delta0(state[0]) + bop232(state[0], state[1], state[2]), delta1(state[4]) + 339 | bop202(state[4], state[5], state[6]) + state[7] + round[i] + SHA2::g_round[i]); 340 | } 341 | 342 | for (auto i = 0U; i < state.size(); ++i) { 343 | m_state[i] += state[i]; 344 | } 345 | } 346 | }; 347 | 348 | // 256 349 | 350 | template<> constexpr 351 | SHA2<256, 224>::SHA2() noexcept : m_state{ 352 | 353 | 0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939, 354 | 0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4} { 355 | } 356 | 357 | template<> constexpr 358 | SHA2<256, 256>::SHA2() noexcept : m_state{ 359 | 360 | 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 361 | 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19} { 362 | } 363 | 364 | template<> decltype(SHA2<256, 256>::g_round) 365 | SHA2<256, 256>::g_round = { 366 | 367 | 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 368 | 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 369 | 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 370 | 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 371 | 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 372 | 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 373 | 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 374 | 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, 375 | 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 376 | 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 377 | 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 378 | 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 379 | 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 380 | 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 381 | 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 382 | 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, 383 | }; 384 | 385 | // 512 386 | 387 | template<> constexpr 388 | SHA2<512, 224>::SHA2() noexcept : m_state{ 389 | 390 | 0x8C3D37C819544DA2, 0x73E1996689DCD4D6, 0x1DFAB7AE32FF9C82, 0x679DD514582F9FCF, 391 | 0x0F6D2B697BD44DA8, 0x77E36F7304C48942, 0x3F9D85A86A1D36C8, 0x1112E6AD91D692A1} { 392 | } 393 | 394 | template<> constexpr 395 | SHA2<512, 256>::SHA2() noexcept : m_state{ 396 | 397 | 0x22312194FC2BF72C, 0x9F555FA3C84C64C2, 0x2393B86B6F53B151, 0x963877195940EABD, 398 | 0x96283EE2A88EFFE3, 0xBE5E1E2553863992, 0x2B0199FC2C85B8AA, 0x0EB72DDC81C52CA2} { 399 | } 400 | 401 | template<> constexpr 402 | SHA2<512, 384>::SHA2() noexcept : m_state{ 403 | 404 | 0xCBBB9D5DC1059ED8, 0x629A292A367CD507, 0x9159015A3070DD17, 0x152FECD8F70E5939, 405 | 0x67332667FFC00B31, 0x8EB44A8768581511, 0xDB0C2E0D64F98FA7, 0x47B5481DBEFA4FA4} { 406 | } 407 | 408 | template<> constexpr 409 | SHA2<512, 512>::SHA2() noexcept : m_state{ 410 | 411 | 0x6A09E667F3BCC908, 0xBB67AE8584CAA73B, 0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1, 412 | 0x510E527FADE682D1, 0x9B05688C2B3E6C1F, 0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179} { 413 | } 414 | 415 | template<> decltype(SHA2<512, 512>::g_round) 416 | SHA2<512, 512>::g_round = { 417 | 418 | 0x428A2F98D728AE22, 0x7137449123EF65CD, 0xB5C0FBCFEC4D3B2F, 0xE9B5DBA58189DBBC, 419 | 0x3956C25BF348B538, 0x59F111F1B605D019, 0x923F82A4AF194F9B, 0xAB1C5ED5DA6D8118, 420 | 0xD807AA98A3030242, 0x12835B0145706FBE, 0x243185BE4EE4B28C, 0x550C7DC3D5FFB4E2, 421 | 0x72BE5D74F27B896F, 0x80DEB1FE3B1696B1, 0x9BDC06A725C71235, 0xC19BF174CF692694, 422 | 0xE49B69C19EF14AD2, 0xEFBE4786384F25E3, 0x0FC19DC68B8CD5B5, 0x240CA1CC77AC9C65, 423 | 0x2DE92C6F592B0275, 0x4A7484AA6EA6E483, 0x5CB0A9DCBD41FBD4, 0x76F988DA831153B5, 424 | 0x983E5152EE66DFAB, 0xA831C66D2DB43210, 0xB00327C898FB213F, 0xBF597FC7BEEF0EE4, 425 | 0xC6E00BF33DA88FC2, 0xD5A79147930AA725, 0x06CA6351E003826F, 0x142929670A0E6E70, 426 | 0x27B70A8546D22FFC, 0x2E1B21385C26C926, 0x4D2C6DFC5AC42AED, 0x53380D139D95B3DF, 427 | 0x650A73548BAF63DE, 0x766A0ABB3C77B2A8, 0x81C2C92E47EDAEE6, 0x92722C851482353B, 428 | 0xA2BFE8A14CF10364, 0xA81A664BBC423001, 0xC24B8B70D0F89791, 0xC76C51A30654BE30, 429 | 0xD192E819D6EF5218, 0xD69906245565A910, 0xF40E35855771202A, 0x106AA07032BBD1B8, 430 | 0x19A4C116B8D2D0C8, 0x1E376C085141AB53, 0x2748774CDF8EEB99, 0x34B0BCB5E19B48A8, 431 | 0x391C0CB3C5C95A63, 0x4ED8AA4AE3418ACB, 0x5B9CCA4F7763E373, 0x682E6FF3D6B2B8A3, 432 | 0x748F82EE5DEFB2FC, 0x78A5636F43172F60, 0x84C87814A1F0AB72, 0x8CC702081A6439EC, 433 | 0x90BEFFFA23631E28, 0xA4506CEBDE82BDE9, 0xBEF9A3F7B2C67915, 0xC67178F2E372532B, 434 | 0xCA273ECEEA26619C, 0xD186B8C721C0C207, 0xEADA7DD6CDE0EB1E, 0xF57D4F7FEE6ED178, 435 | 0x06F067AA72176FBA, 0x0A637DC5A2C898A6, 0x113F9804BEF90DAE, 0x1B710B35131C471B, 436 | 0x28DB77F523047D84, 0x32CAAB7B40C72493, 0x3C9EBE0A15C9BEBC, 0x431D67C49C100D4C, 437 | 0x4CC5D4BECB3E42B6, 0x597F299CFC657E2A, 0x5FCB6FAB3AD6FAEC, 0x6C44198C4A475817, 438 | }; 439 | 440 | 441 | template constexpr decltype(auto) 442 | sha2(input_type &&...input) noexcept { 443 | return SHA2().update(static_cast(input)...).digest(); 444 | } 445 | } 446 | 447 | #if __INCLUDE_LEVEL__ 448 | 449 | #pragma once 450 | 451 | #else 452 | 453 | #include 454 | using namespace crypto; 455 | 456 | template constexpr bool 457 | operator==(const char (&left)[count], const right_type &right) noexcept { 458 | return count - 1 == sizeof(right_type) && __builtin_memcmp(&left, &right, sizeof(right_type)) == 0; 459 | } 460 | 461 | int 462 | main() { 463 | 464 | assert(("\xd1\x4a\x02\x8c\x2a\x3a\x2b\xc9\x47\x61\x02\xbb\x28\x82\x34\xc4\x15\xa2\xb0\x1f\x82\x8e\xa6\x2a\xc5\xb3\xe4\x2f" == sha2<256,224>(""))); 465 | assert(("\x23\x09\x7d\x22\x34\x05\xd8\x22\x86\x42\xa4\x77\xbd\xa2\x55\xb3\x2a\xad\xbc\xe4\xbd\xa0\xb3\xf7\xe3\x6c\x9d\xa7" == sha2<256,224>("abc"))); 466 | assert(("\x75\x38\x8b\x16\x51\x27\x76\xcc\x5d\xba\x5d\xa1\xfd\x89\x01\x50\xb0\xc6\x45\x5c\xb4\xf5\x8b\x19\x52\x52\x25\x25" == sha2<256,224>("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"))); 467 | assert(("\xc9\x7c\xa9\xa5\x59\x85\x0c\xe9\x7a\x04\xa9\x6d\xef\x6d\x99\xa9\xe0\xe0\xe2\xab\x14\xe6\xb8\xdf\x26\x5f\xc0\xb3" == sha2<256,224>("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"))); 468 | assert(("\x20\x79\x46\x55\x98\x0c\x91\xd8\xbb\xb4\xc1\xea\x97\x61\x8a\x4b\xf0\x3f\x42\x58\x19\x48\xb2\xee\x4e\xe7\xad\x67" == sha2<256,224>(1000000, 'a'))); 469 | assert(("\xb5\x98\x97\x13\xca\x4f\xe4\x7a\x00\x9f\x86\x21\x98\x0b\x34\xe6\xd6\x3e\xd3\x06\x3b\x2a\x0a\x2c\x86\x7d\x8a\x85" == sha2<256,224>(16777216, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"))); 470 | 471 | assert(("\x6e\xd0\xdd\x02\x80\x6f\xa8\x9e\x25\xde\x06\x0c\x19\xd3\xac\x86\xca\xbb\x87\xd6\xa0\xdd\xd0\x5c\x33\x3b\x84\xf4" == sha2<512,224>(""))); 472 | assert(("\x46\x34\x27\x0f\x70\x7b\x6a\x54\xda\xae\x75\x30\x46\x08\x42\xe2\x0e\x37\xed\x26\x5c\xee\xe9\xa4\x3e\x89\x24\xaa" == sha2<512,224>("abc"))); 473 | assert(("\xe5\x30\x2d\x6d\x54\xbb\x24\x22\x75\xd1\xe7\x62\x2d\x68\xdf\x6e\xb0\x2d\xed\xd1\x3f\x56\x4c\x13\xdb\xda\x21\x74" == sha2<512,224>("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"))); 474 | assert(("\x23\xfe\xc5\xbb\x94\xd6\x0b\x23\x30\x81\x92\x64\x0b\x0c\x45\x33\x35\xd6\x64\x73\x4f\xe4\x0e\x72\x68\x67\x4a\xf9" == sha2<512,224>("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"))); 475 | assert(("\x37\xab\x33\x1d\x76\xf0\xd3\x6d\xe4\x22\xbd\x0e\xde\xb2\x2a\x28\xac\xcd\x48\x7b\x7a\x84\x53\xae\x96\x5d\xd2\x87" == sha2<512,224>(1000000, 'a'))); 476 | assert(("\x9a\x7f\x86\x72\x7c\x3b\xe1\x40\x3d\x67\x02\x61\x76\x46\xb1\x55\x89\xb8\xc5\xa9\x2c\x70\xf1\x70\x3c\xd2\x5b\x52" == sha2<512,224>(16777216, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"))); 477 | 478 | assert(("\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24\x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52\xb8\x55" == sha2<256,256>(""))); 479 | assert(("\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad" == sha2<256,256>("abc"))); 480 | assert(("\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1" == sha2<256,256>("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"))); 481 | assert(("\xcf\x5b\x16\xa7\x78\xaf\x83\x80\x03\x6c\xe5\x9e\x7b\x04\x92\x37\x0b\x24\x9b\x11\xe8\xf0\x7a\x51\xaf\xac\x45\x03\x7a\xfe\xe9\xd1" == sha2<256,256>("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"))); 482 | assert(("\xcd\xc7\x6e\x5c\x99\x14\xfb\x92\x81\xa1\xc7\xe2\x84\xd7\x3e\x67\xf1\x80\x9a\x48\xa4\x97\x20\x0e\x04\x6d\x39\xcc\xc7\x11\x2c\xd0" == sha2<256,256>(1000000, 'a'))); 483 | assert(("\x50\xe7\x2a\x0e\x26\x44\x2f\xe2\x55\x2d\xc3\x93\x8a\xc5\x86\x58\x22\x8c\x0c\xbf\xb1\xd2\xca\x87\x2a\xe4\x35\x26\x6f\xcd\x05\x5e" == sha2<256,256>(16777216, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"))); 484 | 485 | assert(("\xc6\x72\xb8\xd1\xef\x56\xed\x28\xab\x87\xc3\x62\x2c\x51\x14\x06\x9b\xdd\x3a\xd7\xb8\xf9\x73\x74\x98\xd0\xc0\x1e\xce\xf0\x96\x7a" == sha2<512,256>(""))); 486 | assert(("\x53\x04\x8e\x26\x81\x94\x1e\xf9\x9b\x2e\x29\xb7\x6b\x4c\x7d\xab\xe4\xc2\xd0\xc6\x34\xfc\x6d\x46\xe0\xe2\xf1\x31\x07\xe7\xaf\x23" == sha2<512,256>("abc"))); 487 | assert(("\xbd\xe8\xe1\xf9\xf1\x9b\xb9\xfd\x34\x06\xc9\x0e\xc6\xbc\x47\xbd\x36\xd8\xad\xa9\xf1\x18\x80\xdb\xc8\xa2\x2a\x70\x78\xb6\xa4\x61" == sha2<512,256>("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"))); 488 | assert(("\x39\x28\xe1\x84\xfb\x86\x90\xf8\x40\xda\x39\x88\x12\x1d\x31\xbe\x65\xcb\x9d\x3e\xf8\x3e\xe6\x14\x6f\xea\xc8\x61\xe1\x9b\x56\x3a" == sha2<512,256>("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"))); 489 | assert(("\x9a\x59\xa0\x52\x93\x01\x87\xa9\x70\x38\xca\xe6\x92\xf3\x07\x08\xaa\x64\x91\x92\x3e\xf5\x19\x43\x94\xdc\x68\xd5\x6c\x74\xfb\x21" == sha2<512,256>(1000000, 'a'))); 490 | assert(("\xb5\x85\x5a\x61\x79\x80\x2c\xe5\x67\xcb\xf4\x38\x88\x28\x4c\x6a\xc7\xc3\xf6\xc4\x8b\x08\xc5\xbc\x1e\x8a\xd7\x5d\x12\x78\x2c\x9e" == sha2<512,256>(16777216, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"))); 491 | 492 | assert(("\x38\xb0\x60\xa7\x51\xac\x96\x38\x4c\xd9\x32\x7e\xb1\xb1\xe3\x6a\x21\xfd\xb7\x11\x14\xbe\x07\x43\x4c\x0c\xc7\xbf\x63\xf6\xe1\xda\x27\x4e\xde\xbf\xe7\x6f\x65\xfb\xd5\x1a\xd2\xf1\x48\x98\xb9\x5b" == sha2<512,384>(""))); 493 | assert(("\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50\x07\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff\x5b\xed\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34\xc8\x25\xa7" == sha2<512,384>("abc"))); 494 | assert(("\x33\x91\xfd\xdd\xfc\x8d\xc7\x39\x37\x07\xa6\x5b\x1b\x47\x09\x39\x7c\xf8\xb1\xd1\x62\xaf\x05\xab\xfe\x8f\x45\x0d\xe5\xf3\x6b\xc6\xb0\x45\x5a\x85\x20\xbc\x4e\x6f\x5f\xe9\x5b\x1f\xe3\xc8\x45\x2b" == sha2<512,384>("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"))); 495 | assert(("\x09\x33\x0c\x33\xf7\x11\x47\xe8\x3d\x19\x2f\xc7\x82\xcd\x1b\x47\x53\x11\x1b\x17\x3b\x3b\x05\xd2\x2f\xa0\x80\x86\xe3\xb0\xf7\x12\xfc\xc7\xc7\x1a\x55\x7e\x2d\xb9\x66\xc3\xe9\xfa\x91\x74\x60\x39" == sha2<512,384>("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"))); 496 | assert(("\x9d\x0e\x18\x09\x71\x64\x74\xcb\x08\x6e\x83\x4e\x31\x0a\x4a\x1c\xed\x14\x9e\x9c\x00\xf2\x48\x52\x79\x72\xce\xc5\x70\x4c\x2a\x5b\x07\xb8\xb3\xdc\x38\xec\xc4\xeb\xae\x97\xdd\xd8\x7f\x3d\x89\x85" == sha2<512,384>(1000000, 'a'))); 497 | assert(("\x54\x41\x23\x5c\xc0\x23\x53\x41\xed\x80\x6a\x64\xfb\x35\x47\x42\xb5\xe5\xc0\x2a\x3c\x5c\xb7\x1b\x5f\x63\xfb\x79\x34\x58\xd8\xfd\xae\x59\x9c\x8c\xd8\x88\x49\x43\xc0\x4f\x11\xb3\x1b\x89\xf0\x23" == sha2<512,384>(16777216, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"))); 498 | 499 | assert(("\xcf\x83\xe1\x35\x7e\xef\xb8\xbd\xf1\x54\x28\x50\xd6\x6d\x80\x07\xd6\x20\xe4\x05\x0b\x57\x15\xdc\x83\xf4\xa9\x21\xd3\x6c\xe9\xce\x47\xd0\xd1\x3c\x5d\x85\xf2\xb0\xff\x83\x18\xd2\x87\x7e\xec\x2f\x63\xb9\x31\xbd\x47\x41\x7a\x81\xa5\x38\x32\x7a\xf9\x27\xda\x3e" == sha2<512,512>(""))); 500 | assert(("\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41\x31\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3\xfe\xeb\xbd\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f" == sha2<512,512>("abc"))); 501 | assert(("\x20\x4a\x8f\xc6\xdd\xa8\x2f\x0a\x0c\xed\x7b\xeb\x8e\x08\xa4\x16\x57\xc1\x6e\xf4\x68\xb2\x28\xa8\x27\x9b\xe3\x31\xa7\x03\xc3\x35\x96\xfd\x15\xc1\x3b\x1b\x07\xf9\xaa\x1d\x3b\xea\x57\x78\x9c\xa0\x31\xad\x85\xc7\xa7\x1d\xd7\x03\x54\xec\x63\x12\x38\xca\x34\x45" == sha2<512,512>("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"))); 502 | assert(("\x8e\x95\x9b\x75\xda\xe3\x13\xda\x8c\xf4\xf7\x28\x14\xfc\x14\x3f\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1\x72\x99\xae\xad\xb6\x88\x90\x18\x50\x1d\x28\x9e\x49\x00\xf7\xe4\x33\x1b\x99\xde\xc4\xb5\x43\x3a\xc7\xd3\x29\xee\xb6\xdd\x26\x54\x5e\x96\xe5\x5b\x87\x4b\xe9\x09" == sha2<512,512>("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"))); 503 | assert(("\xe7\x18\x48\x3d\x0c\xe7\x69\x64\x4e\x2e\x42\xc7\xbc\x15\xb4\x63\x8e\x1f\x98\xb1\x3b\x20\x44\x28\x56\x32\xa8\x03\xaf\xa9\x73\xeb\xde\x0f\xf2\x44\x87\x7e\xa6\x0a\x4c\xb0\x43\x2c\xe5\x77\xc3\x1b\xeb\x00\x9c\x5c\x2c\x49\xaa\x2e\x4e\xad\xb2\x17\xad\x8c\xc0\x9b" == sha2<512,512>(1000000, 'a'))); 504 | assert(("\xb4\x7c\x93\x34\x21\xea\x2d\xb1\x49\xad\x6e\x10\xfc\xe6\xc7\xf9\x3d\x07\x52\x38\x01\x80\xff\xd7\xf4\x62\x9a\x71\x21\x34\x83\x1d\x77\xbe\x60\x91\xb8\x19\xed\x35\x2c\x29\x67\xa2\xe2\xd4\xfa\x50\x50\x72\x3c\x96\x30\x69\x1f\x1a\x05\xa7\x28\x1d\xbe\x6c\x10\x86" == sha2<512,512>(16777216, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"))); 505 | 506 | return 0; 507 | } 508 | 509 | #endif 510 | -------------------------------------------------------------------------------- /rmd.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * NAME 3 | * 4 | * rmd - RACE message digest 5 | * 6 | * SYNOPSIS 7 | * 8 | * auto digest = RMD<128>().update(...).digest(); 9 | * auto digest = RMD<160>().update(...).digest(); 10 | * auto digest = RMD<256>().update(...).digest(); 11 | * auto digest = RMD<320>().update(...).digest(); 12 | * 13 | * DESCRIPTION 14 | * 15 | * R[IPE]MD (RACE Integrity Primitives Evaluation Message Digest) is 16 | * a family of cryptographic hash functions that were developed as a 17 | * part of the European Union's RACE project. The original algorithm, 18 | * known as RIPEMD-160, was designed to produce a 160-bit hash value, 19 | * but other variants like RIPEMD-128, RIPEMD-256 and RIPEMD-320 were 20 | * later introduced to produce shorter or longer hash values. 21 | * 22 | * EXAMPLES 23 | * 24 | * #include 25 | * using namespace crypto; 26 | * 27 | * auto 28 | * hash(const auto &trivially_copyable_objects) { 29 | * 30 | * auto hasher = RMD<256>(); 31 | * 32 | * for (const auto &object: trivially_copyable_objects) { 33 | * hasher.update(object); 34 | * } 35 | * 36 | * return rmd<160>(hasher.update("secret").digest()); 37 | * } 38 | * 39 | * COPYRIGHT 40 | * 41 | * Copyright 2022 Quasis - The MIT License 42 | */ 43 | 44 | namespace crypto { 45 | 46 | template 47 | class RMD { 48 | 49 | using uint8_type = __UINT8_TYPE__; 50 | using uint16_type = __UINT16_TYPE__; 51 | using uint32_type = __UINT32_TYPE__; 52 | using uint64_type = __UINT64_TYPE__; 53 | 54 | template 55 | struct buffer { 56 | 57 | value_type m_data[count]; 58 | 59 | using size_type = decltype(sizeof(void*)); 60 | using pointer = uint8_type*; 61 | using const_pointer = const uint8_type*; 62 | using reference = value_type&; 63 | using const_reference = const value_type&; 64 | 65 | constexpr size_type 66 | size() const noexcept { 67 | return count; 68 | } 69 | 70 | constexpr const_pointer 71 | data() const noexcept { 72 | return reinterpret_cast(m_data); 73 | } 74 | 75 | constexpr pointer 76 | data() noexcept { 77 | return reinterpret_cast(m_data); 78 | } 79 | 80 | constexpr reference 81 | operator[](size_type index) noexcept { 82 | return m_data[index]; 83 | } 84 | 85 | constexpr const_reference 86 | operator[](size_type index) const noexcept { 87 | return m_data[index]; 88 | } 89 | }; 90 | 91 | public: 92 | 93 | using size_type = uint64_type; 94 | using word_type = uint32_type; 95 | using state_type = buffer; 96 | using block_type = buffer; 97 | using round_type = buffer; 98 | using output_type = buffer; 99 | 100 | constexpr 101 | RMD() noexcept; 102 | 103 | constexpr 104 | ~RMD() noexcept { 105 | __builtin_memset(m_block.data(), 0, sizeof(block_type)); 106 | } 107 | 108 | constexpr size_type 109 | size() const noexcept { 110 | return m_count; 111 | } 112 | 113 | constexpr RMD& 114 | update(size_type count, uint8_type input) noexcept { 115 | 116 | auto cursor = m_count % sizeof(block_type); 117 | auto excess = (cursor + count) % sizeof(block_type); 118 | auto blocks = (cursor + count) / sizeof(block_type); 119 | 120 | while (blocks-- != 0) { 121 | 122 | while (cursor < sizeof(block_type)) { 123 | m_block.data()[cursor++] = input; 124 | } 125 | 126 | cursor = (compress(m_block), 0); 127 | } 128 | 129 | while (cursor < excess) { 130 | m_block.data()[cursor++] = input; 131 | } 132 | 133 | return (m_count += count, *this); 134 | } 135 | 136 | constexpr RMD& 137 | update(const uint8_type *input, size_type count) noexcept { 138 | 139 | auto cursor = m_count % sizeof(block_type); 140 | auto excess = (cursor + count) % sizeof(block_type); 141 | auto blocks = (cursor + count) / sizeof(block_type); 142 | 143 | while (blocks-- != 0) { 144 | 145 | while (cursor < sizeof(block_type)) { 146 | m_block.data()[cursor++] = *input++; 147 | } 148 | 149 | cursor = (compress(m_block), 0); 150 | } 151 | 152 | while (cursor < excess) { 153 | m_block.data()[cursor++] = *input++; 154 | } 155 | 156 | return (m_count += count, *this); 157 | } 158 | 159 | template constexpr RMD& 160 | update(const input_type *input, size_type count) noexcept requires (__is_trivially_copyable(input_type)) { 161 | return update(reinterpret_cast(input), sizeof(input_type) * count); 162 | } 163 | 164 | template constexpr RMD& 165 | update(const input_type (&input)[count]) noexcept requires (__is_trivially_copyable(input_type)) { 166 | return update(reinterpret_cast(input), sizeof(input_type) * count); 167 | } 168 | 169 | template constexpr RMD& 170 | update(const input_type *begin, const input_type *end) noexcept requires (__is_trivially_copyable(input_type)) { 171 | return update(reinterpret_cast(begin), sizeof(input_type) * (end - begin)); 172 | } 173 | 174 | template constexpr RMD& 175 | update(const input_type &input) noexcept requires (__is_trivially_copyable(input_type)) { 176 | return update(reinterpret_cast(&input), sizeof(input_type)); 177 | } 178 | 179 | constexpr RMD& 180 | update(const char *input) noexcept { 181 | return update(reinterpret_cast(input), __builtin_strlen(input)); 182 | } 183 | 184 | template constexpr RMD& 185 | update(const size_type count, input_type &&input) noexcept { 186 | for (size_type i = 0; i < count; ++i) update(static_cast(input)); return *this; 187 | } 188 | 189 | constexpr output_type 190 | digest() const noexcept { 191 | 192 | auto hasher = RMD{*this}; 193 | 194 | hasher.update(size_type{1}, uint8_type{0x80}); 195 | 196 | auto length = hasher.size() % sizeof(block_type) + sizeof(size_type); 197 | auto factor = (length + sizeof(block_type) - 1) / sizeof(block_type); 198 | 199 | hasher.update(factor * sizeof(block_type) - length, uint8_type{0x00}); 200 | hasher.update(m_count << 3); 201 | 202 | return *reinterpret_cast(&hasher.m_state); 203 | } 204 | 205 | private: 206 | 207 | size_type m_count = {}; 208 | block_type m_block = {}; 209 | state_type m_state = {}; 210 | 211 | static constexpr uint32_type 212 | rotl(uint32_type value, int count) noexcept { 213 | return __builtin_rotateleft32(value, count); 214 | } 215 | 216 | static constexpr void 217 | swap(word_type &word1, word_type &word2) noexcept { 218 | 219 | word_type temp = static_cast(word1); 220 | 221 | word1 = static_cast(word2); 222 | word2 = static_cast(temp); 223 | } 224 | 225 | static constexpr word_type 226 | bop045(word_type word1, word_type word2, word_type word3) noexcept { 227 | return word1 ^ (word2 | ~word3); 228 | } 229 | 230 | static constexpr word_type 231 | bop089(word_type word1, word_type word2, word_type word3) noexcept { 232 | return (word1 | ~word2) ^ word3; 233 | } 234 | 235 | static constexpr word_type 236 | bop150(word_type word1, word_type word2, word_type word3) noexcept { 237 | return word1 ^ word2 ^ word3; 238 | } 239 | 240 | static constexpr word_type 241 | bop202(word_type word1, word_type word2, word_type word3) noexcept { 242 | return (word1 & (word2 ^ word3)) ^ word3; 243 | } 244 | 245 | static constexpr word_type 246 | bop228(word_type word1, word_type word2, word_type word3) noexcept { 247 | return (word1 & word3) | (word2 & ~word3); 248 | } 249 | 250 | static constexpr void 251 | unshift(state_type &state, word_type value) noexcept; 252 | 253 | constexpr void 254 | compress(const block_type &block) noexcept; 255 | }; 256 | 257 | // 128 258 | 259 | template<> constexpr 260 | RMD<128>::RMD() noexcept : m_state{ 261 | 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476} { 262 | } 263 | 264 | template<> constexpr void 265 | RMD<128>::unshift(state_type &state, word_type value) noexcept { 266 | 267 | state[0] = state[3]; 268 | state[3] = state[2]; 269 | state[2] = state[1]; 270 | state[1] = value; 271 | } 272 | 273 | template<> constexpr void 274 | RMD<128>::compress(const block_type &block) noexcept { 275 | 276 | state_type hash1 = m_state, hash2 = m_state; 277 | 278 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 0], 11)); 279 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 5], 8)); 280 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 1], 14)); 281 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[14], 9)); 282 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 2], 15)); 283 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 7], 9)); 284 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 3], 12)); 285 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 0], 11)); 286 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 4], 5)); 287 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 9], 13)); 288 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 5], 8)); 289 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 2], 15)); 290 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 6], 7)); 291 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[11], 15)); 292 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 7], 9)); 293 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 4], 5)); 294 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 8], 11)); 295 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[13], 7)); 296 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 9], 13)); 297 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 6], 7)); 298 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[10], 14)); 299 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[15], 8)); 300 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[11], 15)); 301 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 8], 11)); 302 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[12], 6)); 303 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 1], 14)); 304 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[13], 7)); 305 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[10], 14)); 306 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[14], 9)); 307 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 3], 12)); 308 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[15], 8)); 309 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[12], 6)); 310 | 311 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 7], 7)); 312 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 6], 9)); 313 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 4], 6)); 314 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[11], 13)); 315 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[13], 8)); 316 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 3], 15)); 317 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 1], 13)); 318 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 7], 7)); 319 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[10], 11)); 320 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 0], 12)); 321 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 6], 9)); 322 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[13], 8)); 323 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[15], 7)); 324 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 5], 9)); 325 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 3], 15)); 326 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[10], 11)); 327 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[12], 7)); 328 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[14], 7)); 329 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 0], 12)); 330 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[15], 7)); 331 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 9], 15)); 332 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 8], 12)); 333 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 5], 9)); 334 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[12], 7)); 335 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 2], 11)); 336 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 4], 6)); 337 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[14], 7)); 338 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 9], 15)); 339 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[11], 13)); 340 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 1], 13)); 341 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 8], 12)); 342 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 2], 11)); 343 | 344 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 3], 11)); 345 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[15], 9)); 346 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[10], 13)); 347 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 5], 7)); 348 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[14], 6)); 349 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 1], 15)); 350 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 4], 7)); 351 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 3], 11)); 352 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 9], 14)); 353 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 7], 8)); 354 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[15], 9)); 355 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[14], 6)); 356 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 8], 13)); 357 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 6], 6)); 358 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 1], 15)); 359 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 9], 14)); 360 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 2], 14)); 361 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[11], 12)); 362 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 7], 8)); 363 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 8], 13)); 364 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 0], 13)); 365 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[12], 5)); 366 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 6], 6)); 367 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 2], 14)); 368 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[13], 5)); 369 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[10], 13)); 370 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[11], 12)); 371 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 0], 13)); 372 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 5], 7)); 373 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 4], 7)); 374 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[12], 5)); 375 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[13], 5)); 376 | 377 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 1], 11)); 378 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 8], 15)); 379 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 9], 12)); 380 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 6], 5)); 381 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[11], 14)); 382 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 4], 8)); 383 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[10], 15)); 384 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 1], 11)); 385 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 0], 14)); 386 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 3], 14)); 387 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 8], 15)); 388 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[11], 14)); 389 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[12], 9)); 390 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[15], 6)); 391 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 4], 8)); 392 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 0], 14)); 393 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[13], 9)); 394 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 5], 6)); 395 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 3], 14)); 396 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[12], 9)); 397 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 7], 5)); 398 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 2], 12)); 399 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[15], 6)); 400 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[13], 9)); 401 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[14], 8)); 402 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 9], 12)); 403 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 5], 6)); 404 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 7], 5)); 405 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 6], 5)); 406 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[10], 15)); 407 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 2], 12)); 408 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[14], 8)); 409 | 410 | auto value = m_state[1] + hash1[2] + hash2[3]; 411 | m_state[1] = m_state[2] + hash1[3] + hash2[0]; 412 | m_state[2] = m_state[3] + hash1[0] + hash2[1]; 413 | m_state[3] = m_state[0] + hash1[1] + hash2[2]; 414 | m_state[0] = value; 415 | } 416 | 417 | // 160 418 | 419 | template<> constexpr 420 | RMD<160>::RMD() noexcept : m_state{ 421 | 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0} { 422 | } 423 | 424 | template<> constexpr void 425 | RMD<160>::unshift(state_type &state, word_type value) noexcept { 426 | 427 | state[0] = state[4]; 428 | state[4] = state[3]; 429 | state[3] = rotl(state[2], 10); 430 | state[2] = state[1]; 431 | state[1] = value; 432 | } 433 | 434 | template<> constexpr void 435 | RMD<160>::compress(const block_type &block) noexcept { 436 | 437 | state_type hash1 = m_state, hash2 = m_state; 438 | 439 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 0], 11) + hash1[4]); 440 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 5], 8) + hash2[4]); 441 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 1], 14) + hash1[4]); 442 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[14], 9) + hash2[4]); 443 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 2], 15) + hash1[4]); 444 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 7], 9) + hash2[4]); 445 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 3], 12) + hash1[4]); 446 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 0], 11) + hash2[4]); 447 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 4], 5) + hash1[4]); 448 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 9], 13) + hash2[4]); 449 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 5], 8) + hash1[4]); 450 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 2], 15) + hash2[4]); 451 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 6], 7) + hash1[4]); 452 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[11], 15) + hash2[4]); 453 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 7], 9) + hash1[4]); 454 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 4], 5) + hash2[4]); 455 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 8], 11) + hash1[4]); 456 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[13], 7) + hash2[4]); 457 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 9], 13) + hash1[4]); 458 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 6], 7) + hash2[4]); 459 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[10], 14) + hash1[4]); 460 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[15], 8) + hash2[4]); 461 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[11], 15) + hash1[4]); 462 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 8], 11) + hash2[4]); 463 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[12], 6) + hash1[4]); 464 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 1], 14) + hash2[4]); 465 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[13], 7) + hash1[4]); 466 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[10], 14) + hash2[4]); 467 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[14], 9) + hash1[4]); 468 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 3], 12) + hash2[4]); 469 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[15], 8) + hash1[4]); 470 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[12], 6) + hash2[4]); 471 | 472 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 7], 7) + hash1[4]); 473 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 6], 9) + hash2[4]); 474 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 4], 6) + hash1[4]); 475 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[11], 13) + hash2[4]); 476 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[13], 8) + hash1[4]); 477 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 3], 15) + hash2[4]); 478 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 1], 13) + hash1[4]); 479 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 7], 7) + hash2[4]); 480 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[10], 11) + hash1[4]); 481 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 0], 12) + hash2[4]); 482 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 6], 9) + hash1[4]); 483 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[13], 8) + hash2[4]); 484 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[15], 7) + hash1[4]); 485 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 5], 9) + hash2[4]); 486 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 3], 15) + hash1[4]); 487 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[10], 11) + hash2[4]); 488 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[12], 7) + hash1[4]); 489 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[14], 7) + hash2[4]); 490 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 0], 12) + hash1[4]); 491 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[15], 7) + hash2[4]); 492 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 9], 15) + hash1[4]); 493 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 8], 12) + hash2[4]); 494 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 5], 9) + hash1[4]); 495 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[12], 7) + hash2[4]); 496 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 2], 11) + hash1[4]); 497 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 4], 6) + hash2[4]); 498 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[14], 7) + hash1[4]); 499 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 9], 15) + hash2[4]); 500 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[11], 13) + hash1[4]); 501 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 1], 13) + hash2[4]); 502 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 8], 12) + hash1[4]); 503 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 2], 11) + hash2[4]); 504 | 505 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 3], 11) + hash1[4]); 506 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[15], 9) + hash2[4]); 507 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[10], 13) + hash1[4]); 508 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 5], 7) + hash2[4]); 509 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[14], 6) + hash1[4]); 510 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 1], 15) + hash2[4]); 511 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 4], 7) + hash1[4]); 512 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 3], 11) + hash2[4]); 513 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 9], 14) + hash1[4]); 514 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 7], 8) + hash2[4]); 515 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[15], 9) + hash1[4]); 516 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[14], 6) + hash2[4]); 517 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 8], 13) + hash1[4]); 518 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 6], 6) + hash2[4]); 519 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 1], 15) + hash1[4]); 520 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 9], 14) + hash2[4]); 521 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 2], 14) + hash1[4]); 522 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[11], 12) + hash2[4]); 523 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 7], 8) + hash1[4]); 524 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 8], 13) + hash2[4]); 525 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 0], 13) + hash1[4]); 526 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[12], 5) + hash2[4]); 527 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 6], 6) + hash1[4]); 528 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 2], 14) + hash2[4]); 529 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[13], 5) + hash1[4]); 530 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[10], 13) + hash2[4]); 531 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[11], 12) + hash1[4]); 532 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 0], 13) + hash2[4]); 533 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 5], 7) + hash1[4]); 534 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 4], 7) + hash2[4]); 535 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[12], 5) + hash1[4]); 536 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[13], 5) + hash2[4]); 537 | 538 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 1], 11) + hash1[4]); 539 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 8], 15) + hash2[4]); 540 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 9], 12) + hash1[4]); 541 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 6], 5) + hash2[4]); 542 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[11], 14) + hash1[4]); 543 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 4], 8) + hash2[4]); 544 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[10], 15) + hash1[4]); 545 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 1], 11) + hash2[4]); 546 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 0], 14) + hash1[4]); 547 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 3], 14) + hash2[4]); 548 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 8], 15) + hash1[4]); 549 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[11], 14) + hash2[4]); 550 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[12], 9) + hash1[4]); 551 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[15], 6) + hash2[4]); 552 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 4], 8) + hash1[4]); 553 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 0], 14) + hash2[4]); 554 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[13], 9) + hash1[4]); 555 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 5], 6) + hash2[4]); 556 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 3], 14) + hash1[4]); 557 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[12], 9) + hash2[4]); 558 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 7], 5) + hash1[4]); 559 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 2], 12) + hash2[4]); 560 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[15], 6) + hash1[4]); 561 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[13], 9) + hash2[4]); 562 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[14], 8) + hash1[4]); 563 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 9], 12) + hash2[4]); 564 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 5], 6) + hash1[4]); 565 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 7], 5) + hash2[4]); 566 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 6], 5) + hash1[4]); 567 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[10], 15) + hash2[4]); 568 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 2], 12) + hash1[4]); 569 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[14], 8) + hash2[4]); 570 | 571 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 4], 9) + hash1[4]); 572 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[12], 8) + hash2[4]); 573 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 0], 15) + hash1[4]); 574 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[15], 5) + hash2[4]); 575 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 5], 5) + hash1[4]); 576 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[10], 12) + hash2[4]); 577 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 9], 11) + hash1[4]); 578 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 4], 9) + hash2[4]); 579 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 7], 6) + hash1[4]); 580 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 1], 12) + hash2[4]); 581 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[12], 8) + hash1[4]); 582 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 5], 5) + hash2[4]); 583 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 2], 13) + hash1[4]); 584 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 8], 14) + hash2[4]); 585 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[10], 12) + hash1[4]); 586 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 7], 6) + hash2[4]); 587 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[14], 5) + hash1[4]); 588 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 6], 8) + hash2[4]); 589 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 1], 12) + hash1[4]); 590 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 2], 13) + hash2[4]); 591 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 3], 13) + hash1[4]); 592 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[13], 6) + hash2[4]); 593 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 8], 14) + hash1[4]); 594 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[14], 5) + hash2[4]); 595 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[11], 11) + hash1[4]); 596 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 0], 15) + hash2[4]); 597 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 6], 8) + hash1[4]); 598 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 3], 13) + hash2[4]); 599 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[15], 5) + hash1[4]); 600 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 9], 11) + hash2[4]); 601 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[13], 6) + hash1[4]); 602 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[11], 11) + hash2[4]); 603 | 604 | auto value = m_state[1] + hash1[2] + hash2[3]; 605 | m_state[1] = m_state[2] + hash1[3] + hash2[4]; 606 | m_state[2] = m_state[3] + hash1[4] + hash2[0]; 607 | m_state[3] = m_state[4] + hash1[0] + hash2[1]; 608 | m_state[4] = m_state[0] + hash1[1] + hash2[2]; 609 | m_state[0] = value; 610 | } 611 | 612 | // 256 613 | 614 | template<> constexpr 615 | RMD<256>::RMD() noexcept : m_state{ 616 | 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 617 | 0x76543210, 0xFEDCBA98, 0x89ABCDEF, 0x01234567} { 618 | } 619 | 620 | template<> constexpr void 621 | RMD<256>::unshift(state_type &state, word_type value) noexcept { 622 | 623 | state[0] = state[3]; 624 | state[3] = state[2]; 625 | state[2] = state[1]; 626 | state[1] = value; 627 | } 628 | 629 | template<> constexpr void 630 | RMD<256>::compress(const block_type &block) noexcept { 631 | 632 | state_type state = m_state, &hash1 = state, &hash2 = *static_cast(static_cast(&state[4])); 633 | 634 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 0], 11)); 635 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 5], 8)); 636 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 1], 14)); 637 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[14], 9)); 638 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 2], 15)); 639 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 7], 9)); 640 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 3], 12)); 641 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 0], 11)); 642 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 4], 5)); 643 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 9], 13)); 644 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 5], 8)); 645 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 2], 15)); 646 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 6], 7)); 647 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[11], 15)); 648 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 7], 9)); 649 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 4], 5)); 650 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 8], 11)); 651 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[13], 7)); 652 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 9], 13)); 653 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 6], 7)); 654 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[10], 14)); 655 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[15], 8)); 656 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[11], 15)); 657 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 8], 11)); 658 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[12], 6)); 659 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 1], 14)); 660 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[13], 7)); 661 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[10], 14)); 662 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[14], 9)); 663 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 3], 12)); 664 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[15], 8)); 665 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[12], 6)); 666 | 667 | swap(hash1[0], hash2[0]); 668 | 669 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 7], 7)); 670 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 6], 9)); 671 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 4], 6)); 672 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[11], 13)); 673 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[13], 8)); 674 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 3], 15)); 675 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 1], 13)); 676 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 7], 7)); 677 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[10], 11)); 678 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 0], 12)); 679 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 6], 9)); 680 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[13], 8)); 681 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[15], 7)); 682 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 5], 9)); 683 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 3], 15)); 684 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[10], 11)); 685 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[12], 7)); 686 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[14], 7)); 687 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 0], 12)); 688 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[15], 7)); 689 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 9], 15)); 690 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 8], 12)); 691 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 5], 9)); 692 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[12], 7)); 693 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 2], 11)); 694 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 4], 6)); 695 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[14], 7)); 696 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 9], 15)); 697 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[11], 13)); 698 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 1], 13)); 699 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 8], 12)); 700 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 2], 11)); 701 | 702 | swap(hash1[1], hash2[1]); 703 | 704 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 3], 11)); 705 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[15], 9)); 706 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[10], 13)); 707 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 5], 7)); 708 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[14], 6)); 709 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 1], 15)); 710 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 4], 7)); 711 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 3], 11)); 712 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 9], 14)); 713 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 7], 8)); 714 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[15], 9)); 715 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[14], 6)); 716 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 8], 13)); 717 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 6], 6)); 718 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 1], 15)); 719 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 9], 14)); 720 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 2], 14)); 721 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[11], 12)); 722 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 7], 8)); 723 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 8], 13)); 724 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 0], 13)); 725 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[12], 5)); 726 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 6], 6)); 727 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 2], 14)); 728 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[13], 5)); 729 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[10], 13)); 730 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[11], 12)); 731 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 0], 13)); 732 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 5], 7)); 733 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 4], 7)); 734 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[12], 5)); 735 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[13], 5)); 736 | 737 | swap(hash1[2], hash2[2]); 738 | 739 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 1], 11)); 740 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 8], 15)); 741 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 9], 12)); 742 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 6], 5)); 743 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[11], 14)); 744 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 4], 8)); 745 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[10], 15)); 746 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 1], 11)); 747 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 0], 14)); 748 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 3], 14)); 749 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 8], 15)); 750 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[11], 14)); 751 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[12], 9)); 752 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[15], 6)); 753 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 4], 8)); 754 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 0], 14)); 755 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[13], 9)); 756 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 5], 6)); 757 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 3], 14)); 758 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[12], 9)); 759 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 7], 5)); 760 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 2], 12)); 761 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[15], 6)); 762 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[13], 9)); 763 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[14], 8)); 764 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 9], 12)); 765 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 5], 6)); 766 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 7], 5)); 767 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 6], 5)); 768 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[10], 15)); 769 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 2], 12)); 770 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[14], 8)); 771 | 772 | swap(hash1[3], hash2[3]); 773 | 774 | for (auto i = 0U; i < state.size(); ++i) { 775 | m_state[i] += state[i]; 776 | } 777 | } 778 | 779 | // 320 780 | 781 | template<> constexpr 782 | RMD<320>::RMD() noexcept : m_state{ 783 | 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0, 784 | 0x76543210, 0xFEDCBA98, 0x89ABCDEF, 0x01234567, 0x3C2D1E0F} { 785 | } 786 | 787 | template<> constexpr void 788 | RMD<320>::unshift(state_type &state, word_type value) noexcept { 789 | 790 | state[0] = state[4]; 791 | state[4] = state[3]; 792 | state[3] = rotl(state[2], 10); 793 | state[2] = state[1]; 794 | state[1] = value; 795 | } 796 | 797 | template<> constexpr void 798 | RMD<320>::compress(const block_type &block) noexcept { 799 | 800 | state_type state = m_state, &hash1 = state, &hash2 = *static_cast(static_cast(&state[5])); 801 | 802 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 0], 11) + hash1[4]); 803 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 5], 8) + hash2[4]); 804 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 1], 14) + hash1[4]); 805 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[14], 9) + hash2[4]); 806 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 2], 15) + hash1[4]); 807 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 7], 9) + hash2[4]); 808 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 3], 12) + hash1[4]); 809 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 0], 11) + hash2[4]); 810 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 4], 5) + hash1[4]); 811 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 9], 13) + hash2[4]); 812 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 5], 8) + hash1[4]); 813 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 2], 15) + hash2[4]); 814 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 6], 7) + hash1[4]); 815 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[11], 15) + hash2[4]); 816 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 7], 9) + hash1[4]); 817 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 4], 5) + hash2[4]); 818 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 8], 11) + hash1[4]); 819 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[13], 7) + hash2[4]); 820 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[ 9], 13) + hash1[4]); 821 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 6], 7) + hash2[4]); 822 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[10], 14) + hash1[4]); 823 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[15], 8) + hash2[4]); 824 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[11], 15) + hash1[4]); 825 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 8], 11) + hash2[4]); 826 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[12], 6) + hash1[4]); 827 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 1], 14) + hash2[4]); 828 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[13], 7) + hash1[4]); 829 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[10], 14) + hash2[4]); 830 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[14], 9) + hash1[4]); 831 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[ 3], 12) + hash2[4]); 832 | unshift(hash1, rotl(hash1[0] + bop150(hash1[1], hash1[2], hash1[3]) + 0x00000000 + block[15], 8) + hash1[4]); 833 | unshift(hash2, rotl(hash2[0] + bop045(hash2[1], hash2[2], hash2[3]) + 0x50A28BE6 + block[12], 6) + hash2[4]); 834 | 835 | swap(hash1[1], hash2[1]); 836 | 837 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 7], 7) + hash1[4]); 838 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 6], 9) + hash2[4]); 839 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 4], 6) + hash1[4]); 840 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[11], 13) + hash2[4]); 841 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[13], 8) + hash1[4]); 842 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 3], 15) + hash2[4]); 843 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 1], 13) + hash1[4]); 844 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 7], 7) + hash2[4]); 845 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[10], 11) + hash1[4]); 846 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 0], 12) + hash2[4]); 847 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 6], 9) + hash1[4]); 848 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[13], 8) + hash2[4]); 849 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[15], 7) + hash1[4]); 850 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 5], 9) + hash2[4]); 851 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 3], 15) + hash1[4]); 852 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[10], 11) + hash2[4]); 853 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[12], 7) + hash1[4]); 854 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[14], 7) + hash2[4]); 855 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 0], 12) + hash1[4]); 856 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[15], 7) + hash2[4]); 857 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 9], 15) + hash1[4]); 858 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 8], 12) + hash2[4]); 859 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 5], 9) + hash1[4]); 860 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[12], 7) + hash2[4]); 861 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 2], 11) + hash1[4]); 862 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 4], 6) + hash2[4]); 863 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[14], 7) + hash1[4]); 864 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 9], 15) + hash2[4]); 865 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[11], 13) + hash1[4]); 866 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 1], 13) + hash2[4]); 867 | unshift(hash1, rotl(hash1[0] + bop202(hash1[1], hash1[2], hash1[3]) + 0x5A827999 + block[ 8], 12) + hash1[4]); 868 | unshift(hash2, rotl(hash2[0] + bop228(hash2[1], hash2[2], hash2[3]) + 0x5C4DD124 + block[ 2], 11) + hash2[4]); 869 | 870 | swap(hash1[3], hash2[3]); 871 | 872 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 3], 11) + hash1[4]); 873 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[15], 9) + hash2[4]); 874 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[10], 13) + hash1[4]); 875 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 5], 7) + hash2[4]); 876 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[14], 6) + hash1[4]); 877 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 1], 15) + hash2[4]); 878 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 4], 7) + hash1[4]); 879 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 3], 11) + hash2[4]); 880 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 9], 14) + hash1[4]); 881 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 7], 8) + hash2[4]); 882 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[15], 9) + hash1[4]); 883 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[14], 6) + hash2[4]); 884 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 8], 13) + hash1[4]); 885 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 6], 6) + hash2[4]); 886 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 1], 15) + hash1[4]); 887 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 9], 14) + hash2[4]); 888 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 2], 14) + hash1[4]); 889 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[11], 12) + hash2[4]); 890 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 7], 8) + hash1[4]); 891 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 8], 13) + hash2[4]); 892 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 0], 13) + hash1[4]); 893 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[12], 5) + hash2[4]); 894 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 6], 6) + hash1[4]); 895 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 2], 14) + hash2[4]); 896 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[13], 5) + hash1[4]); 897 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[10], 13) + hash2[4]); 898 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[11], 12) + hash1[4]); 899 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 0], 13) + hash2[4]); 900 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[ 5], 7) + hash1[4]); 901 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[ 4], 7) + hash2[4]); 902 | unshift(hash1, rotl(hash1[0] + bop089(hash1[1], hash1[2], hash1[3]) + 0x6ED9EBA1 + block[12], 5) + hash1[4]); 903 | unshift(hash2, rotl(hash2[0] + bop089(hash2[1], hash2[2], hash2[3]) + 0x6D703EF3 + block[13], 5) + hash2[4]); 904 | 905 | swap(hash1[0], hash2[0]); 906 | 907 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 1], 11) + hash1[4]); 908 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 8], 15) + hash2[4]); 909 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 9], 12) + hash1[4]); 910 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 6], 5) + hash2[4]); 911 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[11], 14) + hash1[4]); 912 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 4], 8) + hash2[4]); 913 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[10], 15) + hash1[4]); 914 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 1], 11) + hash2[4]); 915 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 0], 14) + hash1[4]); 916 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 3], 14) + hash2[4]); 917 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 8], 15) + hash1[4]); 918 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[11], 14) + hash2[4]); 919 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[12], 9) + hash1[4]); 920 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[15], 6) + hash2[4]); 921 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 4], 8) + hash1[4]); 922 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 0], 14) + hash2[4]); 923 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[13], 9) + hash1[4]); 924 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 5], 6) + hash2[4]); 925 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 3], 14) + hash1[4]); 926 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[12], 9) + hash2[4]); 927 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 7], 5) + hash1[4]); 928 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 2], 12) + hash2[4]); 929 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[15], 6) + hash1[4]); 930 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[13], 9) + hash2[4]); 931 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[14], 8) + hash1[4]); 932 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 9], 12) + hash2[4]); 933 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 5], 6) + hash1[4]); 934 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[ 7], 5) + hash2[4]); 935 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 6], 5) + hash1[4]); 936 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[10], 15) + hash2[4]); 937 | unshift(hash1, rotl(hash1[0] + bop228(hash1[1], hash1[2], hash1[3]) + 0x8F1BBCDC + block[ 2], 12) + hash1[4]); 938 | unshift(hash2, rotl(hash2[0] + bop202(hash2[1], hash2[2], hash2[3]) + 0x7A6D76E9 + block[14], 8) + hash2[4]); 939 | 940 | swap(hash1[2], hash2[2]); 941 | 942 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 4], 9) + hash1[4]); 943 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[12], 8) + hash2[4]); 944 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 0], 15) + hash1[4]); 945 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[15], 5) + hash2[4]); 946 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 5], 5) + hash1[4]); 947 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[10], 12) + hash2[4]); 948 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 9], 11) + hash1[4]); 949 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 4], 9) + hash2[4]); 950 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 7], 6) + hash1[4]); 951 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 1], 12) + hash2[4]); 952 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[12], 8) + hash1[4]); 953 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 5], 5) + hash2[4]); 954 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 2], 13) + hash1[4]); 955 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 8], 14) + hash2[4]); 956 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[10], 12) + hash1[4]); 957 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 7], 6) + hash2[4]); 958 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[14], 5) + hash1[4]); 959 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 6], 8) + hash2[4]); 960 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 1], 12) + hash1[4]); 961 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 2], 13) + hash2[4]); 962 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 3], 13) + hash1[4]); 963 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[13], 6) + hash2[4]); 964 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 8], 14) + hash1[4]); 965 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[14], 5) + hash2[4]); 966 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[11], 11) + hash1[4]); 967 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 0], 15) + hash2[4]); 968 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[ 6], 8) + hash1[4]); 969 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 3], 13) + hash2[4]); 970 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[15], 5) + hash1[4]); 971 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[ 9], 11) + hash2[4]); 972 | unshift(hash1, rotl(hash1[0] + bop045(hash1[1], hash1[2], hash1[3]) + 0xA953FD4E + block[13], 6) + hash1[4]); 973 | unshift(hash2, rotl(hash2[0] + bop150(hash2[1], hash2[2], hash2[3]) + 0x00000000 + block[11], 11) + hash2[4]); 974 | 975 | swap(hash1[4], hash2[4]); 976 | 977 | for (auto i = 0U; i < state.size(); ++i) { 978 | m_state[i] += state[i]; 979 | } 980 | } 981 | 982 | template constexpr decltype(auto) 983 | rmd(input_type &&...input) noexcept { 984 | return RMD().update(static_cast(input)...).digest(); 985 | } 986 | } 987 | 988 | #if __INCLUDE_LEVEL__ 989 | 990 | #pragma once 991 | 992 | #else 993 | 994 | #include 995 | using namespace crypto; 996 | 997 | template constexpr bool 998 | operator==(const char (&left)[count], const right_type &right) noexcept { 999 | return count - 1 == sizeof(right_type) && __builtin_memcmp(&left, &right, sizeof(right_type)) == 0; 1000 | } 1001 | 1002 | int 1003 | main() { 1004 | 1005 | assert("\xcd\xf2\x62\x13\xa1\x50\xdc\x3e\xcb\x61\x0f\x18\xf6\xb3\x8b\x46" == rmd<128>("")); 1006 | assert("\x86\xbe\x7a\xfa\x33\x9d\x0f\xc7\xcf\xc7\x85\xe7\x2f\x57\x8d\x33" == rmd<128>("a")); 1007 | assert("\xc1\x4a\x12\x19\x9c\x66\xe4\xba\x84\x63\x6b\x0f\x69\x14\x4c\x77" == rmd<128>("abc")); 1008 | assert("\x9e\x32\x7b\x3d\x6e\x52\x30\x62\xaf\xc1\x13\x2d\x7d\xf9\xd1\xb8" == rmd<128>("message digest")); 1009 | assert("\xfd\x2a\xa6\x07\xf7\x1d\xc8\xf5\x10\x71\x49\x22\xb3\x71\x83\x4e" == rmd<128>("abcdefghijklmnopqrstuvwxyz")); 1010 | assert("\xa1\xaa\x06\x89\xd0\xfa\xfa\x2d\xdc\x22\xe8\x8b\x49\x13\x3a\x06" == rmd<128>("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")); 1011 | assert("\xd1\xe9\x59\xeb\x17\x9c\x91\x1f\xae\xa4\x62\x4c\x60\xc5\xc7\x02" == rmd<128>("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")); 1012 | assert("\x3f\x45\xef\x19\x47\x32\xc2\xdb\xb2\xc4\xa2\xc7\x69\x79\x5f\xa3" == rmd<128>("12345678901234567890123456789012345678901234567890123456789012345678901234567890")); 1013 | assert("\x4a\x7f\x57\x23\xf9\x54\xeb\xa1\x21\x6c\x9d\x8f\x63\x20\x43\x1f" == rmd<128>(1000000, 'a')); 1014 | 1015 | assert("\x9c\x11\x85\xa5\xc5\xe9\xfc\x54\x61\x28\x08\x97\x7e\xe8\xf5\x48\xb2\x25\x8d\x31" == rmd<160>("")); 1016 | assert("\x0b\xdc\x9d\x2d\x25\x6b\x3e\xe9\xda\xae\x34\x7b\xe6\xf4\xdc\x83\x5a\x46\x7f\xfe" == rmd<160>("a")); 1017 | assert("\x8e\xb2\x08\xf7\xe0\x5d\x98\x7a\x9b\x04\x4a\x8e\x98\xc6\xb0\x87\xf1\x5a\x0b\xfc" == rmd<160>("abc")); 1018 | assert("\x5d\x06\x89\xef\x49\xd2\xfa\xe5\x72\xb8\x81\xb1\x23\xa8\x5f\xfa\x21\x59\x5f\x36" == rmd<160>("message digest")); 1019 | assert("\xf7\x1c\x27\x10\x9c\x69\x2c\x1b\x56\xbb\xdc\xeb\x5b\x9d\x28\x65\xb3\x70\x8d\xbc" == rmd<160>("abcdefghijklmnopqrstuvwxyz")); 1020 | assert("\x12\xa0\x53\x38\x4a\x9c\x0c\x88\xe4\x05\xa0\x6c\x27\xdc\xf4\x9a\xda\x62\xeb\x2b" == rmd<160>("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")); 1021 | assert("\xb0\xe2\x0b\x6e\x31\x16\x64\x02\x86\xed\x3a\x87\xa5\x71\x30\x79\xb2\x1f\x51\x89" == rmd<160>("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")); 1022 | assert("\x9b\x75\x2e\x45\x57\x3d\x4b\x39\xf4\xdb\xd3\x32\x3c\xab\x82\xbf\x63\x32\x6b\xfb" == rmd<160>("12345678901234567890123456789012345678901234567890123456789012345678901234567890")); 1023 | assert("\x52\x78\x32\x43\xc1\x69\x7b\xdb\xe1\x6d\x37\xf9\x7f\x68\xf0\x83\x25\xdc\x15\x28" == rmd<160>(1000000, 'a')); 1024 | 1025 | assert("\x02\xba\x4c\x4e\x5f\x8e\xcd\x18\x77\xfc\x52\xd6\x4d\x30\xe3\x7a\x2d\x97\x74\xfb\x1e\x5d\x02\x63\x80\xae\x01\x68\xe3\xc5\x52\x2d" == rmd<256>("")); 1026 | assert("\xf9\x33\x3e\x45\xd8\x57\xf5\xd9\x0a\x91\xba\xb7\x0a\x1e\xba\x0c\xfb\x1b\xe4\xb0\x78\x3c\x9a\xcf\xcd\x88\x3a\x91\x34\x69\x29\x25" == rmd<256>("a")); 1027 | assert("\xaf\xbd\x6e\x22\x8b\x9d\x8c\xbb\xce\xf5\xca\x2d\x03\xe6\xdb\xa1\x0a\xc0\xbc\x7d\xcb\xe4\x68\x0e\x1e\x42\xd2\xe9\x75\x45\x9b\x65" == rmd<256>("abc")); 1028 | assert("\x87\xe9\x71\x75\x9a\x1c\xe4\x7a\x51\x4d\x5c\x91\x4c\x39\x2c\x90\x18\xc7\xc4\x6b\xc1\x44\x65\x55\x4a\xfc\xdf\x54\xa5\x07\x0c\x0e" == rmd<256>("message digest")); 1029 | assert("\x64\x9d\x30\x34\x75\x1e\xa2\x16\x77\x6b\xf9\xa1\x8a\xcc\x81\xbc\x78\x96\x11\x8a\x51\x97\x96\x87\x82\xdd\x1f\xd9\x7d\x8d\x51\x33" == rmd<256>("abcdefghijklmnopqrstuvwxyz")); 1030 | assert("\x38\x43\x04\x55\x83\xaa\xc6\xc8\xc8\xd9\x12\x85\x73\xe7\xa9\x80\x9a\xfb\x2a\x0f\x34\xcc\xc3\x6e\xa9\xe7\x2f\x16\xf6\x36\x8e\x3f" == rmd<256>("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")); 1031 | assert("\x57\x40\xa4\x08\xac\x16\xb7\x20\xb8\x44\x24\xae\x93\x1c\xbb\x1f\xe3\x63\xd1\xd0\xbf\x40\x17\xf1\xa8\x9f\x7e\xa6\xde\x77\xa0\xb8" == rmd<256>("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")); 1032 | assert("\x06\xfd\xcc\x7a\x40\x95\x48\xaa\xf9\x13\x68\xc0\x6a\x62\x75\xb5\x53\xe3\xf0\x99\xbf\x0e\xa4\xed\xfd\x67\x78\xdf\x89\xa8\x90\xdd" == rmd<256>("12345678901234567890123456789012345678901234567890123456789012345678901234567890")); 1033 | assert("\xac\x95\x37\x44\xe1\x0e\x31\x51\x4c\x15\x0d\x4d\x8d\x7b\x67\x73\x42\xe3\x33\x99\x78\x82\x96\xe4\x3a\xe4\x85\x0c\xe4\xf9\x79\x78" == rmd<256>(1000000, 'a')); 1034 | 1035 | assert("\x22\xd6\x5d\x56\x61\x53\x6c\xdc\x75\xc1\xfd\xf5\xc6\xde\x7b\x41\xb9\xf2\x73\x25\xeb\xc6\x1e\x85\x57\x17\x7d\x70\x5a\x0e\xc8\x80\x15\x1c\x3a\x32\xa0\x08\x99\xb8" == rmd<320>("")); 1036 | assert("\xce\x78\x85\x06\x38\xf9\x26\x58\xa5\xa5\x85\x09\x75\x79\x92\x6d\xda\x66\x7a\x57\x16\x56\x2c\xfc\xf6\xfb\xe7\x7f\x63\x54\x2f\x99\xb0\x47\x05\xd6\x97\x0d\xff\x5d" == rmd<320>("a")); 1037 | assert("\xde\x4c\x01\xb3\x05\x4f\x89\x30\xa7\x9d\x09\xae\x73\x8e\x92\x30\x1e\x5a\x17\x08\x5b\xef\xfd\xc1\xb8\xd1\x16\x71\x3e\x74\xf8\x2f\xa9\x42\xd6\x4c\xdb\xc4\x68\x2d" == rmd<320>("abc")); 1038 | assert("\x3a\x8e\x28\x50\x2e\xd4\x5d\x42\x2f\x68\x84\x4f\x9d\xd3\x16\xe7\xb9\x85\x33\xfa\x3f\x2a\x91\xd2\x9f\x84\xd4\x25\xc8\x8d\x6b\x4e\xff\x72\x7d\xf6\x6a\x7c\x01\x97" == rmd<320>("message digest")); 1039 | assert("\xca\xbd\xb1\x81\x0b\x92\x47\x0a\x20\x93\xaa\x6b\xce\x05\x95\x2c\x28\x34\x8c\xf4\x3f\xf6\x08\x41\x97\x51\x66\xbb\x40\xed\x23\x40\x04\xb8\x82\x44\x63\xe6\xb0\x09" == rmd<320>("abcdefghijklmnopqrstuvwxyz")); 1040 | assert("\xd0\x34\xa7\x95\x0c\xf7\x22\x02\x1b\xa4\xb8\x4d\xf7\x69\xa5\xde\x20\x60\xe2\x59\xdf\x4c\x9b\xb4\xa4\x26\x8c\x0e\x93\x5b\xbc\x74\x70\xa9\x69\xc9\xd0\x72\xa1\xac" == rmd<320>("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")); 1041 | assert("\xed\x54\x49\x40\xc8\x6d\x67\xf2\x50\xd2\x32\xc3\x0b\x7b\x3e\x57\x70\xe0\xc6\x0c\x8c\xb9\xa4\xca\xfe\x3b\x11\x38\x8a\xf9\x92\x0e\x1b\x99\x23\x0b\x84\x3c\x86\xa4" == rmd<320>("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")); 1042 | assert("\x55\x78\x88\xaf\x5f\x6d\x8e\xd6\x2a\xb6\x69\x45\xc6\xd2\xa0\xa4\x7e\xcd\x53\x41\xe9\x15\xeb\x8f\xea\x1d\x05\x24\x95\x5f\x82\x5d\xc7\x17\xe4\xa0\x08\xab\x2d\x42" == rmd<320>("12345678901234567890123456789012345678901234567890123456789012345678901234567890")); 1043 | assert("\xbd\xee\x37\xf4\x37\x1e\x20\x64\x6b\x8b\x0d\x86\x2d\xda\x16\x29\x2a\xe3\x6f\x40\x96\x5e\x8c\x85\x09\xe6\x3d\x1d\xbd\xde\xcc\x50\x3e\x2b\x63\xeb\x92\x45\xbb\x66" == rmd<320>(1000000, 'a')); 1044 | 1045 | return 0; 1046 | } 1047 | 1048 | #endif 1049 | --------------------------------------------------------------------------------