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