M5Unit-CRYPTO 0.1.0 git rev:99e558e
Loading...
Searching...
No Matches
sha1.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
10#ifndef M5_UNIT_CRYPTO_UTILITY_SHA1_HPP
11#define M5_UNIT_CRYPTO_UTILITY_SHA1_HPP
12
13#include <cstdint>
14#include <cstring>
15
16namespace m5 {
17namespace utility {
18
24class SHA1 {
25public:
26 SHA1()
27 {
28 }
29
30 void init()
31 {
32 _state[0] = 0x67452301;
33 _state[1] = 0xEFCDAB89;
34 _state[2] = 0x98BADCFE;
35 _state[3] = 0x10325476;
36 _state[4] = 0xC3D2E1F0;
37 _count = 0;
38 _bufferLen = 0;
39 memset(_buffer, 0, sizeof(_buffer));
40 }
41
42 void update(const uint8_t* data, size_t len)
43 {
44 _count += static_cast<uint64_t>(len) << 3;
45 size_t fill{64 - _bufferLen};
46
47 if (len >= fill) {
48 memcpy(_buffer + _bufferLen, data, fill);
49 transform(_state, _buffer);
50 data += fill;
51 len -= fill;
52 _bufferLen = 0;
53
54 while (len >= 64) {
55 transform(_state, data);
56 data += 64;
57 len -= 64;
58 }
59 }
60
61 memcpy(_buffer + _bufferLen, data, len);
62 _bufferLen += len;
63 }
64
65 void finalize(uint8_t digest[20])
66 {
67 uint8_t padding[64]{0x80};
68 uint8_t length[8]{};
69 uint64_t count_be = __builtin_bswap64(_count);
70 memcpy(length, &count_be, 8);
71
72 size_t padLen = (_bufferLen < 56) ? (56 - _bufferLen) : (120 - _bufferLen);
73 update(padding, padLen);
74 update(length, 8);
75
76 for (int i = 0; i < 5; ++i) {
77 uint32_t be = __builtin_bswap32(_state[i]);
78 memcpy(digest + i * 4, &be, 4);
79 }
80 }
81
82 static void sha1(uint8_t digest[20], const uint8_t* data, size_t len)
83 {
84 SHA1 ctx;
85 ctx.update(data, len);
86 ctx.finalize(digest);
87 }
88
89private:
90 void transform(uint32_t state[5], const uint8_t buffer[64])
91 {
92 uint32_t a = state[0], b = state[1], c = state[2], d = state[3], e = state[4];
93 uint32_t block[80];
94
95 for (int i = 0; i < 16; ++i) {
96 block[i] = (uint32_t(buffer[i * 4 + 0]) << 24) | (uint32_t(buffer[i * 4 + 1]) << 16) |
97 (uint32_t(buffer[i * 4 + 2]) << 8) | (uint32_t(buffer[i * 4 + 3]));
98 }
99 for (int i = 16; i < 80; ++i) {
100 block[i] = rol(block[i - 3] ^ block[i - 8] ^ block[i - 14] ^ block[i - 16], 1);
101 }
102
103 for (int i = 0; i < 80; ++i) {
104 uint32_t f, k;
105 if (i < 20) {
106 f = (b & c) | ((~b) & d);
107 k = 0x5A827999;
108 } else if (i < 40) {
109 f = b ^ c ^ d;
110 k = 0x6ED9EBA1;
111 } else if (i < 60) {
112 f = (b & c) | (b & d) | (c & d);
113 k = 0x8F1BBCDC;
114 } else {
115 f = b ^ c ^ d;
116 k = 0xCA62C1D6;
117 }
118
119 uint32_t temp = rol(a, 5) + f + e + k + block[i];
120 e = d;
121 d = c;
122 c = rol(b, 30);
123 b = a;
124 a = temp;
125 }
126
127 state[0] += a;
128 state[1] += b;
129 state[2] += c;
130 state[3] += d;
131 state[4] += e;
132 }
133
134 inline uint32_t rol(uint32_t value, uint32_t bits)
135 {
136 return (value << bits) | (value >> (32 - bits));
137 }
138
139 uint32_t _state[5]{0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0};
140 uint64_t _count{};
141 uint8_t _buffer[64]{};
142 size_t _bufferLen{};
143};
144
145} // namespace utility
146} // namespace m5
147#endif
Top level namespace of M5stack.