/* * (C) 2018 Ribose Inc * * Botan is released under the Simplified BSD License (see license.txt) */ #include "cli.h" #if defined(BOTAN_HAS_PASSWORD_HASHING) #include #include #endif namespace Botan_CLI { #if defined(BOTAN_HAS_PASSWORD_HASHING) class PBKDF_Tune final : public Command { public: PBKDF_Tune() : Command("pbkdf_tune --algo=Scrypt --max-mem=256 --output-len=32 --check *times") {} std::string group() const override { return "passhash"; } std::string description() const override { return "Tune a PBKDF algo"; } void go() override { const size_t output_len = get_arg_sz("output-len"); const std::string algo = get_arg("algo"); const size_t max_mem = get_arg_sz("max-mem"); const bool check_time = flag_set("check"); std::unique_ptr pwdhash_fam = Botan::PasswordHashFamily::create(algo); if(!pwdhash_fam) throw CLI_Error_Unsupported("Password hashing", algo); for(const std::string& time : get_arg_list("times")) { std::unique_ptr pwhash; if(time == "default") { pwhash = pwdhash_fam->default_params(); } else { size_t msec = 0; try { msec = std::stoul(time); } catch(std::exception&) { throw CLI_Usage_Error("Unknown time value '" + time + "' for pbkdf_tune"); } pwhash = pwdhash_fam->tune(output_len, std::chrono::milliseconds(msec), max_mem); } output() << "For " << time << " ms selected " << pwhash->to_string(); if(pwhash->total_memory_usage() > 0) { output() << " using " << pwhash->total_memory_usage()/(1024*1024) << " MiB"; } if(check_time) { std::vector outbuf(output_len); const uint8_t salt[8] = { 0 }; const uint64_t start_ns = Botan::OS::get_system_timestamp_ns(); pwhash->derive_key(outbuf.data(), outbuf.size(), "test", 4, salt, sizeof(salt)); const uint64_t end_ns = Botan::OS::get_system_timestamp_ns(); const uint64_t dur_ns = end_ns - start_ns; output() << " took " << (dur_ns / 1000000.0) << " msec to compute"; } output() << "\n"; } } }; BOTAN_REGISTER_COMMAND("pbkdf_tune", PBKDF_Tune); #endif }