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"
30 #include "zypp/base/PtrTypes.h"
34 bool DigestReport::askUserToAcceptNoDigest( const zypp::Pathname &file )
37 bool DigestReport::askUserToAccepUnknownDigest( const Pathname &file, const std::string &name )
40 bool DigestReport::askUserToAcceptWrongDigest( const Pathname &file, const std::string &requested, const std::string &found )
44 const std::string & Digest::md5()
45 { static std::string _type( "md5" ); return _type; }
47 const std::string & Digest::sha1()
48 { static std::string _type( "sha1" ); return _type; }
50 const std::string & Digest::sha224()
51 { static std::string _type( "sha224" ); return _type; }
53 const std::string & Digest::sha256()
54 { static std::string _type( "sha256" ); return _type; }
56 const std::string & Digest::sha384()
57 { static std::string _type( "sha384" ); return _type; }
59 const std::string & Digest::sha512()
60 { static std::string _type( "sha512" ); return _type; }
66 const P& operator=(const P& p);
69 typedef zypp::shared_ptr<EVP_MD_CTX> EvpDataPtr;
76 unsigned char md_value[EVP_MAX_MD_SIZE];
80 static bool openssl_digests_added;
84 inline bool maybeInit();
85 inline void cleanup();
91 bool Digest::P::openssl_digests_added = false;
104 bool Digest::P::maybeInit()
106 if(!openssl_digests_added)
108 OPENSSL_config(NULL);
109 ENGINE_load_builtin_engines();
110 ENGINE_register_all_complete();
111 OpenSSL_add_all_digests();
112 openssl_digests_added = true;
117 md = EVP_get_digestbyname(name.c_str());
121 #if OPENSSL_VERSION_NUMBER < 0x10100000L
122 EvpDataPtr tmp_mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
124 EvpDataPtr tmp_mdctx(EVP_MD_CTX_new(), EVP_MD_CTX_free);
129 if (!EVP_DigestInit_ex(tmp_mdctx.get(), md, NULL)) {
134 ::memset(md_value, 0, sizeof(md_value));
136 mdctx.swap(tmp_mdctx);
141 void Digest::P::cleanup()
147 Digest::Digest() : _dp(new P())
156 bool Digest::create(const std::string& name)
158 if(name.empty()) return false;
165 return _dp->maybeInit();
168 const std::string& Digest::name()
179 (void)EVP_DigestFinal_ex(_dp->mdctx.get(), _dp->md_value, &_dp->md_len);
180 _dp->finalized = true;
182 if(!EVP_DigestInit_ex(_dp->mdctx.get(), _dp->md, NULL))
184 _dp->finalized = false;
188 std::string Digest::digest()
190 if(!_dp->maybeInit())
191 return std::string();
195 if(!EVP_DigestFinal_ex(_dp->mdctx.get(), _dp->md_value, &_dp->md_len))
196 return std::string();
198 _dp->finalized = true;
201 char mdtxt[_dp->md_len*2 + 1];
202 mdtxt[_dp->md_len*2] = '\0';
204 for(unsigned i = 0; i < _dp->md_len; ++i)
206 ::snprintf(mdtxt + i*2, 3, "%02hhx", _dp->md_value[i]);
209 return std::string(mdtxt);
212 std::vector<unsigned char> Digest::digestVector()
214 std::vector<unsigned char> r;
215 if(!_dp->maybeInit())
220 if(!EVP_DigestFinal_ex(_dp->mdctx.get(), _dp->md_value, &_dp->md_len))
222 _dp->finalized = true;
224 r.reserve(_dp->md_len);
225 for(unsigned i = 0; i < _dp->md_len; ++i)
226 r.push_back(_dp->md_value[i]);
230 bool Digest::update(const char* bytes, size_t len)
237 if(!_dp->maybeInit())
243 if(!_dp->maybeInit())
247 if(!EVP_DigestUpdate(_dp->mdctx.get(), reinterpret_cast<const unsigned char*>(bytes), len))
253 std::string Digest::digest(const std::string& name, std::istream& is, size_t bufsize)
255 if(name.empty() || !is)
261 if(!digest.create(name))
268 is.read(buf, bufsize);
269 readed = is.gcount();
270 if(readed && !digest.update(buf, readed))
274 return digest.digest();
277 std::string Digest::digest( const std::string & name, const std::string & input, size_t bufsize )
279 istringstream is( input );
280 return digest( name, is, bufsize );
283 #ifdef DIGEST_TESTSUITE
284 int main(int argc, char *argv[])
286 bool openssl = false;
289 if(argc > 1 && string(argv[argpos]) == "--openssl")
295 if(argc - argpos < 2)
297 cerr << "Usage: " << argv[0] << " <DIGESTNAME> <FILE>" << endl;
301 const char* digestname = argv[argpos++];
302 const char* fn = argv[argpos++];
306 string digest = Digest::digest(digestname, file);
309 cout << digestname << "(" << fn << ")= " << digest << endl;
311 cout << digest << " " << fn << endl;