sdk-world v2026.11.05
PS2 SDK - world tier (copyleft-allowed, non-essential packages)
Loading...
Searching...
No Matches
sha1.cpp
1// //////////////////////////////////////////////////////////
2// sha1.cpp
3// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
4// see http://create.stephan-brumme.com/disclaimer.html
5//
6
7#include "sha1.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
19{
20 reset();
21}
22
23
26{
27 m_numBytes = 0;
28 m_bufferSize = 0;
29
30 // according to RFC 1321
31 m_hash[0] = 0x67452301;
32 m_hash[1] = 0xefcdab89;
33 m_hash[2] = 0x98badcfe;
34 m_hash[3] = 0x10325476;
35 m_hash[4] = 0xc3d2e1f0;
36}
37
38
39namespace
40{
41 // mix functions for processBlock()
42 inline uint32_t f1(uint32_t b, uint32_t c, uint32_t d)
43 {
44 return d ^ (b & (c ^ d)); // original: f = (b & c) | ((~b) & d);
45 }
46
47 inline uint32_t f2(uint32_t b, uint32_t c, uint32_t d)
48 {
49 return b ^ c ^ d;
50 }
51
52 inline uint32_t f3(uint32_t b, uint32_t c, uint32_t d)
53 {
54 return (b & c) | (b & d) | (c & d);
55 }
56
57 inline uint32_t rotate(uint32_t a, uint32_t c)
58 {
59 return (a << c) | (a >> (32 - c));
60 }
61
62 inline uint32_t swap(uint32_t x)
63 {
64#if defined(__GNUC__) || defined(__clang__)
65 return __builtin_bswap32(x);
66#endif
67#ifdef MSC_VER
68 return _byteswap_ulong(x);
69#endif
70
71 return (x >> 24) |
72 ((x >> 8) & 0x0000FF00) |
73 ((x << 8) & 0x00FF0000) |
74 (x << 24);
75 }
76}
77
78
80void SHA1::processBlock(const void* data)
81{
82 // get last hash
83 uint32_t a = m_hash[0];
84 uint32_t b = m_hash[1];
85 uint32_t c = m_hash[2];
86 uint32_t d = m_hash[3];
87 uint32_t e = m_hash[4];
88
89 // data represented as 16x 32-bit words
90 const uint32_t* input = (uint32_t*) data;
91 // convert to big endian
92 uint32_t words[80];
93 for (int i = 0; i < 16; i++)
94#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN)
95 words[i] = input[i];
96#else
97 words[i] = swap(input[i]);
98#endif
99
100 // extend to 80 words
101 for (int i = 16; i < 80; i++)
102 words[i] = rotate(words[i-3] ^ words[i-8] ^ words[i-14] ^ words[i-16], 1);
103
104 // first round
105 for (int i = 0; i < 4; i++)
106 {
107 int offset = 5*i;
108 e += rotate(a,5) + f1(b,c,d) + words[offset ] + 0x5a827999; b = rotate(b,30);
109 d += rotate(e,5) + f1(a,b,c) + words[offset+1] + 0x5a827999; a = rotate(a,30);
110 c += rotate(d,5) + f1(e,a,b) + words[offset+2] + 0x5a827999; e = rotate(e,30);
111 b += rotate(c,5) + f1(d,e,a) + words[offset+3] + 0x5a827999; d = rotate(d,30);
112 a += rotate(b,5) + f1(c,d,e) + words[offset+4] + 0x5a827999; c = rotate(c,30);
113 }
114
115 // second round
116 for (int i = 4; i < 8; i++)
117 {
118 int offset = 5*i;
119 e += rotate(a,5) + f2(b,c,d) + words[offset ] + 0x6ed9eba1; b = rotate(b,30);
120 d += rotate(e,5) + f2(a,b,c) + words[offset+1] + 0x6ed9eba1; a = rotate(a,30);
121 c += rotate(d,5) + f2(e,a,b) + words[offset+2] + 0x6ed9eba1; e = rotate(e,30);
122 b += rotate(c,5) + f2(d,e,a) + words[offset+3] + 0x6ed9eba1; d = rotate(d,30);
123 a += rotate(b,5) + f2(c,d,e) + words[offset+4] + 0x6ed9eba1; c = rotate(c,30);
124 }
125
126 // third round
127 for (int i = 8; i < 12; i++)
128 {
129 int offset = 5*i;
130 e += rotate(a,5) + f3(b,c,d) + words[offset ] + 0x8f1bbcdc; b = rotate(b,30);
131 d += rotate(e,5) + f3(a,b,c) + words[offset+1] + 0x8f1bbcdc; a = rotate(a,30);
132 c += rotate(d,5) + f3(e,a,b) + words[offset+2] + 0x8f1bbcdc; e = rotate(e,30);
133 b += rotate(c,5) + f3(d,e,a) + words[offset+3] + 0x8f1bbcdc; d = rotate(d,30);
134 a += rotate(b,5) + f3(c,d,e) + words[offset+4] + 0x8f1bbcdc; c = rotate(c,30);
135 }
136
137 // fourth round
138 for (int i = 12; i < 16; i++)
139 {
140 int offset = 5*i;
141 e += rotate(a,5) + f2(b,c,d) + words[offset ] + 0xca62c1d6; b = rotate(b,30);
142 d += rotate(e,5) + f2(a,b,c) + words[offset+1] + 0xca62c1d6; a = rotate(a,30);
143 c += rotate(d,5) + f2(e,a,b) + words[offset+2] + 0xca62c1d6; e = rotate(e,30);
144 b += rotate(c,5) + f2(d,e,a) + words[offset+3] + 0xca62c1d6; d = rotate(d,30);
145 a += rotate(b,5) + f2(c,d,e) + words[offset+4] + 0xca62c1d6; c = rotate(c,30);
146 }
147
148 // update hash
149 m_hash[0] += a;
150 m_hash[1] += b;
151 m_hash[2] += c;
152 m_hash[3] += d;
153 m_hash[4] += e;
154}
155
156
158void SHA1::add(const void* data, size_t numBytes)
159{
160 const uint8_t* current = (const uint8_t*) data;
161
162 if (m_bufferSize > 0)
163 {
164 while (numBytes > 0 && m_bufferSize < BlockSize)
165 {
166 m_buffer[m_bufferSize++] = *current++;
167 numBytes--;
168 }
169 }
170
171 // full buffer
172 if (m_bufferSize == BlockSize)
173 {
174 processBlock((void*)m_buffer);
175 m_numBytes += BlockSize;
176 m_bufferSize = 0;
177 }
178
179 // no more data ?
180 if (numBytes == 0)
181 return;
182
183 // process full blocks
184 while (numBytes >= BlockSize)
185 {
186 processBlock(current);
187 current += BlockSize;
188 m_numBytes += BlockSize;
189 numBytes -= BlockSize;
190 }
191
192 // keep remaining bytes in buffer
193 while (numBytes > 0)
194 {
195 m_buffer[m_bufferSize++] = *current++;
196 numBytes--;
197 }
198}
199
200
202void SHA1::processBuffer()
203{
204 // the input bytes are considered as bits strings, where the first bit is the most significant bit of the byte
205
206 // - append "1" bit to message
207 // - append "0" bits until message length in bit mod 512 is 448
208 // - append length as 64 bit integer
209
210 // number of bits
211 size_t paddedLength = m_bufferSize * 8;
212
213 // plus one bit set to 1 (always appended)
214 paddedLength++;
215
216 // number of bits must be (numBits % 512) = 448
217 size_t lower11Bits = paddedLength & 511;
218 if (lower11Bits <= 448)
219 paddedLength += 448 - lower11Bits;
220 else
221 paddedLength += 512 + 448 - lower11Bits;
222 // convert from bits to bytes
223 paddedLength /= 8;
224
225 // only needed if additional data flows over into a second block
226 unsigned char extra[BlockSize];
227
228 // append a "1" bit, 128 => binary 10000000
229 if (m_bufferSize < BlockSize)
230 m_buffer[m_bufferSize] = 128;
231 else
232 extra[0] = 128;
233
234 size_t i;
235 for (i = m_bufferSize + 1; i < BlockSize; i++)
236 m_buffer[i] = 0;
237 for (; i < paddedLength; i++)
238 extra[i - BlockSize] = 0;
239
240 // add message length in bits as 64 bit number
241 uint64_t msgBits = 8 * (m_numBytes + m_bufferSize);
242 // find right position
243 unsigned char* addLength;
244 if (paddedLength < BlockSize)
245 addLength = m_buffer + paddedLength;
246 else
247 addLength = extra + paddedLength - BlockSize;
248
249 // must be big endian
250 *addLength++ = (unsigned char)((msgBits >> 56) & 0xFF);
251 *addLength++ = (unsigned char)((msgBits >> 48) & 0xFF);
252 *addLength++ = (unsigned char)((msgBits >> 40) & 0xFF);
253 *addLength++ = (unsigned char)((msgBits >> 32) & 0xFF);
254 *addLength++ = (unsigned char)((msgBits >> 24) & 0xFF);
255 *addLength++ = (unsigned char)((msgBits >> 16) & 0xFF);
256 *addLength++ = (unsigned char)((msgBits >> 8) & 0xFF);
257 *addLength = (unsigned char)( msgBits & 0xFF);
258
259 // process blocks
260 processBlock(m_buffer);
261 // flowed over into a second block ?
262 if (paddedLength > BlockSize)
263 processBlock(extra);
264}
265
266
268std::string SHA1::getHash()
269{
270 // compute hash (as raw bytes)
271 unsigned char rawHash[HashBytes];
272 getHash(rawHash);
273
274 // convert to hex string
275 std::string result;
276 result.reserve(2 * HashBytes);
277 for (int i = 0; i < HashBytes; i++)
278 {
279 static const char dec2hex[16+1] = "0123456789abcdef";
280 result += dec2hex[(rawHash[i] >> 4) & 15];
281 result += dec2hex[ rawHash[i] & 15];
282 }
283
284 return result;
285}
286
287
289void SHA1::getHash(unsigned char buffer[SHA1::HashBytes])
290{
291 // save old hash if buffer is partially filled
292 uint32_t oldHash[HashValues];
293 for (int i = 0; i < HashValues; i++)
294 oldHash[i] = m_hash[i];
295
296 // process remaining bytes
297 processBuffer();
298
299 unsigned char* current = buffer;
300 for (int i = 0; i < HashValues; i++)
301 {
302 *current++ = (m_hash[i] >> 24) & 0xFF;
303 *current++ = (m_hash[i] >> 16) & 0xFF;
304 *current++ = (m_hash[i] >> 8) & 0xFF;
305 *current++ = m_hash[i] & 0xFF;
306
307 // restore old hash
308 m_hash[i] = oldHash[i];
309 }
310}
311
312
314std::string SHA1::operator()(const void* data, size_t numBytes)
315{
316 reset();
317 add(data, numBytes);
318 return getHash();
319}
320
321
323std::string SHA1::operator()(const std::string& text)
324{
325 reset();
326 add(text.c_str(), text.size());
327 return getHash();
328}
void add(const void *data, size_t numBytes)
add arbitrary number of bytes
Definition sha1.cpp:158
std::string operator()(const void *data, size_t numBytes)
compute SHA1 of a memory block
Definition sha1.cpp:314
std::string getHash()
return latest hash as 40 hex characters
Definition sha1.cpp:268
void reset()
restart
Definition sha1.cpp:25
SHA1()
same as reset()
Definition sha1.cpp:18