libzypp  15.28.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 #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  {
105  if(!openssl_digests_added)
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  EVP_MD_CTX_init(&mdctx);
121 
122  if(!EVP_DigestInit_ex(&mdctx, md, NULL))
123  return false;
124 
125  md_len = 0;
126  ::memset(md_value, 0, sizeof(md_value));
127  initialized = true;
128  }
129  return true;
130  }
131 
133  {
134  if(initialized)
135  {
136  EVP_MD_CTX_cleanup(&mdctx);
137  initialized = false;
138  finalized = false;
139  }
140  }
141 
142  Digest::Digest() : _dp(new P())
143  {
144  }
145 
147  {
148  delete _dp;
149  }
150 
151  bool Digest::create(const std::string& name)
152  {
153  if(name.empty()) return false;
154 
155  if(_dp->initialized)
156  _dp->cleanup();
157 
158  _dp->name = name;
159 
160  return _dp->maybeInit();
161  }
162 
163  const std::string& Digest::name()
164  {
165  return _dp->name;
166  }
167 
169  {
170  if (!_dp->initialized)
171  return false;
172  if(!_dp->finalized)
173  {
174  (void)EVP_DigestFinal_ex(&_dp->mdctx, _dp->md_value, &_dp->md_len);
175  _dp->finalized = true;
176  }
177  if(!EVP_DigestInit_ex(&_dp->mdctx, _dp->md, NULL))
178  return false;
179  _dp->finalized = false;
180  return true;
181  }
182 
183  std::string Digest::digest()
184  {
185  if(!_dp->maybeInit())
186  return std::string();
187 
188  if(!_dp->finalized)
189  {
190  if(!EVP_DigestFinal_ex(&_dp->mdctx, _dp->md_value, &_dp->md_len))
191  return std::string();
192 
193  _dp->finalized = true;
194  }
195 
196  char mdtxt[_dp->md_len*2 + 1];
197  mdtxt[_dp->md_len*2] = '\0';
198 
199  for(unsigned i = 0; i < _dp->md_len; ++i)
200  {
201  ::snprintf(mdtxt + i*2, 3, "%02hhx", _dp->md_value[i]);
202  }
203 
204  return std::string(mdtxt);
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, _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, reinterpret_cast<const unsigned char*>(bytes), len))
243  return false;
244 
245  return true;
246  }
247 
248  std::string Digest::digest(const std::string& name, std::istream& is, size_t bufsize)
249  {
250  if(name.empty() || !is)
251  return string();
252 
253  char buf[bufsize];
254 
255  Digest digest;
256  if(!digest.create(name))
257  return string();
258 
259 
260  while(is.good())
261  {
262  int readed;
263  is.read(buf, bufsize);
264  readed = is.gcount();
265  if(readed && !digest.update(buf, readed))
266  return string();
267  }
268 
269  return digest.digest();
270  }
271 
272  std::string Digest::digest( const std::string & name, const std::string & input, size_t bufsize )
273  {
274  istringstream is( input );
275  return digest( name, is, bufsize );
276  }
277 
278 #ifdef DIGEST_TESTSUITE
279  int main(int argc, char *argv[])
280  {
281  bool openssl = false;
282  unsigned argpos = 1;
283 
284  if(argc > 1 && string(argv[argpos]) == "--openssl")
285  {
286  openssl = true;
287  ++argpos;
288  }
289 
290  if(argc - argpos < 2)
291  {
292  cerr << "Usage: " << argv[0] << " <DIGESTNAME> <FILE>" << endl;
293  return 1;
294  }
295 
296  const char* digestname = argv[argpos++];
297  const char* fn = argv[argpos++];
298 
299  ifstream file(fn);
300 
301  string digest = Digest::digest(digestname, file);
302 
303  if(openssl)
304  cout << digestname << "(" << fn << ")= " << digest << endl;
305  else
306  cout << digest << " " << fn << endl;
307 
308  return 0;
309  }
310 #endif
311 
312 } // 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:183
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:163
bool maybeInit()
Definition: Digest.cc:103
bool reset()
reset internal digest state
Definition: Digest.cc:168
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:207
unsigned char md_value[EVP_MAX_MD_SIZE]
Definition: Digest.cc:73
EVP_MD_CTX mdctx
Definition: Digest.cc:70
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:151
const EVP_MD * md
Definition: Digest.cc:72
static const std::string & md5()
md5
Definition: Digest.cc:43
P * _dp
Definition: Digest.h:48
static const std::string & sha224()
sha224
Definition: Digest.cc:49
void cleanup()
Definition: Digest.cc:132
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:225
const P & operator=(const P &p)
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