/src/crow/include/crow/TinySHA1.hpp
Line | Count | Source |
1 | | /* |
2 | | * SHA1 Wikipedia Page: http://en.wikipedia.org/wiki/SHA-1 |
3 | | * |
4 | | * Copyright (c) 2012-22 SAURAV MOHAPATRA <mohaps@gmail.com> |
5 | | * |
6 | | * Permission to use, copy, modify, and distribute this software for any |
7 | | * purpose with or without fee is hereby granted, provided that the above |
8 | | * copyright notice and this permission notice appear in all copies. |
9 | | * |
10 | | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 | | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
12 | | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
13 | | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
14 | | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
15 | | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
16 | | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 | | */ |
18 | | |
19 | | /** |
20 | | * \file TinySHA1.hpp |
21 | | * \author SAURAV MOHAPATRA <mohaps@gmail.com> |
22 | | * \date 2012-22 |
23 | | * \brief TinySHA1 - a header only implementation of the SHA1 algorithm in C++. Based |
24 | | * on the implementation in boost::uuid::details. |
25 | | * |
26 | | * In this file are defined: |
27 | | * - sha1::SHA1 |
28 | | */ |
29 | | #ifndef _TINY_SHA1_HPP_ |
30 | | #define _TINY_SHA1_HPP_ |
31 | | #include <cstdio> |
32 | | #include <cstdlib> |
33 | | #include <cstring> |
34 | | #include <stdint.h> |
35 | | |
36 | | /** |
37 | | * \namespace sha1 |
38 | | * \brief Here is defined the SHA1 class |
39 | | */ |
40 | | namespace sha1 |
41 | | { |
42 | | /** |
43 | | * \class SHA1 |
44 | | * \brief A tiny SHA1 algorithm implementation used internally in the |
45 | | * Crow server (specifically in crow/websocket.h). |
46 | | */ |
47 | | class SHA1 |
48 | | { |
49 | | public: |
50 | | typedef uint32_t digest32_t[5]; |
51 | | typedef uint8_t digest8_t[20]; |
52 | 0 | inline static uint32_t LeftRotate(uint32_t value, size_t count) { |
53 | 0 | return (value << count) ^ (value >> (32-count)); |
54 | 0 | } |
55 | 0 | SHA1(){ reset(); } |
56 | 0 | virtual ~SHA1() {} |
57 | 0 | SHA1(const SHA1& s) { *this = s; } |
58 | 0 | const SHA1& operator = (const SHA1& s) { |
59 | 0 | memcpy(m_digest, s.m_digest, 5 * sizeof(uint32_t)); |
60 | 0 | memcpy(m_block, s.m_block, 64); |
61 | 0 | m_blockByteIndex = s.m_blockByteIndex; |
62 | 0 | m_byteCount = s.m_byteCount; |
63 | 0 | return *this; |
64 | 0 | } |
65 | 0 | SHA1& reset() { |
66 | 0 | m_digest[0] = 0x67452301; |
67 | 0 | m_digest[1] = 0xEFCDAB89; |
68 | 0 | m_digest[2] = 0x98BADCFE; |
69 | 0 | m_digest[3] = 0x10325476; |
70 | 0 | m_digest[4] = 0xC3D2E1F0; |
71 | 0 | m_blockByteIndex = 0; |
72 | 0 | m_byteCount = 0; |
73 | 0 | return *this; |
74 | 0 | } |
75 | 0 | SHA1& processByte(uint8_t octet) { |
76 | 0 | this->m_block[this->m_blockByteIndex++] = octet; |
77 | 0 | ++this->m_byteCount; |
78 | 0 | if(m_blockByteIndex == 64) { |
79 | 0 | this->m_blockByteIndex = 0; |
80 | 0 | processBlock(); |
81 | 0 | } |
82 | 0 | return *this; |
83 | 0 | } |
84 | 0 | SHA1& processBlock(const void* const start, const void* const end) { |
85 | 0 | const uint8_t* begin = static_cast<const uint8_t*>(start); |
86 | 0 | const uint8_t* finish = static_cast<const uint8_t*>(end); |
87 | 0 | while(begin != finish) { |
88 | 0 | processByte(*begin); |
89 | 0 | begin++; |
90 | 0 | } |
91 | 0 | return *this; |
92 | 0 | } |
93 | 0 | SHA1& processBytes(const void* const data, size_t len) { |
94 | 0 | const uint8_t* block = static_cast<const uint8_t*>(data); |
95 | 0 | processBlock(block, block + len); |
96 | 0 | return *this; |
97 | 0 | } |
98 | 0 | const uint32_t* getDigest(digest32_t digest) { |
99 | 0 | size_t bitCount = this->m_byteCount * 8; |
100 | 0 | processByte(0x80); |
101 | 0 | if (this->m_blockByteIndex > 56) { |
102 | 0 | while (m_blockByteIndex != 0) { |
103 | 0 | processByte(0); |
104 | 0 | } |
105 | 0 | while (m_blockByteIndex < 56) { |
106 | 0 | processByte(0); |
107 | 0 | } |
108 | 0 | } else { |
109 | 0 | while (m_blockByteIndex < 56) { |
110 | 0 | processByte(0); |
111 | 0 | } |
112 | 0 | } |
113 | 0 | processByte(0); |
114 | 0 | processByte(0); |
115 | 0 | processByte(0); |
116 | 0 | processByte(0); |
117 | 0 | processByte( static_cast<unsigned char>((bitCount>>24) & 0xFF)); |
118 | 0 | processByte( static_cast<unsigned char>((bitCount>>16) & 0xFF)); |
119 | 0 | processByte( static_cast<unsigned char>((bitCount>>8 ) & 0xFF)); |
120 | 0 | processByte( static_cast<unsigned char>((bitCount) & 0xFF)); |
121 | 0 |
|
122 | 0 | memcpy(digest, m_digest, 5 * sizeof(uint32_t)); |
123 | 0 | return digest; |
124 | 0 | } |
125 | 0 | const uint8_t* getDigestBytes(digest8_t digest) { |
126 | 0 | digest32_t d32; |
127 | 0 | getDigest(d32); |
128 | 0 | size_t di = 0; |
129 | 0 | digest[di++] = ((d32[0] >> 24) & 0xFF); |
130 | 0 | digest[di++] = ((d32[0] >> 16) & 0xFF); |
131 | 0 | digest[di++] = ((d32[0] >> 8) & 0xFF); |
132 | 0 | digest[di++] = ((d32[0]) & 0xFF); |
133 | 0 |
|
134 | 0 | digest[di++] = ((d32[1] >> 24) & 0xFF); |
135 | 0 | digest[di++] = ((d32[1] >> 16) & 0xFF); |
136 | 0 | digest[di++] = ((d32[1] >> 8) & 0xFF); |
137 | 0 | digest[di++] = ((d32[1]) & 0xFF); |
138 | 0 |
|
139 | 0 | digest[di++] = ((d32[2] >> 24) & 0xFF); |
140 | 0 | digest[di++] = ((d32[2] >> 16) & 0xFF); |
141 | 0 | digest[di++] = ((d32[2] >> 8) & 0xFF); |
142 | 0 | digest[di++] = ((d32[2]) & 0xFF); |
143 | 0 |
|
144 | 0 | digest[di++] = ((d32[3] >> 24) & 0xFF); |
145 | 0 | digest[di++] = ((d32[3] >> 16) & 0xFF); |
146 | 0 | digest[di++] = ((d32[3] >> 8) & 0xFF); |
147 | 0 | digest[di++] = ((d32[3]) & 0xFF); |
148 | 0 |
|
149 | 0 | digest[di++] = ((d32[4] >> 24) & 0xFF); |
150 | 0 | digest[di++] = ((d32[4] >> 16) & 0xFF); |
151 | 0 | digest[di++] = ((d32[4] >> 8) & 0xFF); |
152 | 0 | digest[di++] = ((d32[4]) & 0xFF); |
153 | 0 | return digest; |
154 | 0 | } |
155 | | |
156 | | protected: |
157 | 0 | void processBlock() { |
158 | 0 | uint32_t w[80]; |
159 | 0 | for (size_t i = 0; i < 16; i++) { |
160 | 0 | w[i] = (m_block[i*4 + 0] << 24); |
161 | 0 | w[i] |= (m_block[i*4 + 1] << 16); |
162 | 0 | w[i] |= (m_block[i*4 + 2] << 8); |
163 | 0 | w[i] |= (m_block[i*4 + 3]); |
164 | 0 | } |
165 | 0 | for (size_t i = 16; i < 80; i++) { |
166 | 0 | w[i] = LeftRotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1); |
167 | 0 | } |
168 | 0 |
|
169 | 0 | uint32_t a = m_digest[0]; |
170 | 0 | uint32_t b = m_digest[1]; |
171 | 0 | uint32_t c = m_digest[2]; |
172 | 0 | uint32_t d = m_digest[3]; |
173 | 0 | uint32_t e = m_digest[4]; |
174 | 0 |
|
175 | 0 | for (std::size_t i=0; i<80; ++i) { |
176 | 0 | uint32_t f = 0; |
177 | 0 | uint32_t k = 0; |
178 | 0 |
|
179 | 0 | if (i<20) { |
180 | 0 | f = (b & c) | (~b & d); |
181 | 0 | k = 0x5A827999; |
182 | 0 | } else if (i<40) { |
183 | 0 | f = b ^ c ^ d; |
184 | 0 | k = 0x6ED9EBA1; |
185 | 0 | } else if (i<60) { |
186 | 0 | f = (b & c) | (b & d) | (c & d); |
187 | 0 | k = 0x8F1BBCDC; |
188 | 0 | } else { |
189 | 0 | f = b ^ c ^ d; |
190 | 0 | k = 0xCA62C1D6; |
191 | 0 | } |
192 | 0 | uint32_t temp = LeftRotate(a, 5) + f + e + k + w[i]; |
193 | 0 | e = d; |
194 | 0 | d = c; |
195 | 0 | c = LeftRotate(b, 30); |
196 | 0 | b = a; |
197 | 0 | a = temp; |
198 | 0 | } |
199 | 0 |
|
200 | 0 | m_digest[0] += a; |
201 | 0 | m_digest[1] += b; |
202 | 0 | m_digest[2] += c; |
203 | 0 | m_digest[3] += d; |
204 | 0 | m_digest[4] += e; |
205 | 0 | } |
206 | | private: |
207 | | digest32_t m_digest; |
208 | | uint8_t m_block[64]; |
209 | | size_t m_blockByteIndex; |
210 | | size_t m_byteCount; |
211 | | }; |
212 | | } |
213 | | #endif |