1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/Digest.cc
11 * \todo replace by Blocxx
15 #include <cstdio> // snprintf
16 #include <openssl/evp.h>
17 #include <openssl/conf.h>
18 #include <openssl/engine.h>
25 #ifdef DIGEST_TESTSUITE
29 #include "zypp/Digest.h"
33 bool DigestReport::askUserToAcceptNoDigest( const zypp::Pathname &file )
36 bool DigestReport::askUserToAccepUnknownDigest( const Pathname &file, const std::string &name )
39 bool DigestReport::askUserToAcceptWrongDigest( const Pathname &file, const std::string &requested, const std::string &found )
43 const std::string & Digest::md5()
44 { static std::string _type( "md5" ); return _type; }
46 const std::string & Digest::sha1()
47 { static std::string _type( "sha1" ); return _type; }
49 const std::string & Digest::sha256()
50 { static std::string _type( "sha256" ); return _type; }
56 const P& operator=(const P& p);
64 unsigned char md_value[EVP_MAX_MD_SIZE];
69 static bool openssl_digests_added;
73 inline bool maybeInit();
74 inline void cleanup();
80 bool Digest::P::openssl_digests_added = false;
94 bool Digest::P::maybeInit()
96 if(!openssl_digests_added)
99 ENGINE_load_builtin_engines();
100 ENGINE_register_all_complete();
101 OpenSSL_add_all_digests();
102 openssl_digests_added = true;
107 md = EVP_get_digestbyname(name.c_str());
111 EVP_MD_CTX_init(&mdctx);
113 if(!EVP_DigestInit_ex(&mdctx, md, NULL))
117 ::memset(md_value, 0, sizeof(md_value));
123 void Digest::P::cleanup()
127 EVP_MD_CTX_cleanup(&mdctx);
133 Digest::Digest() : _dp(new P())
142 bool Digest::create(const std::string& name)
144 if(name.empty()) return false;
151 return _dp->maybeInit();
154 const std::string& Digest::name()
161 if (!_dp->initialized)
165 (void)EVP_DigestFinal_ex(&_dp->mdctx, _dp->md_value, &_dp->md_len);
166 _dp->finalized = true;
168 if(!EVP_DigestInit_ex(&_dp->mdctx, _dp->md, NULL))
170 _dp->finalized = false;
174 std::string Digest::digest()
176 if(!_dp->maybeInit())
177 return std::string();
181 if(!EVP_DigestFinal_ex(&_dp->mdctx, _dp->md_value, &_dp->md_len))
182 return std::string();
184 _dp->finalized = true;
187 char mdtxt[_dp->md_len*2 + 1];
188 mdtxt[_dp->md_len*2] = '\0';
190 for(unsigned i = 0; i < _dp->md_len; ++i)
192 ::snprintf(mdtxt + i*2, 3, "%02hhx", _dp->md_value[i]);
195 return std::string(mdtxt);
198 std::vector<unsigned char> Digest::digestVector()
200 std::vector<unsigned char> r;
201 if(!_dp->maybeInit())
206 if(!EVP_DigestFinal_ex(&_dp->mdctx, _dp->md_value, &_dp->md_len))
208 _dp->finalized = true;
210 r.reserve(_dp->md_len);
211 for(unsigned i = 0; i < _dp->md_len; ++i)
212 r.push_back(_dp->md_value[i]);
216 bool Digest::update(const char* bytes, size_t len)
223 if(!_dp->maybeInit())
229 if(!_dp->maybeInit())
233 if(!EVP_DigestUpdate(&_dp->mdctx, reinterpret_cast<const unsigned char*>(bytes), len))
239 std::string Digest::digest(const std::string& name, std::istream& is, size_t bufsize)
241 if(name.empty() || !is)
247 if(!digest.create(name))
254 is.read(buf, bufsize);
255 readed = is.gcount();
256 if(readed && !digest.update(buf, readed))
260 return digest.digest();
263 std::string Digest::digest( const std::string & name, const std::string & input, size_t bufsize )
265 istringstream is( input );
266 return digest( name, is, bufsize );
269 #ifdef DIGEST_TESTSUITE
270 int main(int argc, char *argv[])
272 bool openssl = false;
275 if(argc > 1 && string(argv[argpos]) == "--openssl")
281 if(argc - argpos < 2)
283 cerr << "Usage: " << argv[0] << " <DIGESTNAME> <FILE>" << endl;
287 const char* digestname = argv[argpos++];
288 const char* fn = argv[argpos++];
292 string digest = Digest::digest(digestname, file);
295 cout << digestname << "(" << fn << ")= " << digest << endl;
297 cout << digest << " " << fn << endl;