libzypp  17.22.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  {
191  }
192 
193  string Digest::digestVectorToString(const std::vector<unsigned char> &vec)
194  {
195  if ( vec.empty() )
196  return std::string();
197 
198  std::vector<char> resData ( vec.size()*2 + 1, '\0' );
199  char *mdtxt = &resData[0];
200  for(unsigned i = 0; i < vec.size(); ++i)
201  {
202  ::snprintf( mdtxt+(i*2), 3, "%02hhx", vec[i]);
203  }
204  return std::string( resData.data() );
205  }
206 
207  std::vector<unsigned char> Digest::digestVector()
208  {
209  std::vector<unsigned char> r;
210  if(!_dp->maybeInit())
211  return r;
212 
213  if(!_dp->finalized)
214  {
215  if(!EVP_DigestFinal_ex(_dp->mdctx.get(), _dp->md_value, &_dp->md_len))
216  return r;
217  _dp->finalized = true;
218  }
219  r.reserve(_dp->md_len);
220  for(unsigned i = 0; i < _dp->md_len; ++i)
221  r.push_back(_dp->md_value[i]);
222  return r;
223  }
224 
225  bool Digest::update(const char* bytes, size_t len)
226  {
227  if(!bytes)
228  {
229  return false;
230  }
231 
232  if(!_dp->maybeInit())
233  return false;
234 
235  if(_dp->finalized)
236  {
237  _dp->cleanup();
238  if(!_dp->maybeInit())
239  return false;
240 
241  }
242  if(!EVP_DigestUpdate(_dp->mdctx.get(), reinterpret_cast<const unsigned char*>(bytes), len))
243  return false;
244 
245  return true;
246  }
247 
248  bool Digest::update(istream &is, size_t bufsize)
249  {
250  if( !is )
251  return false;
252 
253  char buf[bufsize];
254 
255  while(is.good())
256  {
257  size_t readed;
258  is.read(buf, bufsize);
259  readed = is.gcount();
260  if(readed && !update(buf, readed))
261  return false;
262  }
263 
264  return true;
265  }
266 
267  std::string Digest::digest(const std::string& name, std::istream& is, size_t bufsize)
268  {
269  if(name.empty() || !is)
270  return string();
271 
272  Digest digest;
273  if(!digest.create(name))
274  return string();
275 
276  if ( !digest.update( is, bufsize ))
277  return string();
278 
279  return digest.digest();
280  }
281 
282  std::string Digest::digest( const std::string & name, const std::string & input, size_t bufsize )
283  {
284  istringstream is( input );
285  return digest( name, is, bufsize );
286  }
287 
288 #ifdef DIGEST_TESTSUITE
289  int main(int argc, char *argv[])
290  {
291  bool openssl = false;
292  unsigned argpos = 1;
293 
294  if(argc > 1 && string(argv[argpos]) == "--openssl")
295  {
296  openssl = true;
297  ++argpos;
298  }
299 
300  if(argc - argpos < 2)
301  {
302  cerr << "Usage: " << argv[0] << " <DIGESTNAME> <FILE>" << endl;
303  return 1;
304  }
305 
306  const char* digestname = argv[argpos++];
307  const char* fn = argv[argpos++];
308 
309  ifstream file(fn);
310 
311  string digest = Digest::digest(digestname, file);
312 
313  if(openssl)
314  cout << digestname << "(" << fn << ")= " << digest << endl;
315  else
316  cout << digest << " " << fn << endl;
317 
318  return 0;
319  }
320 #endif
321 
322 } // 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
static std::string digestVectorToString(const std::vector< unsigned char > &vec)
get hex string representation of the digest vector given as parameter
Definition: Digest.cc:193
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:347
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:207
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:225
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