sdk-world v2026.11.05
PS2 SDK - world tier (copyleft-allowed, non-essential packages)
Loading...
Searching...
No Matches
sha256.cpp
1// //////////////////////////////////////////////////////////
2// sha256.cpp
3// Copyright (c) 2014,2015,2021 Stephan Brumme. All rights reserved.
4// see http://create.stephan-brumme.com/disclaimer.html
5//
6
7#include "sha256.h"
8
9// big endian architectures need #define __BYTE_ORDER __BIG_ENDIAN
10#if defined(__PS2__)
11 #include <machine/endian.h>
12#elif !defined(_MSC_VER)
13 #include <endian.h>
14#endif
15
16//#define SHA2_224_SEED_VECTOR
17
18
21{
22 reset();
23}
24
25
28{
29 m_numBytes = 0;
30 m_bufferSize = 0;
31
32 // according to RFC 1321
33 // "These words were obtained by taking the first thirty-two bits of the
34 // fractional parts of the square roots of the first eight prime numbers"
35 m_hash[0] = 0x6a09e667;
36 m_hash[1] = 0xbb67ae85;
37 m_hash[2] = 0x3c6ef372;
38 m_hash[3] = 0xa54ff53a;
39 m_hash[4] = 0x510e527f;
40 m_hash[5] = 0x9b05688c;
41 m_hash[6] = 0x1f83d9ab;
42 m_hash[7] = 0x5be0cd19;
43
44#ifdef SHA2_224_SEED_VECTOR
45 // if you want SHA2-224 instead then use these seeds
46 // and throw away the last 32 bits of getHash
47 m_hash[0] = 0xc1059ed8;
48 m_hash[1] = 0x367cd507;
49 m_hash[2] = 0x3070dd17;
50 m_hash[3] = 0xf70e5939;
51 m_hash[4] = 0xffc00b31;
52 m_hash[5] = 0x68581511;
53 m_hash[6] = 0x64f98fa7;
54 m_hash[7] = 0xbefa4fa4;
55#endif
56}
57
58
59namespace
60{
61 inline uint32_t rotate(uint32_t a, uint32_t c)
62 {
63 return (a >> c) | (a << (32 - c));
64 }
65
66 inline uint32_t swap(uint32_t x)
67 {
68#if defined(__GNUC__) || defined(__clang__)
69 return __builtin_bswap32(x);
70#endif
71#ifdef MSC_VER
72 return _byteswap_ulong(x);
73#endif
74
75 return (x >> 24) |
76 ((x >> 8) & 0x0000FF00) |
77 ((x << 8) & 0x00FF0000) |
78 (x << 24);
79 }
80
81 // mix functions for processBlock()
82 inline uint32_t f1(uint32_t e, uint32_t f, uint32_t g)
83 {
84 uint32_t term1 = rotate(e, 6) ^ rotate(e, 11) ^ rotate(e, 25);
85 uint32_t term2 = (e & f) ^ (~e & g); //(g ^ (e & (f ^ g)))
86 return term1 + term2;
87 }
88
89 inline uint32_t f2(uint32_t a, uint32_t b, uint32_t c)
90 {
91 uint32_t term1 = rotate(a, 2) ^ rotate(a, 13) ^ rotate(a, 22);
92 uint32_t term2 = ((a | b) & c) | (a & b); //(a & (b ^ c)) ^ (b & c);
93 return term1 + term2;
94 }
95}
96
97
99void SHA256::processBlock(const void* data)
100{
101 // get last hash
102 uint32_t a = m_hash[0];
103 uint32_t b = m_hash[1];
104 uint32_t c = m_hash[2];
105 uint32_t d = m_hash[3];
106 uint32_t e = m_hash[4];
107 uint32_t f = m_hash[5];
108 uint32_t g = m_hash[6];
109 uint32_t h = m_hash[7];
110
111 // data represented as 16x 32-bit words
112 const uint32_t* input = (uint32_t*) data;
113 // convert to big endian
114 uint32_t words[64];
115 int i;
116 for (i = 0; i < 16; i++)
117#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN)
118 words[i] = input[i];
119#else
120 words[i] = swap(input[i]);
121#endif
122
123 uint32_t x,y; // temporaries
124
125 // first round
126 x = h + f1(e,f,g) + 0x428a2f98 + words[ 0]; y = f2(a,b,c); d += x; h = x + y;
127 x = g + f1(d,e,f) + 0x71374491 + words[ 1]; y = f2(h,a,b); c += x; g = x + y;
128 x = f + f1(c,d,e) + 0xb5c0fbcf + words[ 2]; y = f2(g,h,a); b += x; f = x + y;
129 x = e + f1(b,c,d) + 0xe9b5dba5 + words[ 3]; y = f2(f,g,h); a += x; e = x + y;
130 x = d + f1(a,b,c) + 0x3956c25b + words[ 4]; y = f2(e,f,g); h += x; d = x + y;
131 x = c + f1(h,a,b) + 0x59f111f1 + words[ 5]; y = f2(d,e,f); g += x; c = x + y;
132 x = b + f1(g,h,a) + 0x923f82a4 + words[ 6]; y = f2(c,d,e); f += x; b = x + y;
133 x = a + f1(f,g,h) + 0xab1c5ed5 + words[ 7]; y = f2(b,c,d); e += x; a = x + y;
134
135 // secound round
136 x = h + f1(e,f,g) + 0xd807aa98 + words[ 8]; y = f2(a,b,c); d += x; h = x + y;
137 x = g + f1(d,e,f) + 0x12835b01 + words[ 9]; y = f2(h,a,b); c += x; g = x + y;
138 x = f + f1(c,d,e) + 0x243185be + words[10]; y = f2(g,h,a); b += x; f = x + y;
139 x = e + f1(b,c,d) + 0x550c7dc3 + words[11]; y = f2(f,g,h); a += x; e = x + y;
140 x = d + f1(a,b,c) + 0x72be5d74 + words[12]; y = f2(e,f,g); h += x; d = x + y;
141 x = c + f1(h,a,b) + 0x80deb1fe + words[13]; y = f2(d,e,f); g += x; c = x + y;
142 x = b + f1(g,h,a) + 0x9bdc06a7 + words[14]; y = f2(c,d,e); f += x; b = x + y;
143 x = a + f1(f,g,h) + 0xc19bf174 + words[15]; y = f2(b,c,d); e += x; a = x + y;
144
145 // extend to 24 words
146 for (; i < 24; i++)
147 words[i] = words[i-16] +
148 (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
149 words[i-7] +
150 (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
151
152 // third round
153 x = h + f1(e,f,g) + 0xe49b69c1 + words[16]; y = f2(a,b,c); d += x; h = x + y;
154 x = g + f1(d,e,f) + 0xefbe4786 + words[17]; y = f2(h,a,b); c += x; g = x + y;
155 x = f + f1(c,d,e) + 0x0fc19dc6 + words[18]; y = f2(g,h,a); b += x; f = x + y;
156 x = e + f1(b,c,d) + 0x240ca1cc + words[19]; y = f2(f,g,h); a += x; e = x + y;
157 x = d + f1(a,b,c) + 0x2de92c6f + words[20]; y = f2(e,f,g); h += x; d = x + y;
158 x = c + f1(h,a,b) + 0x4a7484aa + words[21]; y = f2(d,e,f); g += x; c = x + y;
159 x = b + f1(g,h,a) + 0x5cb0a9dc + words[22]; y = f2(c,d,e); f += x; b = x + y;
160 x = a + f1(f,g,h) + 0x76f988da + words[23]; y = f2(b,c,d); e += x; a = x + y;
161
162 // extend to 32 words
163 for (; i < 32; i++)
164 words[i] = words[i-16] +
165 (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
166 words[i-7] +
167 (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
168
169 // fourth round
170 x = h + f1(e,f,g) + 0x983e5152 + words[24]; y = f2(a,b,c); d += x; h = x + y;
171 x = g + f1(d,e,f) + 0xa831c66d + words[25]; y = f2(h,a,b); c += x; g = x + y;
172 x = f + f1(c,d,e) + 0xb00327c8 + words[26]; y = f2(g,h,a); b += x; f = x + y;
173 x = e + f1(b,c,d) + 0xbf597fc7 + words[27]; y = f2(f,g,h); a += x; e = x + y;
174 x = d + f1(a,b,c) + 0xc6e00bf3 + words[28]; y = f2(e,f,g); h += x; d = x + y;
175 x = c + f1(h,a,b) + 0xd5a79147 + words[29]; y = f2(d,e,f); g += x; c = x + y;
176 x = b + f1(g,h,a) + 0x06ca6351 + words[30]; y = f2(c,d,e); f += x; b = x + y;
177 x = a + f1(f,g,h) + 0x14292967 + words[31]; y = f2(b,c,d); e += x; a = x + y;
178
179 // extend to 40 words
180 for (; i < 40; i++)
181 words[i] = words[i-16] +
182 (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
183 words[i-7] +
184 (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
185
186 // fifth round
187 x = h + f1(e,f,g) + 0x27b70a85 + words[32]; y = f2(a,b,c); d += x; h = x + y;
188 x = g + f1(d,e,f) + 0x2e1b2138 + words[33]; y = f2(h,a,b); c += x; g = x + y;
189 x = f + f1(c,d,e) + 0x4d2c6dfc + words[34]; y = f2(g,h,a); b += x; f = x + y;
190 x = e + f1(b,c,d) + 0x53380d13 + words[35]; y = f2(f,g,h); a += x; e = x + y;
191 x = d + f1(a,b,c) + 0x650a7354 + words[36]; y = f2(e,f,g); h += x; d = x + y;
192 x = c + f1(h,a,b) + 0x766a0abb + words[37]; y = f2(d,e,f); g += x; c = x + y;
193 x = b + f1(g,h,a) + 0x81c2c92e + words[38]; y = f2(c,d,e); f += x; b = x + y;
194 x = a + f1(f,g,h) + 0x92722c85 + words[39]; y = f2(b,c,d); e += x; a = x + y;
195
196 // extend to 48 words
197 for (; i < 48; i++)
198 words[i] = words[i-16] +
199 (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
200 words[i-7] +
201 (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
202
203 // sixth round
204 x = h + f1(e,f,g) + 0xa2bfe8a1 + words[40]; y = f2(a,b,c); d += x; h = x + y;
205 x = g + f1(d,e,f) + 0xa81a664b + words[41]; y = f2(h,a,b); c += x; g = x + y;
206 x = f + f1(c,d,e) + 0xc24b8b70 + words[42]; y = f2(g,h,a); b += x; f = x + y;
207 x = e + f1(b,c,d) + 0xc76c51a3 + words[43]; y = f2(f,g,h); a += x; e = x + y;
208 x = d + f1(a,b,c) + 0xd192e819 + words[44]; y = f2(e,f,g); h += x; d = x + y;
209 x = c + f1(h,a,b) + 0xd6990624 + words[45]; y = f2(d,e,f); g += x; c = x + y;
210 x = b + f1(g,h,a) + 0xf40e3585 + words[46]; y = f2(c,d,e); f += x; b = x + y;
211 x = a + f1(f,g,h) + 0x106aa070 + words[47]; y = f2(b,c,d); e += x; a = x + y;
212
213 // extend to 56 words
214 for (; i < 56; i++)
215 words[i] = words[i-16] +
216 (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
217 words[i-7] +
218 (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
219
220 // seventh round
221 x = h + f1(e,f,g) + 0x19a4c116 + words[48]; y = f2(a,b,c); d += x; h = x + y;
222 x = g + f1(d,e,f) + 0x1e376c08 + words[49]; y = f2(h,a,b); c += x; g = x + y;
223 x = f + f1(c,d,e) + 0x2748774c + words[50]; y = f2(g,h,a); b += x; f = x + y;
224 x = e + f1(b,c,d) + 0x34b0bcb5 + words[51]; y = f2(f,g,h); a += x; e = x + y;
225 x = d + f1(a,b,c) + 0x391c0cb3 + words[52]; y = f2(e,f,g); h += x; d = x + y;
226 x = c + f1(h,a,b) + 0x4ed8aa4a + words[53]; y = f2(d,e,f); g += x; c = x + y;
227 x = b + f1(g,h,a) + 0x5b9cca4f + words[54]; y = f2(c,d,e); f += x; b = x + y;
228 x = a + f1(f,g,h) + 0x682e6ff3 + words[55]; y = f2(b,c,d); e += x; a = x + y;
229
230 // extend to 64 words
231 for (; i < 64; i++)
232 words[i] = words[i-16] +
233 (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
234 words[i-7] +
235 (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
236
237 // eigth round
238 x = h + f1(e,f,g) + 0x748f82ee + words[56]; y = f2(a,b,c); d += x; h = x + y;
239 x = g + f1(d,e,f) + 0x78a5636f + words[57]; y = f2(h,a,b); c += x; g = x + y;
240 x = f + f1(c,d,e) + 0x84c87814 + words[58]; y = f2(g,h,a); b += x; f = x + y;
241 x = e + f1(b,c,d) + 0x8cc70208 + words[59]; y = f2(f,g,h); a += x; e = x + y;
242 x = d + f1(a,b,c) + 0x90befffa + words[60]; y = f2(e,f,g); h += x; d = x + y;
243 x = c + f1(h,a,b) + 0xa4506ceb + words[61]; y = f2(d,e,f); g += x; c = x + y;
244 x = b + f1(g,h,a) + 0xbef9a3f7 + words[62]; y = f2(c,d,e); f += x; b = x + y;
245 x = a + f1(f,g,h) + 0xc67178f2 + words[63]; y = f2(b,c,d); e += x; a = x + y;
246
247 // update hash
248 m_hash[0] += a;
249 m_hash[1] += b;
250 m_hash[2] += c;
251 m_hash[3] += d;
252 m_hash[4] += e;
253 m_hash[5] += f;
254 m_hash[6] += g;
255 m_hash[7] += h;
256}
257
258
260void SHA256::add(const void* data, size_t numBytes)
261{
262 const uint8_t* current = (const uint8_t*) data;
263
264 if (m_bufferSize > 0)
265 {
266 while (numBytes > 0 && m_bufferSize < BlockSize)
267 {
268 m_buffer[m_bufferSize++] = *current++;
269 numBytes--;
270 }
271 }
272
273 // full buffer
274 if (m_bufferSize == BlockSize)
275 {
276 processBlock(m_buffer);
277 m_numBytes += BlockSize;
278 m_bufferSize = 0;
279 }
280
281 // no more data ?
282 if (numBytes == 0)
283 return;
284
285 // process full blocks
286 while (numBytes >= BlockSize)
287 {
288 processBlock(current);
289 current += BlockSize;
290 m_numBytes += BlockSize;
291 numBytes -= BlockSize;
292 }
293
294 // keep remaining bytes in buffer
295 while (numBytes > 0)
296 {
297 m_buffer[m_bufferSize++] = *current++;
298 numBytes--;
299 }
300}
301
302
304void SHA256::processBuffer()
305{
306 // the input bytes are considered as bits strings, where the first bit is the most significant bit of the byte
307
308 // - append "1" bit to message
309 // - append "0" bits until message length in bit mod 512 is 448
310 // - append length as 64 bit integer
311
312 // number of bits
313 size_t paddedLength = m_bufferSize * 8;
314
315 // plus one bit set to 1 (always appended)
316 paddedLength++;
317
318 // number of bits must be (numBits % 512) = 448
319 size_t lower11Bits = paddedLength & 511;
320 if (lower11Bits <= 448)
321 paddedLength += 448 - lower11Bits;
322 else
323 paddedLength += 512 + 448 - lower11Bits;
324 // convert from bits to bytes
325 paddedLength /= 8;
326
327 // only needed if additional data flows over into a second block
328 unsigned char extra[BlockSize];
329
330 // append a "1" bit, 128 => binary 10000000
331 if (m_bufferSize < BlockSize)
332 m_buffer[m_bufferSize] = 128;
333 else
334 extra[0] = 128;
335
336 size_t i;
337 for (i = m_bufferSize + 1; i < BlockSize; i++)
338 m_buffer[i] = 0;
339 for (; i < paddedLength; i++)
340 extra[i - BlockSize] = 0;
341
342 // add message length in bits as 64 bit number
343 uint64_t msgBits = 8 * (m_numBytes + m_bufferSize);
344 // find right position
345 unsigned char* addLength;
346 if (paddedLength < BlockSize)
347 addLength = m_buffer + paddedLength;
348 else
349 addLength = extra + paddedLength - BlockSize;
350
351 // must be big endian
352 *addLength++ = (unsigned char)((msgBits >> 56) & 0xFF);
353 *addLength++ = (unsigned char)((msgBits >> 48) & 0xFF);
354 *addLength++ = (unsigned char)((msgBits >> 40) & 0xFF);
355 *addLength++ = (unsigned char)((msgBits >> 32) & 0xFF);
356 *addLength++ = (unsigned char)((msgBits >> 24) & 0xFF);
357 *addLength++ = (unsigned char)((msgBits >> 16) & 0xFF);
358 *addLength++ = (unsigned char)((msgBits >> 8) & 0xFF);
359 *addLength = (unsigned char)( msgBits & 0xFF);
360
361 // process blocks
362 processBlock(m_buffer);
363 // flowed over into a second block ?
364 if (paddedLength > BlockSize)
365 processBlock(extra);
366}
367
368
370std::string SHA256::getHash()
371{
372 // compute hash (as raw bytes)
373 unsigned char rawHash[HashBytes];
374 getHash(rawHash);
375
376 // convert to hex string
377 std::string result;
378 result.reserve(2 * HashBytes);
379 for (int i = 0; i < HashBytes; i++)
380 {
381 static const char dec2hex[16+1] = "0123456789abcdef";
382 result += dec2hex[(rawHash[i] >> 4) & 15];
383 result += dec2hex[ rawHash[i] & 15];
384 }
385
386 return result;
387}
388
389
391void SHA256::getHash(unsigned char buffer[SHA256::HashBytes])
392{
393 // save old hash if buffer is partially filled
394 uint32_t oldHash[HashValues];
395 for (int i = 0; i < HashValues; i++)
396 oldHash[i] = m_hash[i];
397
398 // process remaining bytes
399 processBuffer();
400
401 unsigned char* current = buffer;
402 for (int i = 0; i < HashValues; i++)
403 {
404 *current++ = (m_hash[i] >> 24) & 0xFF;
405 *current++ = (m_hash[i] >> 16) & 0xFF;
406 *current++ = (m_hash[i] >> 8) & 0xFF;
407 *current++ = m_hash[i] & 0xFF;
408
409 // restore old hash
410 m_hash[i] = oldHash[i];
411 }
412}
413
414
416std::string SHA256::operator()(const void* data, size_t numBytes)
417{
418 reset();
419 add(data, numBytes);
420 return getHash();
421}
422
423
425std::string SHA256::operator()(const std::string& text)
426{
427 reset();
428 add(text.c_str(), text.size());
429 return getHash();
430}
void add(const void *data, size_t numBytes)
add arbitrary number of bytes
Definition sha256.cpp:260
std::string operator()(const void *data, size_t numBytes)
compute SHA256 of a memory block
Definition sha256.cpp:416
SHA256()
same as reset()
Definition sha256.cpp:20
void reset()
restart
Definition sha256.cpp:27
std::string getHash()
return latest hash as 64 hex characters
Definition sha256.cpp:370