libzypp 17.31.6
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;
66
67 bool finalized : 1;
68 static bool openssl_digests_added;
69
70 std::string name;
71
72 inline bool maybeInit();
73 inline void cleanup();
74 };
75
76
77
79
80 Digest::P::P() :
81 md(NULL),
82 finalized(false)
83 {
84 }
85
86 Digest::P::~P()
87 {
88 cleanup();
89 }
90
91 bool Digest::P::maybeInit()
92 {
93 if(!openssl_digests_added)
94 {
95 OPENSSL_config(NULL);
96 ENGINE_load_builtin_engines();
97 ENGINE_register_all_complete();
98 OpenSSL_add_all_digests();
99 openssl_digests_added = true;
100 }
101
102 if(!mdctx)
103 {
104 md = EVP_get_digestbyname(name.c_str());
105 if(!md)
106 return false;
107
108#if OPENSSL_VERSION_NUMBER < 0x10100000L
109 EvpDataPtr tmp_mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
110#else
111 EvpDataPtr tmp_mdctx(EVP_MD_CTX_new(), EVP_MD_CTX_free);
112#endif
113 if (!tmp_mdctx)
114 return false;
115
116 if (!EVP_DigestInit_ex(tmp_mdctx.get(), md, NULL)) {
117 return false;
118 }
119
120 md_len = 0;
121 ::memset(md_value, 0, sizeof(md_value));
122
123 mdctx.swap(tmp_mdctx);
124 }
125 return true;
126 }
127
128 void Digest::P::cleanup()
129 {
130 mdctx.reset();
131 finalized = false;
132 }
133
134 Digest::Digest() : _dp(new P())
135 {
136 }
137
138 Digest::~Digest()
139 {
140 delete _dp;
141 }
142
143 bool Digest::create(const std::string& name)
144 {
145 if(name.empty()) return false;
146
147 if(_dp->mdctx)
148 _dp->cleanup();
149
150 _dp->name = name;
151
152 return _dp->maybeInit();
153 }
154
155 const std::string& Digest::name()
156 {
157 return _dp->name;
158 }
159
160 bool Digest::reset()
161 {
162 if (!_dp->mdctx)
163 return false;
164 if(!_dp->finalized)
165 {
166 (void)EVP_DigestFinal_ex(_dp->mdctx.get(), _dp->md_value, &_dp->md_len);
167 _dp->finalized = true;
168 }
169 if(!EVP_DigestInit_ex(_dp->mdctx.get(), _dp->md, NULL))
170 return false;
171 _dp->finalized = false;
172 return true;
173 }
174
175 std::string Digest::digest()
176 {
177 return digestVectorToString( digestVector() );
178 }
179
180 std::string Digest::digestVectorToString(const UByteArray &vec)
181 {
182 if ( vec.empty() )
183 return std::string();
184
185 std::vector<char> resData ( vec.size()*2 + 1, '\0' );
186 char *mdtxt = &resData[0];
187 for(unsigned i = 0; i < vec.size(); ++i)
188 {
189 ::snprintf( mdtxt+(i*2), 3, "%02hhx", vec[i]);
190 }
191 return std::string( resData.data() );
192 }
193
194#ifdef __cpp_lib_string_view
195 namespace {
196 template <typename BArr>
197 BArr hexStrToBArr ( std::string_view &&str ) {
198 BArr bytes;
199 for ( std::string::size_type i = 0; i < str.length(); i+=2 )
200 {
201 #define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \
202 : ((c)>='a' && (c)<='f') ? ((c)-('a'-10)) \
203 : ((c)>='A' && (c)<='F') ? ((c)-('A'-10)) \
204 : -1)
205 int v = c2h(str[i]);
206 if (v < 0)
207 return {};
208 bytes.push_back(v);
209 v = c2h(str[i+1]);
210 if (v < 0)
211 return {};
212 bytes.back() = (bytes.back() << 4) | v;
213 #undef c2h
214 }
215 return bytes;
216 }
217 } // namespace
218
219 ByteArray Digest::hexStringToByteArray(std::string_view str)
220 {
221 return hexStrToBArr<ByteArray>( std::move(str) );
222 }
223
224 UByteArray Digest::hexStringToUByteArray( std::string_view str )
225 {
226 return hexStrToBArr<UByteArray>( std::move(str) );
227 }
228#endif
229
230 UByteArray Digest::digestVector()
231 {
232 UByteArray r;
233 if(!_dp->maybeInit())
234 return r;
235
236 if(!_dp->finalized)
237 {
238 if(!EVP_DigestFinal_ex(_dp->mdctx.get(), _dp->md_value, &_dp->md_len))
239 return r;
240 _dp->finalized = true;
241 }
242 r.reserve(_dp->md_len);
243 for(unsigned i = 0; i < _dp->md_len; ++i)
244 r.push_back(_dp->md_value[i]);
245 return r;
246 }
247
248 bool Digest::update(const char* bytes, size_t len)
249 {
250 if(!bytes)
251 {
252 return false;
253 }
254
255 if(!_dp->maybeInit())
256 return false;
257
258 if(_dp->finalized)
259 {
260 _dp->cleanup();
261 if(!_dp->maybeInit())
262 return false;
263
264 }
265 if(!EVP_DigestUpdate(_dp->mdctx.get(), reinterpret_cast<const unsigned char*>(bytes), len))
266 return false;
267
268 return true;
269 }
270
271 bool Digest::update(std::istream &is, size_t bufsize)
272 {
273 if( !is )
274 return false;
275
276 char buf[bufsize];
277
278 while(is.good())
279 {
280 size_t readed;
281 is.read(buf, bufsize);
282 readed = is.gcount();
283 if(readed && !update(buf, readed))
284 return false;
285 }
286
287 return true;
288 }
289
290 std::string Digest::digest(const std::string& name, std::istream& is, size_t bufsize)
291 {
292 if(name.empty() || !is)
293 return std::string();
294
295 Digest digest;
296 if(!digest.create(name))
297 return std::string();
298
299 if ( !digest.update( is, bufsize ))
300 return std::string();
301
302 return digest.digest();
303 }
304
305 std::string Digest::digest( const std::string & name, const std::string & input, size_t bufsize )
306 {
307 std::istringstream is( input );
308 return digest( name, is, bufsize );
309 }
310
311} // namespace zypp
#define c2h(c)
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:68
unsigned md_len
Definition: Digest.cc:65
zypp::shared_ptr< EVP_MD_CTX > EvpDataPtr
Definition: Digest.cc:57
void cleanup()
Definition: Digest.cc:128
bool maybeInit()
Definition: Digest.cc:91
std::string name
Definition: Digest.cc:70
bool finalized
Definition: Digest.cc:67
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