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