17 BEGIN_NAMESPACE_CRYPTO
32 , state{ 0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL, 0xc3d2e1f0UL }
40 uint32_t currentLength;
41 unsigned char buffer[64];
44 #define F0(x,y,z) (z ^ (x & (y ^ z))) 45 #define F1(x,y,z) (x ^ y ^ z) 46 #define F2(x,y,z) ((x & y) | (z & (x | y))) 47 #define F3(x,y,z) (x ^ y ^ z) 50 #define ROL(x, y) ( (((uint32_t)(x)<<(uint32_t)((y)&31)) | (((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((32-((y)&31))&31))) & 0xFFFFFFFFUL) 51 #define ROR(x, y) ( ((((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((y)&31)) | ((uint32_t)(x)<<(uint32_t)((32-((y)&31))&31))) & 0xFFFFFFFFUL) 52 #define ROLc(x, y) ( (((uint32_t)(x)<<(uint32_t)((y)&31)) | (((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((32-((y)&31))&31))) & 0xFFFFFFFFUL) 53 #define RORc(x, y) ( ((((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((y)&31)) | ((uint32_t)(x)<<(uint32_t)((32-((y)&31))&31))) & 0xFFFFFFFFUL) 55 #define STORE64H(x, y) \ 56 do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ 57 (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ 58 (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ 59 (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0) 61 #define STORE32H(x, y) \ 62 do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ 63 (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0) 65 #define LOAD32H(x, y) \ 66 do { x = ((uint32_t)((y)[0] & 255)<<24) | \ 67 ((uint32_t)((y)[1] & 255)<<16) | \ 68 ((uint32_t)((y)[2] & 255)<<8) | \ 69 ((uint32_t)((y)[3] & 255)); } while(0) 72 #define MIN(x, y) ( ((x)<(y))?(x):(y) ) 75 constexpr Sha1Status sha1Compress(
Sha1State& md,
const unsigned char* buffer)
81 for (i = 0; i < 16; i++)
83 LOAD32H(W[i], buffer + (4 * i));
87 uint64_t a = md.state[0];
88 uint64_t b = md.state[1];
89 uint64_t c = md.state[2];
90 uint64_t d = md.state[3];
91 uint64_t e = md.state[4];
94 for (i = 16; i < 80; i++)
96 W[i] = ROL(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
101 #define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30); 102 #define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30); 103 #define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30); 104 #define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30); 108 FF0(a, b, c, d, e, i++);
109 FF0(e, a, b, c, d, i++);
110 FF0(d, e, a, b, c, i++);
111 FF0(c, d, e, a, b, i++);
112 FF0(b, c, d, e, a, i++);
118 FF1(a, b, c, d, e, i++);
119 FF1(e, a, b, c, d, i++);
120 FF1(d, e, a, b, c, i++);
121 FF1(c, d, e, a, b, i++);
122 FF1(b, c, d, e, a, i++);
128 FF2(a, b, c, d, e, i++);
129 FF2(e, a, b, c, d, i++);
130 FF2(d, e, a, b, c, i++);
131 FF2(c, d, e, a, b, i++);
132 FF2(b, c, d, e, a, i++);
138 FF3(a, b, c, d, e, i++);
139 FF3(e, a, b, c, d, i++);
140 FF3(d, e, a, b, c, i++);
141 FF3(c, d, e, a, b, i++);
142 FF3(b, c, d, e, a, i++);
151 md.state[0] = (uint32_t)(md.state[0] + a);
152 md.state[1] = (uint32_t)(md.state[1] + b);
153 md.state[2] = (uint32_t)(md.state[2] + c);
154 md.state[3] = (uint32_t)(md.state[3] + d);
155 md.state[4] = (uint32_t)(md.state[4] + e);
157 return Sha1Status::Ok;
168 template <
bool HasTrailingZero = false, std::u
int32_t N>
171 std::uint32_t inLength = HasTrailingZero ? N - 1 : N;
173 const unsigned char* ptr = &in[0];
175 if (md.currentLength >
sizeof(md.buffer))
177 return Sha1Status::InvalidArgument;
180 if ((md.length + inLength) < md.length)
182 return Sha1Status::Overflow;
185 Sha1Status err = Sha1Status::Ok;
188 if (md.currentLength == 0 && inLength >= 64)
190 if ((err = sha1Compress(md, ptr)) != Sha1Status::Ok)
200 const uint32_t n = MIN(inLength, (64 - md.currentLength));
201 unsigned char*
const dest = md.buffer + md.currentLength;
203 for (std::size_t i = 0; i < n; i++)
208 md.currentLength += n;
212 if (md.currentLength == 64)
214 if ((err = sha1Compress(md, (
const unsigned char*)&md.buffer)) != Sha1Status::Ok)
219 md.currentLength = 0;
223 return Sha1Status::Ok;
234 if (md.currentLength >=
sizeof(md.buffer))
236 return Sha1Status::InvalidArgument;
240 md.length += md.currentLength * 8;
243 md.buffer[md.currentLength++] = 0x80;
249 if (md.currentLength > 56)
251 while (md.currentLength < 64)
253 md.buffer[md.currentLength++] = 0;
255 sha1Compress(md, md.buffer);
256 md.currentLength = 0;
260 while (md.currentLength < 56)
262 md.buffer[md.currentLength++] = 0;
266 STORE64H(md.length, md.buffer + 56);
267 sha1Compress(md, md.buffer);
270 for (
int i = 0; i < 5; i++)
272 STORE32H(md.state[i], out + (4 * i));
274 return Sha1Status::Ok;
286 template <
bool HasTrailingZero = false, std::
size_t N >
287 constexpr std::array<unsigned char, 20>
ct_sha1(
const unsigned char (&in)[N])
290 Detail::Sha1Status status = Detail::sha1Process<HasTrailingZero, N>(md, in);
291 if (status == Detail::Sha1Status::InvalidArgument)
293 throw std::runtime_error(
"Invalid argument");
296 if (status == Detail::Sha1Status::Overflow)
298 throw std::runtime_error(
"Overflow");
301 #if __cplusplus >= 201703L 302 std::array<unsigned char, 20> tmp{};
303 Detail::sha1Done(md, &tmp[0]);
307 const std::array<unsigned char, 20> tmp{};
308 Detail::sha1Done(md, (
unsigned char*
const) &tmp[0]);
constexpr std::array< unsigned char, 20 > ct_sha1(const unsigned char(&in)[N])
Calculates the SHA-1 digest in compile-time if the arguments are constexpr.
Definition: sha1.h:287
constexpr Sha1Status sha1Process(Sha1State &md, const unsigned char(&in)[N])
Process a block of memory though the hash.
Definition: sha1.h:169
constexpr Sha1Status sha1Done(Sha1State &md, unsigned char *const out)
Terminate the hash to get the digest.
Definition: sha1.h:232