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