tlx
Loading...
Searching...
No Matches
sha1.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 * tlx/digest/sha1.cpp
3 *
4 * Public domain implementation of SHA-1 processor. Based on LibTomCrypt from
5 * https://github.com/libtom/libtomcrypt.git
6 *
7 * Part of tlx - http://panthema.net/tlx
8 *
9 * Copyright (C) 2018 Timo Bingmann <tb@panthema.net>
10 *
11 * All rights reserved. Published under the Boost Software License, Version 1.0
12 ******************************************************************************/
13
14#include <tlx/digest/sha1.hpp>
15
16#include <cstdint>
17#include <tlx/math/rol.hpp>
19
20namespace tlx {
21
22/*
23 * LibTomCrypt, modular cryptographic library -- Tom St Denis
24 *
25 * LibTomCrypt is a library that provides various cryptographic algorithms in a
26 * highly modular and flexible manner.
27 *
28 * The library is free for all purposes without any express guarantee it works.
29 */
30
31namespace digest_detail {
32
33static inline std::uint32_t min(std::uint32_t x, std::uint32_t y) {
34 return x < y ? x : y;
35}
36
37static inline void store64h(std::uint64_t x, unsigned char* y) {
38 for (int i = 0; i != 8; ++i)
39 y[i] = (x >> ((7 - i) * 8)) & 255;
40}
41static inline std::uint32_t load32h(const std::uint8_t* y) {
42 return (std::uint32_t(y[0]) << 24) | (std::uint32_t(y[1]) << 16) |
43 (std::uint32_t(y[2]) << 8) | (std::uint32_t(y[3]) << 0);
44}
45static inline void store32h(std::uint32_t x, std::uint8_t* y) {
46 for (int i = 0; i != 4; ++i)
47 y[i] = (x >> ((3 - i) * 8)) & 255;
48}
49
50static inline
51std::uint32_t F0(const std::uint32_t& x, const std::uint32_t& y, const std::uint32_t& z) {
52 return (z ^ (x & (y ^ z)));
53}
54static inline
55std::uint32_t F1(const std::uint32_t& x, const std::uint32_t& y, const std::uint32_t& z) {
56 return (x ^ y ^ z);
57}
58static inline
59std::uint32_t F2(const std::uint32_t& x, const std::uint32_t& y, const std::uint32_t& z) {
60 return ((x & y) | (z & (x | y)));
61}
62static inline
63std::uint32_t F3(const std::uint32_t& x, const std::uint32_t& y, const std::uint32_t& z) {
64 return (x ^ y ^ z);
65}
66
67static void sha1_compress(std::uint32_t state[4], const std::uint8_t* buf) {
68 std::uint32_t a, b, c, d, e, W[80], i, t;
69
70 /* copy the state into 512-bits into W[0..15] */
71 for (i = 0; i < 16; i++) {
72 W[i] = load32h(buf + (4 * i));
73 }
74
75 /* copy state */
76 a = state[0];
77 b = state[1];
78 c = state[2];
79 d = state[3];
80 e = state[4];
81
82 /* expand it */
83 for (i = 16; i < 80; i++) {
84 W[i] = rol32(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
85 }
86
87 /* compress */
88 for (i = 0; i < 20; ++i) {
89 e = (rol32(a, 5) + F0(b, c, d) + e + W[i] + 0x5a827999UL);
90 b = rol32(b, 30);
91 t = e, e = d, d = c, c = b, b = a, a = t;
92 }
93 for ( ; i < 40; ++i) {
94 e = (rol32(a, 5) + F1(b, c, d) + e + W[i] + 0x6ed9eba1UL);
95 b = rol32(b, 30);
96 t = e, e = d, d = c, c = b, b = a, a = t;
97 }
98 for ( ; i < 60; ++i) {
99 e = (rol32(a, 5) + F2(b, c, d) + e + W[i] + 0x8f1bbcdcUL);
100 b = rol32(b, 30);
101 t = e, e = d, d = c, c = b, b = a, a = t;
102 }
103 for ( ; i < 80; ++i) {
104 e = (rol32(a, 5) + F3(b, c, d) + e + W[i] + 0xca62c1d6UL);
105 b = rol32(b, 30);
106 t = e, e = d, d = c, c = b, b = a, a = t;
107 }
108
109 /* store */
110 state[0] = state[0] + a;
111 state[1] = state[1] + b;
112 state[2] = state[2] + c;
113 state[3] = state[3] + d;
114 state[4] = state[4] + e;
115}
116
117} // namespace digest_detail
118
120 curlen_ = 0;
121 length_ = 0;
122 state_[0] = 0x67452301UL;
123 state_[1] = 0xefcdab89UL;
124 state_[2] = 0x98badcfeUL;
125 state_[3] = 0x10325476UL;
126 state_[4] = 0xc3d2e1f0UL;
127}
128
129SHA1::SHA1(const void* data, std::uint32_t size) : SHA1() {
130 process(data, size);
131}
132
133SHA1::SHA1(const std::string& str) : SHA1() {
134 process(str);
135}
136
137void SHA1::process(const void* data, std::uint32_t size) {
138 const std::uint32_t block_size = sizeof(SHA1::buf_);
139 auto in = static_cast<const std::uint8_t*>(data);
140
141 while (size > 0)
142 {
143 if (curlen_ == 0 && size >= block_size)
144 {
146 length_ += block_size * 8;
147 in += block_size;
148 size -= block_size;
149 }
150 else
151 {
152 std::uint32_t n = digest_detail::min(size, (block_size - curlen_));
153 std::uint8_t* b = buf_ + curlen_;
154 for (const std::uint8_t* a = in; a != in + n; ++a, ++b) {
155 *b = *a;
156 }
157 curlen_ += n;
158 in += n;
159 size -= n;
160
161 if (curlen_ == block_size)
162 {
164 length_ += 8 * block_size;
165 curlen_ = 0;
166 }
167 }
168 }
169}
170
171void SHA1::process(const std::string& str) {
172 return process(str.data(), str.size());
173}
174
175void SHA1::finalize(void* digest) {
176 // Increase the length of the message
177 length_ += curlen_ * 8;
178
179 // Append the '1' bit
180 buf_[curlen_++] = static_cast<std::uint8_t>(0x80);
181
182 // If the length_ is currently above 56 bytes we append zeros then
183 // sha1_compress(). Then we can fall back to padding zeros and length
184 // encoding like normal.
185 if (curlen_ > 56) {
186 while (curlen_ < 64)
187 buf_[curlen_++] = 0;
189 curlen_ = 0;
190 }
191
192 // Pad up to 56 bytes of zeroes
193 while (curlen_ < 56)
194 buf_[curlen_++] = 0;
195
196 // Store length
199
200 // Copy output
201 for (size_t i = 0; i < 5; i++)
202 digest_detail::store32h(state_[i], static_cast<std::uint8_t*>(digest) + (4 * i));
203}
204
205std::string SHA1::digest() {
206 std::string out(kDigestLength, '0');
207 finalize(const_cast<char*>(out.data()));
208 return out;
209}
210
211std::string SHA1::digest_hex() {
212 std::uint8_t digest[kDigestLength];
215}
216
217std::string SHA1::digest_hex_uc() {
218 std::uint8_t digest[kDigestLength];
221}
222
223std::string sha1_hex(const void* data, std::uint32_t size) {
224 return SHA1(data, size).digest_hex();
225}
226
227std::string sha1_hex(const std::string& str) {
228 return SHA1(str).digest_hex();
229}
230
231std::string sha1_hex_uc(const void* data, std::uint32_t size) {
232 return SHA1(data, size).digest_hex_uc();
233}
234
235std::string sha1_hex_uc(const std::string& str) {
236 return SHA1(str).digest_hex_uc();
237}
238
239} // namespace tlx
240
241/******************************************************************************/
SHA-1 processor without external dependencies.
Definition sha1.hpp:29
void finalize(void *digest)
finalize computation and output 20 byte (160 bit) digest
Definition sha1.cpp:175
std::string digest_hex()
finalize computation and return 20 byte (160 bit) digest hex encoded
Definition sha1.cpp:211
std::string digest()
finalize computation and return 20 byte (160 bit) digest
Definition sha1.cpp:205
std::string digest_hex_uc()
finalize computation and return 20 byte (160 bit) digest upper-case hex
Definition sha1.cpp:217
std::uint32_t curlen_
Definition sha1.hpp:59
static constexpr size_t kDigestLength
digest length in bytes
Definition sha1.hpp:44
std::uint8_t buf_[64]
Definition sha1.hpp:60
void process(const void *data, std::uint32_t size)
process more data
Definition sha1.cpp:137
std::uint64_t length_
Definition sha1.hpp:57
SHA1()
construct empty object.
Definition sha1.cpp:119
std::uint32_t state_[5]
Definition sha1.hpp:58
std::string sha1_hex_uc(const void *data, std::uint32_t size)
process data and return 20 byte (160 bit) digest upper-case hex encoded
Definition sha1.cpp:231
std::string sha1_hex(const void *data, std::uint32_t size)
process data and return 20 byte (160 bit) digest hex encoded
Definition sha1.cpp:223
static std::uint32_t rol32(const std::uint32_t &x, int i)
rol32 - generic
Definition rol.hpp:55
std::string hexdump_lc(const void *const data, size_t size)
Dump a (binary) string as a sequence of lowercase hexadecimal pairs.
Definition hexdump.cpp:96
std::string hexdump(const void *const data, size_t size)
Dump a (binary) string as a sequence of uppercase hexadecimal pairs.
Definition hexdump.cpp:22
static void sha1_compress(std::uint32_t state[4], const std::uint8_t *buf)
Definition sha1.cpp:67
static std::uint32_t min(std::uint32_t x, std::uint32_t y)
Definition md5.cpp:33
static void store64h(std::uint64_t x, unsigned char *y)
Definition sha1.cpp:37
static std::uint32_t F0(const std::uint32_t &x, const std::uint32_t &y, const std::uint32_t &z)
Definition sha1.cpp:51
static std::uint32_t F1(const std::uint32_t &x, const std::uint32_t &y, const std::uint32_t &z)
Definition sha1.cpp:55
static std::uint32_t load32h(const std::uint8_t *y)
Definition sha1.cpp:41
static std::uint32_t F2(const std::uint32_t &x, const std::uint32_t &y, const std::uint32_t &z)
Definition sha1.cpp:59
static std::uint32_t F3(const std::uint32_t &x, const std::uint32_t &y, const std::uint32_t &z)
Definition sha1.cpp:63
static void store32h(std::uint32_t x, std::uint8_t *y)
Definition sha1.cpp:45