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