forked from newton-blockchain/ton
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdigest.hpp
151 lines (128 loc) · 3.71 KB
/
digest.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
#include <assert.h>
#include <openssl/evp.h>
#include <openssl/opensslv.h>
#include "td/utils/Slice.h"
namespace digest {
struct OpensslEVP_SHA1 {
enum { digest_bytes = 20 };
static const EVP_MD *get_evp() {
return EVP_sha1();
}
};
struct OpensslEVP_SHA256 {
enum { digest_bytes = 32 };
static const EVP_MD *get_evp() {
return EVP_sha256();
}
};
struct OpensslEVP_SHA512 {
enum { digest_bytes = 64 };
static const EVP_MD *get_evp() {
return EVP_sha512();
}
};
template <typename H>
class HashCtx {
EVP_MD_CTX *ctx{nullptr};
void init();
void clear();
public:
enum { digest_bytes = H::digest_bytes };
HashCtx() {
init();
}
HashCtx(const void *data, std::size_t len) {
init();
feed(data, len);
}
~HashCtx() {
clear();
}
void reset();
void feed(const void *data, std::size_t len);
void feed(td::Slice slice) {
feed(slice.data(), slice.size());
}
std::size_t extract(unsigned char buffer[digest_bytes]);
std::size_t extract(td::MutableSlice slice);
std::string extract();
};
template <typename H>
void HashCtx<H>::init() {
ctx = EVP_MD_CTX_create();
reset();
}
template <typename H>
void HashCtx<H>::reset() {
EVP_DigestInit_ex(ctx, H::get_evp(), 0);
}
template <typename H>
void HashCtx<H>::clear() {
EVP_MD_CTX_destroy(ctx);
ctx = nullptr;
}
template <typename H>
void HashCtx<H>::feed(const void *data, std::size_t len) {
EVP_DigestUpdate(ctx, data, len);
}
template <typename H>
std::size_t HashCtx<H>::extract(unsigned char buffer[digest_bytes]) {
unsigned olen = 0;
EVP_DigestFinal_ex(ctx, buffer, &olen);
assert(olen == digest_bytes);
return olen;
}
template <typename H>
std::size_t HashCtx<H>::extract(td::MutableSlice slice) {
return extract(slice.ubegin());
}
template <typename H>
std::string HashCtx<H>::extract() {
unsigned char buffer[digest_bytes];
unsigned olen = 0;
EVP_DigestFinal_ex(ctx, buffer, &olen);
assert(olen == digest_bytes);
return std::string((char *)buffer, olen);
}
typedef HashCtx<OpensslEVP_SHA1> SHA1;
typedef HashCtx<OpensslEVP_SHA256> SHA256;
typedef HashCtx<OpensslEVP_SHA512> SHA512;
template <typename T>
std::size_t hash_str(unsigned char buffer[T::digest_bytes], const void *data, std::size_t size) {
T hasher(data, size);
return hasher.extract(buffer);
}
template <typename T>
std::size_t hash_two_str(unsigned char buffer[T::digest_bytes], const void *data1, std::size_t size1, const void *data2,
std::size_t size2) {
T hasher(data1, size1);
hasher.feed(data2, size2);
return hasher.extract(buffer);
}
template <typename T>
std::string hash_str(const void *data, std::size_t size) {
T hasher(data, size);
return hasher.extract();
}
template <typename T>
std::string hash_two_str(const void *data1, std::size_t size1, const void *data2, std::size_t size2) {
T hasher(data1, size1);
hasher.feed(data2, size2);
return hasher.extract();
}
} // namespace digest