libzypp 17.31.7
Digest.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
15#include <cstdio> // snprintf
16#include <openssl/evp.h>
17#include <openssl/conf.h>
18#include <openssl/engine.h>
19#include <string>
20#include <string.h>
21
22#include <iostream>
23#include <sstream>
24
25#include <zypp-core/Digest.h>
26#include <zypp-core/base/PtrTypes.h>
27
28using std::endl;
29
30namespace zypp {
31
32 const std::string & Digest::md5()
33 { static std::string _type( "md5" ); return _type; }
34
35 const std::string & Digest::sha1()
36 { static std::string _type( "sha1" ); return _type; }
37
38 const std::string & Digest::sha224()
39 { static std::string _type( "sha224" ); return _type; }
40
41 const std::string & Digest::sha256()
42 { static std::string _type( "sha256" ); return _type; }
43
44 const std::string & Digest::sha384()
45 { static std::string _type( "sha384" ); return _type; }
46
47 const std::string & Digest::sha512()
48 { static std::string _type( "sha512" ); return _type; }
49
50 // private data
51 class Digest::P
52 {
53 P(const P& p);
54 const P& operator=(const P& p);
55
56 public:
57 typedef zypp::shared_ptr<EVP_MD_CTX> EvpDataPtr;
58 P();
59 ~P();
60
62
63 const EVP_MD *md;
64 unsigned char md_value[EVP_MAX_MD_SIZE];
65 unsigned md_len;
67
68 bool finalized : 1;
69 static bool openssl_digests_added;
70
71 std::string name;
72
73 inline bool maybeInit();
74 inline void cleanup();
75 };
76
77
78
80
81 Digest::P::P() :
82 md(NULL),
83 finalized(false)
84 {
85 }
86
87 Digest::P::~P()
88 {
89 cleanup();
90 }
91
92 bool Digest::P::maybeInit()
93 {
94 if(!openssl_digests_added)
95 {
96 OPENSSL_config(NULL);
97 ENGINE_load_builtin_engines();
98 ENGINE_register_all_complete();
99 OpenSSL_add_all_digests();
100 openssl_digests_added = true;
101 }
102
103 if(!mdctx)
104 {
105 md = EVP_get_digestbyname(name.c_str());
106 if(!md)
107 return false;
108
109#if OPENSSL_VERSION_NUMBER < 0x10100000L
110 EvpDataPtr tmp_mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
111#else
112 EvpDataPtr tmp_mdctx(EVP_MD_CTX_new(), EVP_MD_CTX_free);
113#endif
114 if (!tmp_mdctx)
115 return false;
116
117 if (!EVP_DigestInit_ex(tmp_mdctx.get(), md, NULL)) {
118 return false;
119 }
120
121 md_len = 0;
122 ::memset(md_value, 0, sizeof(md_value));
123
124 bytesHashed = 0;
125
126 mdctx.swap(tmp_mdctx);
127 }
128 return true;
129 }
130
131 void Digest::P::cleanup()
132 {
133 mdctx.reset();
134 finalized = false;
135 }
136
137 Digest::Digest() : _dp(new P())
138 {
139 }
140
141 Digest::~Digest()
142 {
143 delete _dp;
144 }
145
146 bool Digest::create(const std::string& name)
147 {
148 if(name.empty()) return false;
149
150 if(_dp->mdctx)
151 _dp->cleanup();
152
153 _dp->name = name;
154
155 return _dp->maybeInit();
156 }
157
158 const std::string& Digest::name()
159 {
160 return _dp->name;
161 }
162
163 bool Digest::reset()
164 {
165 if (!_dp->mdctx)
166 return false;
167 if(!_dp->finalized)
168 {
169 (void)EVP_DigestFinal_ex(_dp->mdctx.get(), _dp->md_value, &_dp->md_len);
170 _dp->finalized = true;
171 }
172 if(!EVP_DigestInit_ex(_dp->mdctx.get(), _dp->md, NULL))
173 return false;
174 _dp->finalized = false;
175 _dp->bytesHashed = 0;
176 return true;
177 }
178
179 std::string Digest::digest()
180 {
181 return digestVectorToString( digestVector() );
182 }
183
184 std::string Digest::digestVectorToString(const UByteArray &vec)
185 {
186 if ( vec.empty() )
187 return std::string();
188
189 std::vector<char> resData ( vec.size()*2 + 1, '\0' );
190 char *mdtxt = &resData[0];
191 for(unsigned i = 0; i < vec.size(); ++i)
192 {
193 ::snprintf( mdtxt+(i*2), 3, "%02hhx", vec[i]);
194 }
195 return std::string( resData.data() );
196 }
197
198#ifdef __cpp_lib_string_view
199 namespace {
200 template <typename BArr>
201 BArr hexStrToBArr ( std::string_view &&str ) {
202 BArr bytes;
203 for ( std::string::size_type i = 0; i < str.length(); i+=2 )
204 {
205 #define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \
206 : ((c)>='a' && (c)<='f') ? ((c)-('a'-10)) \
207 : ((c)>='A' && (c)<='F') ? ((c)-('A'-10)) \
208 : -1)
209 int v = c2h(str[i]);
210 if (v < 0)
211 return {};
212 bytes.push_back(v);
213 v = c2h(str[i+1]);
214 if (v < 0)
215 return {};
216 bytes.back() = (bytes.back() << 4) | v;
217 #undef c2h
218 }
219 return bytes;
220 }
221 } // namespace
222
223 ByteArray Digest::hexStringToByteArray(std::string_view str)
224 {
225 return hexStrToBArr<ByteArray>( std::move(str) );
226 }
227
228 UByteArray Digest::hexStringToUByteArray( std::string_view str )
229 {
230 return hexStrToBArr<UByteArray>( std::move(str) );
231 }
232#endif
233
234 UByteArray Digest::digestVector()
235 {
236 UByteArray r;
237 if(!_dp->maybeInit())
238 return r;
239
240 if(!_dp->finalized)
241 {
242 if(!EVP_DigestFinal_ex(_dp->mdctx.get(), _dp->md_value, &_dp->md_len))
243 return r;
244 _dp->finalized = true;
245 }
246 r.reserve(_dp->md_len);
247 for(unsigned i = 0; i < _dp->md_len; ++i)
248 r.push_back(_dp->md_value[i]);
249 return r;
250 }
251
252 bool Digest::update(const char* bytes, size_t len)
253 {
254 if(!bytes)
255 {
256 return false;
257 }
258
259 if(!_dp->maybeInit())
260 return false;
261
262 if(_dp->finalized)
263 {
264 _dp->cleanup();
265 if(!_dp->maybeInit())
266 return false;
267
268 }
269 if(!EVP_DigestUpdate(_dp->mdctx.get(), reinterpret_cast<const unsigned char*>(bytes), len))
270 return false;
271
272 _dp->bytesHashed += len;
273 return true;
274 }
275
276 bool Digest::update(std::istream &is, size_t bufsize)
277 {
278 if( !is )
279 return false;
280
281 char buf[bufsize];
282
283 while(is.good())
284 {
285 size_t readed;
286 is.read(buf, bufsize);
287 readed = is.gcount();
288 if(readed && !update(buf, readed))
289 return false;
290 }
291
292 return true;
293 }
294
295 ByteCount Digest::bytesHashed() const
296 {
297 return _dp->bytesHashed;
298 }
299
300 std::string Digest::digest(const std::string& name, std::istream& is, size_t bufsize)
301 {
302 if(name.empty() || !is)
303 return std::string();
304
305 Digest digest;
306 if(!digest.create(name))
307 return std::string();
308
309 if ( !digest.update( is, bufsize ))
310 return std::string();
311
312 return digest.digest();
313 }
314
315 std::string Digest::digest( const std::string & name, const std::string & input, size_t bufsize )
316 {
317 std::istringstream is( input );
318 return digest( name, is, bufsize );
319 }
320
321} // namespace zypp
Store and operate with byte count.
Definition: ByteCount.h:31
EvpDataPtr mdctx
Definition: Digest.cc:61
const EVP_MD * md
Definition: Digest.cc:63
const P & operator=(const P &p)
unsigned char md_value[EVP_MAX_MD_SIZE]
Definition: Digest.cc:64
static bool openssl_digests_added
Definition: Digest.cc:69
zypp::ByteCount bytesHashed
Definition: Digest.cc:66
unsigned md_len
Definition: Digest.cc:65
zypp::shared_ptr< EVP_MD_CTX > EvpDataPtr
Definition: Digest.cc:57
void cleanup()
Definition: Digest.cc:131
bool maybeInit()
Definition: Digest.cc:92
std::string name
Definition: Digest.cc:71
bool finalized
Definition: Digest.cc:68
static const std::string & md5()
md5
Definition: Digest.cc:32
static const std::string & sha384()
sha384
Definition: Digest.cc:44
static const std::string & sha512()
sha512
Definition: Digest.cc:47
static const std::string & sha1()
sha1
Definition: Digest.cc:35
static const std::string & sha256()
sha256
Definition: Digest.cc:41
static const std::string & sha224()
sha224
Definition: Digest.cc:38
String related utilities and Regular expression matching.
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
#define c2h(c)