Thrill  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 <[email protected]>
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>
17 #include <tlx/string/hexdump.hpp>
18 
19 #include <algorithm>
20 
21 namespace tlx {
22 
23 /*
24  * LibTomCrypt, modular cryptographic library -- Tom St Denis
25  *
26  * LibTomCrypt is a library that provides various cryptographic algorithms in a
27  * highly modular and flexible manner.
28  *
29  * The library is free for all purposes without any express guarantee it works.
30  */
31 
32 typedef uint32_t u32;
33 typedef uint64_t u64;
34 
35 namespace {
36 
37 static inline u32 min(u32 x, u32 y) {
38  return x < y ? x : y;
39 }
40 
41 static inline void store64h(u64 x, unsigned char* y) {
42  for (int i = 0; i != 8; ++i)
43  y[i] = (x >> ((7 - i) * 8)) & 255;
44 }
45 static inline u32 load32h(const uint8_t* y) {
46  return (u32(y[0]) << 24) | (u32(y[1]) << 16) |
47  (u32(y[2]) << 8) | (u32(y[3]) << 0);
48 }
49 static inline void store32h(u32 x, uint8_t* y) {
50  for (int i = 0; i != 4; ++i)
51  y[i] = (x >> ((3 - i) * 8)) & 255;
52 }
53 
54 static inline u32 F0(const u32& x, const u32& y, const u32& z) {
55  return (z ^ (x & (y ^ z)));
56 }
57 static inline u32 F1(const u32& x, const u32& y, const u32& z) {
58  return (x ^ y ^ z);
59 }
60 static inline u32 F2(const u32& x, const u32& y, const u32& z) {
61  return ((x & y) | (z & (x | y)));
62 }
63 static inline u32 F3(const u32& x, const u32& y, const u32& z) {
64  return (x ^ y ^ z);
65 }
66 
67 static void sha1_compress(uint32_t state[4], const uint8_t* buf) {
68  u32 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
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 
129 SHA1::SHA1(const void* data, uint32_t size)
130  : SHA1() {
131  process(data, size);
132 }
133 
135  : SHA1() {
136  process(str);
137 }
138 
139 void SHA1::process(const void* data, u32 size) {
140  const u32 block_size = sizeof(SHA1::buf_);
141  auto in = static_cast<const uint8_t*>(data);
142 
143  while (size > 0)
144  {
145  if (curlen_ == 0 && size >= block_size)
146  {
147  sha1_compress(state_, in);
148  length_ += block_size * 8;
149  in += block_size;
150  size -= block_size;
151  }
152  else
153  {
154  u32 n = min(size, (block_size - curlen_));
155  std::copy(in, in + n, buf_ + curlen_);
156  curlen_ += n;
157  in += n;
158  size -= n;
159 
160  if (curlen_ == block_size)
161  {
162  sha1_compress(state_, buf_);
163  length_ += 8 * block_size;
164  curlen_ = 0;
165  }
166  }
167  }
168 }
169 
170 void SHA1::process(const std::string& str) {
171  return process(str.data(), str.size());
172 }
173 
174 void 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;
187  sha1_compress(state_, buf_);
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
196  store64h(length_, buf_ + 56);
197  sha1_compress(state_, buf_);
198 
199  // Copy output
200  for (size_t i = 0; i < 5; i++)
201  store32h(state_[i], static_cast<uint8_t*>(digest) + (4 * i));
202 }
203 
205  std::string out(kDigestLength, '0');
206  finalize(const_cast<char*>(out.data()));
207  return out;
208 }
209 
211  uint8_t digest[kDigestLength];
212  finalize(digest);
213  return hexdump_lc(digest, kDigestLength);
214 }
215 
217  uint8_t digest[kDigestLength];
218  finalize(digest);
219  return hexdump(digest, kDigestLength);
220 }
221 
222 std::string SHA1_hex(const void* data, uint32_t size) {
223  return SHA1(data, size).digest_hex();
224 }
225 
227  return SHA1(str).digest_hex();
228 }
229 
230 std::string SHA1_hex_uc(const void* data, uint32_t size) {
231  return SHA1(data, size).digest_hex_uc();
232 }
233 
235  return SHA1(str).digest_hex_uc();
236 }
237 
238 } // namespace tlx
239 
240 /******************************************************************************/
void process(const void *data, uint32_t size)
process more data
Definition: sha1.cpp:139
SHA-1 processor without external dependencies.
Definition: sha1.hpp:28
uint8_t buf_[64]
Definition: sha1.hpp:60
std::string digest()
finalize computation and return 20 byte (160 bit) digest
Definition: sha1.cpp:204
uint64_t u64
Definition: md5.cpp:33
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
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
SHA1()
construct empty object.
Definition: sha1.cpp:119
list x
Definition: gen_data.py:39
std::basic_string< char, std::char_traits< char >, Allocator< char > > string
string with Manager tracking
Definition: allocator.hpp:220
static uint32_t rol32(const uint32_t &x, int i)
rol32 - generic
Definition: rol.hpp:55
uint32_t curlen_
Definition: sha1.hpp:59
static uint_pair min()
return an uint_pair instance containing the smallest value possible
Definition: uint_types.hpp:217
std::string digest_hex_uc()
finalize computation and return 20 byte (160 bit) digest upper-case hex
Definition: sha1.cpp:216
uint32_t u32
Definition: md5.cpp:32
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
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 constexpr size_t kDigestLength
digest length in bytes
Definition: sha1.hpp:44
std::string digest_hex()
finalize computation and return 20 byte (160 bit) digest hex encoded
Definition: sha1.cpp:210
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
uint64_t length_
Definition: sha1.hpp:57