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