1 // @file hashutil.cpp hash utilities. 2 // @author TPOC: contact@palisade-crypto.org 3 // 4 // @copyright Copyright (c) 2019, New Jersey Institute of Technology (NJIT) 5 // All rights reserved. 6 // Redistribution and use in source and binary forms, with or without 7 // modification, are permitted provided that the following conditions are met: 8 // 1. Redistributions of source code must retain the above copyright notice, 9 // this list of conditions and the following disclaimer. 10 // 2. Redistributions in binary form must reproduce the above copyright notice, 11 // this list of conditions and the following disclaimer in the documentation 12 // and/or other materials provided with the distribution. THIS SOFTWARE IS 13 // PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 14 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 15 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 16 // EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 17 // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 24 #include <iomanip> 25 #include <sstream> 26 #include "utils/hashutil.h" 27 28 namespace lbcrypto { 29 30 #define RIGHT_ROT(x, n) \ 31 ((x >> (n % (sizeof(x) * 8)) | \ 32 (x << ((sizeof(x) * 8) - (n % (sizeof(x) * 8)))))) 33 34 const uint32_t HashUtil::k_256[64] = { 35 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 36 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 37 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, GenerateVector(usint size,const typename VecType::Integer & modulus,usint h) const38 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 39 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 40 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 41 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 42 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 43 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 44 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 45 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; 46 47 const uint64_t HashUtil::k_512[80] = { 48 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 49 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, 50 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 51 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 52 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 53 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 54 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275, 55 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 56 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 57 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 58 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 59 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, 60 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 61 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 62 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218, 63 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 64 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 65 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 66 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 67 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, 68 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 69 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207, 70 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 71 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, 72 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 73 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 74 0x5fcb6fab3ad6faec, 0x6c44198c4a475817}; 75 76 void HashUtil::SHA256(string message, vector<int64_t>& digest) { 77 uint32_t h_256[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 78 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; 79 80 uint64_t m_len = message.size() * 8; 81 uint16_t pad_len = 1; 82 while ((m_len + pad_len) % 512 != 448) { 83 pad_len++; 84 } 85 message.push_back(0); 86 for (int a = 0; a < (pad_len) / 8 - 1; a++) { 87 message.push_back(0); 88 } 89 message.push_back((uint8_t)((m_len & 0xff00000000000000) >> 56)); 90 message.push_back((uint8_t)((m_len & 0x00ff000000000000) >> 48)); 91 message.push_back((uint8_t)((m_len & 0x0000ff0000000000) >> 40)); 92 message.push_back((uint8_t)((m_len & 0x000000ff00000000) >> 32)); 93 message.push_back((uint8_t)((m_len & 0x00000000ff000000) >> 24)); 94 message.push_back((uint8_t)((m_len & 0x0000000000ff0000) >> 16)); GenerateIntVector(usint size,usint h) const95 message.push_back((uint8_t)((m_len & 0x000000000000ff00) >> 8)); 96 message.push_back((uint8_t)(m_len & 0x00000000000000ff)); 97 98 for (size_t n = 0; n < (message.size() * 8) / 512; n++) { 99 uint32_t w[64]; 100 short counter = 0; 101 for (size_t m = 64 * n; m < (64 * (n + 1)); m += 4) { 102 w[counter] = ((uint32_t)message.at(m) << 24) ^ 103 ((uint32_t)message.at(m + 1) << 16) ^ 104 ((uint32_t)message.at(m + 2) << 8) ^ 105 ((uint32_t)message.at(m + 3)); 106 counter++; 107 } 108 for (int i = 16; i < 64; i++) { 109 uint32_t s0 = ((uint32_t)RIGHT_ROT(w[i - 15], 7)) ^ 110 ((uint32_t)(RIGHT_ROT(w[i - 15], 18))) ^ 111 ((uint32_t)(w[i - 15] >> 3)); 112 uint32_t s1 = ((uint32_t)RIGHT_ROT(w[i - 2], 17)) ^ 113 ((uint32_t)RIGHT_ROT(w[i - 2], 19)) ^ 114 ((uint32_t)(w[i - 2] >> 10)); 115 w[i] = w[i - 16] + s0 + w[i - 7] + s1; 116 } 117 118 uint32_t a = h_256[0]; 119 uint32_t b = h_256[1]; 120 uint32_t c = h_256[2]; 121 uint32_t d = h_256[3]; 122 uint32_t e = h_256[4]; 123 uint32_t f = h_256[5]; 124 uint32_t g = h_256[6]; 125 uint32_t h = h_256[7]; 126 127 for (int i = 0; i < 64; i++) { 128 uint32_t S1 = ((uint32_t)RIGHT_ROT(e, 6)) ^ ((uint32_t)RIGHT_ROT(e, 11)) ^ 129 ((uint32_t)RIGHT_ROT(e, 25)); 130 uint32_t ch = (e & f) ^ ((~e) & g); 131 uint32_t temp1 = h + S1 + ch + k_256[i] + w[i]; 132 uint32_t S0 = ((uint32_t)RIGHT_ROT(a, 2)) ^ ((uint32_t)RIGHT_ROT(a, 13)) ^ 133 ((uint32_t)RIGHT_ROT(a, 22)); 134 uint32_t maj = (a & b) ^ (a & c) ^ (b & c); 135 uint32_t temp2 = S0 + maj; 136 137 h = g; 138 g = f; 139 f = e; 140 e = d + temp1; 141 d = c; 142 c = b; 143 b = a; 144 a = temp1 + temp2; 145 } 146 147 h_256[0] += a; 148 h_256[1] += b; 149 h_256[2] += c; 150 h_256[3] += d; 151 h_256[4] += e; 152 h_256[5] += f; 153 h_256[6] += g; 154 h_256[7] += h; 155 } 156 157 for (int i = 0; i < 8; i++) { 158 digest.push_back((uint8_t)((h_256[i] & 0xff000000) >> 24)); 159 digest.push_back((uint8_t)((h_256[i] & 0x00ff0000) >> 16)); 160 digest.push_back((uint8_t)((h_256[i] & 0x0000ff00) >> 8)); 161 digest.push_back((uint8_t)(h_256[i] & 0x000000ff)); 162 } 163 164 return; 165 } 166 167 std::string HashUtil::HashString(std::string message) { 168 uint32_t h_256[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 169 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; 170 171 uint64_t m_len = message.size() * 8; 172 uint16_t pad_len = 1; 173 while ((m_len + pad_len) % 512 != 448) { 174 pad_len++; 175 } 176 177 message += static_cast<char>(0x80); 178 for (int a = 0; a < (pad_len) / 8 - 1; a++) { 179 message += static_cast<char>(0); 180 } 181 message += static_cast<char>((m_len & 0xff00000000000000) >> 56); 182 message += static_cast<char>((m_len & 0x00ff000000000000) >> 48); 183 message += static_cast<char>((m_len & 0x0000ff0000000000) >> 40); 184 message += static_cast<char>((m_len & 0x000000ff00000000) >> 32); 185 message += static_cast<char>((m_len & 0x00000000ff000000) >> 24); 186 message += static_cast<char>((m_len & 0x0000000000ff0000) >> 16); 187 message += static_cast<char>((m_len & 0x000000000000ff00) >> 8); 188 message += static_cast<char>(m_len & 0x00000000000000ff); 189 190 for (size_t n = 0; n < (message.size() * 8) / 512; n++) { 191 uint32_t w[64]; 192 short counter = 0; 193 for (size_t m = 64 * n; m < (64 * (n + 1)); m += 4) { 194 w[counter] = ((uint32_t)(message.at(m) & 0xff) << 24) ^ 195 ((uint32_t)(message.at(m + 1) & 0xff) << 16) ^ 196 ((uint32_t)(message.at(m + 2) & 0xff) << 8) ^ 197 ((uint32_t)(message.at(m + 3) & 0xff)); 198 counter++; 199 } 200 for (int i = 16; i < 64; i++) { 201 uint32_t s0 = ((uint32_t)RIGHT_ROT(w[i - 15], 7)) ^ 202 ((uint32_t)(RIGHT_ROT(w[i - 15], 18))) ^ 203 ((uint32_t)(w[i - 15] >> 3)); 204 uint32_t s1 = ((uint32_t)RIGHT_ROT(w[i - 2], 17)) ^ 205 ((uint32_t)RIGHT_ROT(w[i - 2], 19)) ^ 206 ((uint32_t)(w[i - 2] >> 10)); 207 w[i] = w[i - 16] + s0 + w[i - 7] + s1; 208 } 209 210 uint32_t a = h_256[0]; 211 uint32_t b = h_256[1]; 212 uint32_t c = h_256[2]; 213 uint32_t d = h_256[3]; 214 uint32_t e = h_256[4]; 215 uint32_t f = h_256[5]; 216 uint32_t g = h_256[6]; 217 uint32_t h = h_256[7]; 218 219 for (int i = 0; i < 64; i++) { 220 uint32_t S1 = ((uint32_t)RIGHT_ROT(e, 6)) ^ ((uint32_t)RIGHT_ROT(e, 11)) ^ 221 ((uint32_t)RIGHT_ROT(e, 25)); 222 uint32_t ch = (e & f) ^ ((~e) & g); 223 uint32_t temp1 = h + S1 + ch + k_256[i] + w[i]; 224 uint32_t S0 = ((uint32_t)RIGHT_ROT(a, 2)) ^ ((uint32_t)RIGHT_ROT(a, 13)) ^ 225 ((uint32_t)RIGHT_ROT(a, 22)); 226 uint32_t maj = (a & b) ^ (a & c) ^ (b & c); 227 uint32_t temp2 = S0 + maj; 228 229 h = g; 230 g = f; 231 f = e; 232 e = d + temp1; 233 d = c; 234 c = b; 235 b = a; 236 a = temp1 + temp2; 237 } 238 239 h_256[0] += a; 240 h_256[1] += b; 241 h_256[2] += c; 242 h_256[3] += d; 243 h_256[4] += e; 244 h_256[5] += f; 245 h_256[6] += g; 246 h_256[7] += h; 247 } 248 249 std::stringstream s; 250 s.fill('0'); 251 s << std::hex; 252 for (size_t ii = 0; ii < 8; ii++) s << std::setw(8) << h_256[ii]; 253 254 return s.str(); 255 } 256 257 #if 0 258 lbcrypto::BytePlaintextEncoding HashUtil::SHA512( 259 lbcrypto::BytePlaintextEncoding message) { 260 uint64_t h_512[8] = {0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 261 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 262 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 263 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179}; 264 265 uint128_t m_len = message.size() * 8; 266 uint64_t m_len_first = message.size() / (0x2000000000000000); 267 uint64_t m_len_second = message.size() * 8; 268 uint16_t pad_len = 1; 269 while ((m_len + pad_len) % 1024 != 896) { 270 pad_len++; 271 } 272 message.push_back(128); 273 for (int a = 0; a < (pad_len) / 8 - 1; a++) { 274 message.push_back(0); 275 } 276 277 message.push_back((uint8_t)((m_len_first & 0xff00000000000000) >> 56)); 278 message.push_back((uint8_t)((m_len_first & 0x00ff000000000000) >> 48)); 279 message.push_back((uint8_t)((m_len_first & 0x0000ff0000000000) >> 40)); 280 message.push_back((uint8_t)((m_len_first & 0x000000ff00000000) >> 32)); 281 message.push_back((uint8_t)((m_len_first & 0x00000000ff000000) >> 24)); 282 message.push_back((uint8_t)((m_len_first & 0x0000000000ff0000) >> 16)); 283 message.push_back((uint8_t)((m_len_first & 0x000000000000ff00) >> 8)); 284 message.push_back((uint8_t)(m_len_first & 0x00000000000000ff)); 285 286 message.push_back((uint8_t)((m_len_second & 0xff00000000000000) >> 56)); 287 message.push_back((uint8_t)((m_len_second & 0x00ff000000000000) >> 48)); 288 message.push_back((uint8_t)((m_len_second & 0x0000ff0000000000) >> 40)); 289 message.push_back((uint8_t)((m_len_second & 0x000000ff00000000) >> 32)); 290 message.push_back((uint8_t)((m_len_second & 0x00000000ff000000) >> 24)); 291 message.push_back((uint8_t)((m_len_second & 0x0000000000ff0000) >> 16)); 292 message.push_back((uint8_t)((m_len_second & 0x000000000000ff00) >> 8)); 293 message.push_back((uint8_t)(m_len_second & 0x00000000000000ff)); 294 295 for (int n = 0; n < (message.size() * 8) / 1024; n++) { 296 uint64_t w[80]; 297 short counter = 0; 298 for (int m = 128 * n; m < (128 * (n + 1)); m += 8) { 299 w[counter] = ((uint64_t)message.at(m) << 56) ^ 300 ((uint64_t)message.at(m + 1) << 48) ^ 301 ((uint64_t)message.at(m + 2) << 40) ^ 302 ((uint64_t)message.at(m + 3) << 32) ^ 303 ((uint64_t)message.at(m + 4) << 24) ^ 304 ((uint64_t)message.at(m + 5) << 16) ^ 305 ((uint64_t)message.at(m + 6) << 8) ^ 306 ((uint64_t)message.at(m + 7)); 307 counter++; 308 } 309 for (int i = 16; i < 80; i++) { 310 uint64_t s0 = ((uint64_t)RIGHT_ROT(w[i - 15], 1)) ^ 311 ((uint64_t)(RIGHT_ROT(w[i - 15], 8))) ^ 312 ((uint64_t)(w[i - 15] >> 7)); 313 uint64_t s1 = ((uint64_t)RIGHT_ROT(w[i - 2], 19)) ^ 314 ((uint64_t)RIGHT_ROT(w[i - 2], 61)) ^ 315 ((uint64_t)(w[i - 2] >> 6)); 316 w[i] = w[i - 16] + s0 + w[i - 7] + s1; 317 } 318 319 uint64_t a = h_512[0]; 320 uint64_t b = h_512[1]; 321 uint64_t c = h_512[2]; 322 uint64_t d = h_512[3]; 323 uint64_t e = h_512[4]; 324 uint64_t f = h_512[5]; 325 uint64_t g = h_512[6]; 326 uint64_t h = h_512[7]; 327 328 for (int i = 0; i < 80; i++) { 329 uint64_t S1 = ((uint64_t)RIGHT_ROT(e, 14)) ^ 330 ((uint64_t)RIGHT_ROT(e, 18)) ^ ((uint64_t)RIGHT_ROT(e, 41)); 331 uint64_t ch = (e & f) ^ ((~e) & g); 332 uint64_t temp1 = h + S1 + ch + k_512[i] + w[i]; 333 uint64_t S0 = ((uint64_t)RIGHT_ROT(a, 28)) ^ 334 ((uint64_t)RIGHT_ROT(a, 34)) ^ ((uint64_t)RIGHT_ROT(a, 39)); 335 uint64_t maj = (a & b) ^ (a & c) ^ (b & c); 336 uint64_t temp2 = S0 + maj; 337 338 h = g; 339 g = f; 340 f = e; 341 e = d + temp1; 342 d = c; 343 c = b; 344 b = a; 345 a = temp1 + temp2; 346 } 347 348 h_512[0] += a; 349 h_512[1] += b; 350 h_512[2] += c; 351 h_512[3] += d; 352 h_512[4] += e; 353 h_512[5] += f; 354 h_512[6] += g; 355 h_512[7] += h; 356 } 357 358 lbcrypto::BytePlaintextEncoding digest; 359 for (int i = 0; i < 8; i++) { 360 digest.push_back((uint8_t)((h_512[i] & 0xff00000000000000) >> 56)); 361 digest.push_back((uint8_t)((h_512[i] & 0x00ff000000000000) >> 48)); 362 digest.push_back((uint8_t)((h_512[i] & 0x0000ff0000000000) >> 40)); 363 digest.push_back((uint8_t)((h_512[i] & 0x000000ff00000000) >> 32)); 364 digest.push_back((uint8_t)((h_512[i] & 0x00000000ff000000) >> 24)); 365 digest.push_back((uint8_t)((h_512[i] & 0x0000000000ff0000) >> 16)); 366 digest.push_back((uint8_t)((h_512[i] & 0x000000000000ff00) >> 8)); 367 digest.push_back((uint8_t)(h_512[i] & 0x00000000000000ff)); 368 } 369 370 return digest; 371 } 372 #endif 373 374 } // namespace lbcrypto 375