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