libzypp  17.25.1
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 using std::endl;
33 
34 namespace 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
65  class Digest::P
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;
82  static bool openssl_digests_added;
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 
148  Digest::Digest() : _dp(new P())
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 
273  Digest digest;
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
zypp::Digest::P::P
P()
Definition: Digest.cc:94
zypp::Digest::P::operator=
const P & operator=(const P &p)
zypp::Digest::sha1
static const std::string & sha1()
sha1
Definition: Digest.cc:49
zypp::Digest::digestVector
std::vector< unsigned char > digestVector()
get vector of unsigned char representation of the digest
Definition: Digest.cc:208
zypp::DigestReport::askUserToAcceptWrongDigest
virtual bool askUserToAcceptWrongDigest(const Pathname &file, const std::string &requested, const std::string &found)
Definition: Digest.cc:42
zypp::Digest::P::EvpDataPtr
zypp::shared_ptr< EVP_MD_CTX > EvpDataPtr
Definition: Digest.cc:71
zypp::Digest::name
const std::string & name()
get the name of the current digest algorithm
Definition: Digest.cc:169
zypp::Digest::reset
bool reset()
reset internal digest state
Definition: Digest.cc:174
zypp::Digest::P::finalized
bool finalized
Definition: Digest.cc:81
zypp::Digest::P::md
const EVP_MD * md
Definition: Digest.cc:77
PtrTypes.h
zypp::Digest::P::maybeInit
bool maybeInit()
Definition: Digest.cc:105
zypp::Digest::sha224
static const std::string & sha224()
sha224
Definition: Digest.cc:52
zypp::Digest
Compute Message Digests (MD5, SHA1 etc)
Definition: Digest.h:45
zypp::Digest::P::cleanup
void cleanup()
Definition: Digest.cc:142
zypp::Digest::sha384
static const std::string & sha384()
sha384
Definition: Digest.cc:58
zypp::Digest::md5
static const std::string & md5()
md5
Definition: Digest.cc:46
zypp::DigestReport::askUserToAccepUnknownDigest
virtual bool askUserToAccepUnknownDigest(const Pathname &file, const std::string &name)
Definition: Digest.cc:39
zypp::Digest::P::openssl_digests_added
static bool openssl_digests_added
Definition: Digest.cc:82
zypp::Digest::digestVectorToString
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
zypp::Digest::P::mdctx
EvpDataPtr mdctx
Definition: Digest.cc:75
zypp::Digest::sha512
static const std::string & sha512()
sha512
Definition: Digest.cc:61
zypp::Digest::P::md_value
unsigned char md_value[EVP_MAX_MD_SIZE]
Definition: Digest.cc:78
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
zypp::Digest::digest
std::string digest()
get hex string representation of the digest
Definition: Digest.cc:189
zypp::Digest::P::md_len
unsigned md_len
Definition: Digest.cc:79
zypp::Digest::P::~P
~P()
Definition: Digest.cc:100
zypp::Digest::~Digest
~Digest()
Definition: Digest.cc:152
zypp::Digest::P::name
std::string name
Definition: Digest.cc:84
zypp::Digest::create
bool create(const std::string &name)
initialize creation of a new message digest
Definition: Digest.cc:157
zypp::Digest::Digest
Digest()
Definition: Digest.cc:148
Digest.h
zypp::Digest::update
bool update(const char *bytes, size_t len)
feed data into digest computation algorithm
Definition: Digest.cc:226
zypp::Digest::sha256
static const std::string & sha256()
sha256
Definition: Digest.cc:55
zypp::filesystem::Pathname
Pathname.
Definition: Pathname.h:44
zypp::DigestReport::askUserToAcceptNoDigest
virtual bool askUserToAcceptNoDigest(const zypp::Pathname &file)
Definition: Digest.cc:36
zypp::Digest::P
Definition: Digest.cc:65
zypp::Digest::_dp
P * _dp
Definition: Digest.h:48