libzypp 17.25.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#ifdef DIGEST_TESTSUITE
26#include <fstream>
27#endif
28
29#include <zypp/Digest.h>
30#include <zypp/base/PtrTypes.h>
31
32using std::endl;
33
34namespace zypp {
35
37 { return false; }
38
39 bool DigestReport::askUserToAccepUnknownDigest( const Pathname &file, const std::string &name )
40 { return false; }
41
42 bool DigestReport::askUserToAcceptWrongDigest( const Pathname &file, const std::string &requested, const std::string &found )
43 { return false; }
44
45
46 const std::string & Digest::md5()
47 { static std::string _type( "md5" ); return _type; }
48
49 const std::string & Digest::sha1()
50 { static std::string _type( "sha1" ); return _type; }
51
52 const std::string & Digest::sha224()
53 { static std::string _type( "sha224" ); return _type; }
54
55 const std::string & Digest::sha256()
56 { static std::string _type( "sha256" ); return _type; }
57
58 const std::string & Digest::sha384()
59 { static std::string _type( "sha384" ); return _type; }
60
61 const std::string & Digest::sha512()
62 { static std::string _type( "sha512" ); return _type; }
63
64 // private data
66 {
67 P(const P& p);
68 const P& operator=(const P& p);
69
70 public:
71 typedef zypp::shared_ptr<EVP_MD_CTX> EvpDataPtr;
72 P();
73 ~P();
74
76
77 const EVP_MD *md;
78 unsigned char md_value[EVP_MAX_MD_SIZE];
79 unsigned md_len;
80
81 bool finalized : 1;
83
84 std::string name;
85
86 inline bool maybeInit();
87 inline void cleanup();
88 };
89
90
91
93
95 md(NULL),
96 finalized(false)
97 {
98 }
99
101 {
102 cleanup();
103 }
104
106 {
107 if(!openssl_digests_added)
108 {
109 OPENSSL_config(NULL);
110 ENGINE_load_builtin_engines();
111 ENGINE_register_all_complete();
112 OpenSSL_add_all_digests();
113 openssl_digests_added = true;
114 }
115
116 if(!mdctx)
117 {
118 md = EVP_get_digestbyname(name.c_str());
119 if(!md)
120 return false;
121
122#if OPENSSL_VERSION_NUMBER < 0x10100000L
123 EvpDataPtr tmp_mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
124#else
125 EvpDataPtr tmp_mdctx(EVP_MD_CTX_new(), EVP_MD_CTX_free);
126#endif
127 if (!tmp_mdctx)
128 return false;
129
130 if (!EVP_DigestInit_ex(tmp_mdctx.get(), md, NULL)) {
131 return false;
132 }
133
134 md_len = 0;
135 ::memset(md_value, 0, sizeof(md_value));
136
137 mdctx.swap(tmp_mdctx);
138 }
139 return true;
140 }
141
143 {
144 mdctx.reset();
145 finalized = false;
146 }
147
149 {
150 }
151
153 {
154 delete _dp;
155 }
156
157 bool Digest::create(const std::string& name)
158 {
159 if(name.empty()) return false;
160
161 if(_dp->mdctx)
162 _dp->cleanup();
163
164 _dp->name = name;
165
166 return _dp->maybeInit();
167 }
168
169 const std::string& Digest::name()
170 {
171 return _dp->name;
172 }
173
175 {
176 if (!_dp->mdctx)
177 return false;
178 if(!_dp->finalized)
179 {
180 (void)EVP_DigestFinal_ex(_dp->mdctx.get(), _dp->md_value, &_dp->md_len);
181 _dp->finalized = true;
182 }
183 if(!EVP_DigestInit_ex(_dp->mdctx.get(), _dp->md, NULL))
184 return false;
185 _dp->finalized = false;
186 return true;
187 }
188
189 std::string Digest::digest()
190 {
192 }
193
194 std::string Digest::digestVectorToString(const std::vector<unsigned char> &vec)
195 {
196 if ( vec.empty() )
197 return std::string();
198
199 std::vector<char> resData ( vec.size()*2 + 1, '\0' );
200 char *mdtxt = &resData[0];
201 for(unsigned i = 0; i < vec.size(); ++i)
202 {
203 ::snprintf( mdtxt+(i*2), 3, "%02hhx", vec[i]);
204 }
205 return std::string( resData.data() );
206 }
207
208 std::vector<unsigned char> Digest::digestVector()
209 {
210 std::vector<unsigned char> r;
211 if(!_dp->maybeInit())
212 return r;
213
214 if(!_dp->finalized)
215 {
216 if(!EVP_DigestFinal_ex(_dp->mdctx.get(), _dp->md_value, &_dp->md_len))
217 return r;
218 _dp->finalized = true;
219 }
220 r.reserve(_dp->md_len);
221 for(unsigned i = 0; i < _dp->md_len; ++i)
222 r.push_back(_dp->md_value[i]);
223 return r;
224 }
225
226 bool Digest::update(const char* bytes, size_t len)
227 {
228 if(!bytes)
229 {
230 return false;
231 }
232
233 if(!_dp->maybeInit())
234 return false;
235
236 if(_dp->finalized)
237 {
238 _dp->cleanup();
239 if(!_dp->maybeInit())
240 return false;
241
242 }
243 if(!EVP_DigestUpdate(_dp->mdctx.get(), reinterpret_cast<const unsigned char*>(bytes), len))
244 return false;
245
246 return true;
247 }
248
249 bool Digest::update(std::istream &is, size_t bufsize)
250 {
251 if( !is )
252 return false;
253
254 char buf[bufsize];
255
256 while(is.good())
257 {
258 size_t readed;
259 is.read(buf, bufsize);
260 readed = is.gcount();
261 if(readed && !update(buf, readed))
262 return false;
263 }
264
265 return true;
266 }
267
268 std::string Digest::digest(const std::string& name, std::istream& is, size_t bufsize)
269 {
270 if(name.empty() || !is)
271 return std::string();
272
274 if(!digest.create(name))
275 return std::string();
276
277 if ( !digest.update( is, bufsize ))
278 return std::string();
279
280 return digest.digest();
281 }
282
283 std::string Digest::digest( const std::string & name, const std::string & input, size_t bufsize )
284 {
285 std::istringstream is( input );
286 return digest( name, is, bufsize );
287 }
288
289#ifdef DIGEST_TESTSUITE
290 int main(int argc, char *argv[])
291 {
292 bool openssl = false;
293 unsigned argpos = 1;
294
295 if(argc > 1 && std::string(argv[argpos]) == "--openssl")
296 {
297 openssl = true;
298 ++argpos;
299 }
300
301 if(argc - argpos < 2)
302 {
303 cerr << "Usage: " << argv[0] << " <DIGESTNAME> <FILE>" << endl;
304 return 1;
305 }
306
307 const char* digestname = argv[argpos++];
308 const char* fn = argv[argpos++];
309
310 std::ifstream file(fn);
311
312 std::string digest = Digest::digest(digestname, file);
313
314 if(openssl)
315 cout << digestname << "(" << fn << ")= " << digest << endl;
316 else
317 cout << digest << " " << fn << endl;
318
319 return 0;
320 }
321#endif
322
323} // namespace zypp
EvpDataPtr mdctx
Definition: Digest.cc:75
const EVP_MD * md
Definition: Digest.cc:77
const P & operator=(const P &p)
unsigned char md_value[EVP_MAX_MD_SIZE]
Definition: Digest.cc:78
static bool openssl_digests_added
Definition: Digest.cc:82
unsigned md_len
Definition: Digest.cc:79
zypp::shared_ptr< EVP_MD_CTX > EvpDataPtr
Definition: Digest.cc:71
void cleanup()
Definition: Digest.cc:142
P(const P &p)
bool maybeInit()
Definition: Digest.cc:105
std::string name
Definition: Digest.cc:84
bool finalized
Definition: Digest.cc:81
Compute Message Digests (MD5, SHA1 etc)
Definition: Digest.h:46
static const std::string & md5()
md5
Definition: Digest.cc:46
static const std::string & sha384()
sha384
Definition: Digest.cc:58
std::string digest()
get hex string representation of the digest
Definition: Digest.cc:189
static const std::string & sha512()
sha512
Definition: Digest.cc:61
static const std::string & sha1()
sha1
Definition: Digest.cc:49
bool update(const char *bytes, size_t len)
feed data into digest computation algorithm
Definition: Digest.cc:226
std::vector< unsigned char > digestVector()
get vector of unsigned char representation of the digest
Definition: Digest.cc:208
static const std::string & sha256()
sha256
Definition: Digest.cc:55
static const std::string & sha224()
sha224
Definition: Digest.cc:52
bool reset()
reset internal digest state
Definition: Digest.cc:174
const std::string & name()
get the name of the current digest algorithm
Definition: Digest.cc:169
static std::string digestVectorToString(const std::vector< unsigned char > &vec)
get hex string representation of the digest vector given as parameter
Definition: Digest.cc:194
P * _dp
Definition: Digest.h:49
bool create(const std::string &name)
initialize creation of a new message digest
Definition: Digest.cc:157
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
virtual bool askUserToAcceptNoDigest(const zypp::Pathname &file)
Definition: Digest.cc:36
virtual bool askUserToAcceptWrongDigest(const Pathname &file, const std::string &requested, const std::string &found)
Definition: Digest.cc:42
virtual bool askUserToAccepUnknownDigest(const Pathname &file, const std::string &name)
Definition: Digest.cc:39