sha1_digest.cpp (7512B)
1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com> 2 // SPDX-License-Identifier: (GPL-3.0 OR PolyForm-Strict-1.0.0) 3 4 #include "sha1_digest.h" 5 #include "assert.h" 6 7 #include <cstring> 8 9 // mostly based on this implementation (public domain): https://gist.github.com/jrabbit/1042021 10 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) 11 12 /* blk0() and blk() perform the initial expand. */ 13 /* I got the idea of expanding during the round function from SSLeay */ 14 #define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | (rol(block->l[i], 8) & 0x00FF00FF)) 15 #define blk(i) \ 16 (block->l[i & 15] = \ 17 rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1)) 18 19 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ 20 #define R0(v, w, x, y, z, i) \ 21 z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \ 22 w = rol(w, 30); 23 #define R1(v, w, x, y, z, i) \ 24 z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ 25 w = rol(w, 30); 26 #define R2(v, w, x, y, z, i) \ 27 z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \ 28 w = rol(w, 30); 29 #define R3(v, w, x, y, z, i) \ 30 z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ 31 w = rol(w, 30); 32 #define R4(v, w, x, y, z, i) \ 33 z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ 34 w = rol(w, 30); 35 36 /* Hash a single 512-bit block. This is the core of the algorithm. */ 37 38 static void SHA1Transform(u32 state[5], const unsigned char buffer[64]) 39 { 40 u32 a, b, c, d, e; 41 typedef union 42 { 43 unsigned char c[64]; 44 u32 l[16]; 45 } CHAR64LONG16; 46 47 CHAR64LONG16 block[1]; /* use array to appear as a pointer */ 48 std::memcpy(block, buffer, 64); 49 50 /* Copy context->state[] to working vars */ 51 a = state[0]; 52 b = state[1]; 53 c = state[2]; 54 d = state[3]; 55 e = state[4]; 56 /* 4 rounds of 20 operations each. Loop unrolled. */ 57 R0(a, b, c, d, e, 0); 58 R0(e, a, b, c, d, 1); 59 R0(d, e, a, b, c, 2); 60 R0(c, d, e, a, b, 3); 61 R0(b, c, d, e, a, 4); 62 R0(a, b, c, d, e, 5); 63 R0(e, a, b, c, d, 6); 64 R0(d, e, a, b, c, 7); 65 R0(c, d, e, a, b, 8); 66 R0(b, c, d, e, a, 9); 67 R0(a, b, c, d, e, 10); 68 R0(e, a, b, c, d, 11); 69 R0(d, e, a, b, c, 12); 70 R0(c, d, e, a, b, 13); 71 R0(b, c, d, e, a, 14); 72 R0(a, b, c, d, e, 15); 73 R1(e, a, b, c, d, 16); 74 R1(d, e, a, b, c, 17); 75 R1(c, d, e, a, b, 18); 76 R1(b, c, d, e, a, 19); 77 R2(a, b, c, d, e, 20); 78 R2(e, a, b, c, d, 21); 79 R2(d, e, a, b, c, 22); 80 R2(c, d, e, a, b, 23); 81 R2(b, c, d, e, a, 24); 82 R2(a, b, c, d, e, 25); 83 R2(e, a, b, c, d, 26); 84 R2(d, e, a, b, c, 27); 85 R2(c, d, e, a, b, 28); 86 R2(b, c, d, e, a, 29); 87 R2(a, b, c, d, e, 30); 88 R2(e, a, b, c, d, 31); 89 R2(d, e, a, b, c, 32); 90 R2(c, d, e, a, b, 33); 91 R2(b, c, d, e, a, 34); 92 R2(a, b, c, d, e, 35); 93 R2(e, a, b, c, d, 36); 94 R2(d, e, a, b, c, 37); 95 R2(c, d, e, a, b, 38); 96 R2(b, c, d, e, a, 39); 97 R3(a, b, c, d, e, 40); 98 R3(e, a, b, c, d, 41); 99 R3(d, e, a, b, c, 42); 100 R3(c, d, e, a, b, 43); 101 R3(b, c, d, e, a, 44); 102 R3(a, b, c, d, e, 45); 103 R3(e, a, b, c, d, 46); 104 R3(d, e, a, b, c, 47); 105 R3(c, d, e, a, b, 48); 106 R3(b, c, d, e, a, 49); 107 R3(a, b, c, d, e, 50); 108 R3(e, a, b, c, d, 51); 109 R3(d, e, a, b, c, 52); 110 R3(c, d, e, a, b, 53); 111 R3(b, c, d, e, a, 54); 112 R3(a, b, c, d, e, 55); 113 R3(e, a, b, c, d, 56); 114 R3(d, e, a, b, c, 57); 115 R3(c, d, e, a, b, 58); 116 R3(b, c, d, e, a, 59); 117 R4(a, b, c, d, e, 60); 118 R4(e, a, b, c, d, 61); 119 R4(d, e, a, b, c, 62); 120 R4(c, d, e, a, b, 63); 121 R4(b, c, d, e, a, 64); 122 R4(a, b, c, d, e, 65); 123 R4(e, a, b, c, d, 66); 124 R4(d, e, a, b, c, 67); 125 R4(c, d, e, a, b, 68); 126 R4(b, c, d, e, a, 69); 127 R4(a, b, c, d, e, 70); 128 R4(e, a, b, c, d, 71); 129 R4(d, e, a, b, c, 72); 130 R4(c, d, e, a, b, 73); 131 R4(b, c, d, e, a, 74); 132 R4(a, b, c, d, e, 75); 133 R4(e, a, b, c, d, 76); 134 R4(d, e, a, b, c, 77); 135 R4(c, d, e, a, b, 78); 136 R4(b, c, d, e, a, 79); 137 /* Add the working vars back into context.state[] */ 138 state[0] += a; 139 state[1] += b; 140 state[2] += c; 141 state[3] += d; 142 state[4] += e; 143 } 144 145 SHA1Digest::SHA1Digest() 146 { 147 Reset(); 148 } 149 150 /* SHA1Init - Initialize new context */ 151 152 void SHA1Digest::Reset() 153 { 154 /* SHA1 initialization constants */ 155 state[0] = 0x67452301; 156 state[1] = 0xEFCDAB89; 157 state[2] = 0x98BADCFE; 158 state[3] = 0x10325476; 159 state[4] = 0xC3D2E1F0; 160 count[0] = count[1] = 0; 161 } 162 163 std::string SHA1Digest::DigestToString(const std::span<u8, DIGEST_SIZE> digest) 164 { 165 std::string ret; 166 ret.reserve(DIGEST_SIZE * 2); 167 for (u32 i = 0; i < DIGEST_SIZE; i++) 168 { 169 u8 nibble = digest[i] >> 4; 170 if (nibble >= 0xA) 171 ret.push_back('A' + (nibble - 0xA)); 172 else 173 ret.push_back('0' + nibble); 174 nibble = digest[i] & 0xF; 175 if (nibble >= 0xA) 176 ret.push_back('A' + (nibble - 0xA)); 177 else 178 ret.push_back('0' + nibble); 179 } 180 return ret; 181 } 182 183 std::array<u8, SHA1Digest::DIGEST_SIZE> SHA1Digest::GetDigest(const void* data, size_t len) 184 { 185 std::array<u8, SHA1Digest::DIGEST_SIZE> ret; 186 SHA1Digest digest; 187 digest.Update(data, len); 188 digest.Final(ret.data()); 189 return ret; 190 } 191 192 std::array<u8, SHA1Digest::DIGEST_SIZE> SHA1Digest::GetDigest(std::span<const u8> data) 193 { 194 std::array<u8, SHA1Digest::DIGEST_SIZE> ret; 195 SHA1Digest digest; 196 digest.Update(data); 197 digest.Final(ret.data()); 198 return ret; 199 } 200 201 /* Run your data through this. */ 202 203 void SHA1Digest::Update(const void* data, size_t len) 204 { 205 const u8* bdata = static_cast<const u8*>(data); 206 Assert(len <= std::numeric_limits<u32>::max()); 207 const u32 ulen = static_cast<u32>(len); 208 209 u32 i; 210 u32 j = count[0]; 211 if ((count[0] += ulen << 3) < j) 212 count[1]++; 213 count[1] += (ulen >> 29); 214 j = (j >> 3) & 63; 215 if ((j + ulen) > 63) 216 { 217 std::memcpy(&buffer[j], bdata, (i = 64 - j)); 218 SHA1Transform(state, buffer); 219 for (; i + 63 < ulen; i += 64) 220 { 221 SHA1Transform(state, &bdata[i]); 222 } 223 j = 0; 224 } 225 else 226 { 227 i = 0; 228 } 229 memcpy(&buffer[j], &bdata[i], len - i); 230 } 231 232 void SHA1Digest::Update(std::span<const u8> data) 233 { 234 Update(data.data(), data.size()); 235 } 236 237 /* Add padding and return the message digest. */ 238 239 void SHA1Digest::Final(u8 digest[DIGEST_SIZE]) 240 { 241 u8 finalcount[8]; 242 u8 c; 243 244 for (u32 i = 0; i < 8; i++) 245 { 246 finalcount[i] = (u8)((count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ 247 } 248 249 c = 0200; 250 Update(&c, 1); 251 while ((count[0] & 504) != 448) 252 { 253 c = 0000; 254 Update(&c, 1); 255 } 256 Update(finalcount, 8); /* Should cause a SHA1Transform() */ 257 for (u32 i = 0; i < 20; i++) 258 { 259 digest[i] = (u8)((state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); 260 } 261 }