/* * (C) 2018 Ribose Inc * * Botan is released under the Simplified BSD License (see license.txt) */ #ifndef BOTAN_PWDHASH_H_ #define BOTAN_PWDHASH_H_ #include #include #include #include #include namespace Botan { /** * Base class for password based key derivation functions. * * Converts a password into a key using a salt and iterated hashing to * make brute force attacks harder. */ class BOTAN_PUBLIC_API(2,8) PasswordHash { public: virtual ~PasswordHash() = default; virtual std::string to_string() const = 0; /** * Most password hashes have some notion of iterations. */ virtual size_t iterations() const = 0; /** * Some password hashing algorithms have a parameter which controls how * much memory is used. If not supported by some algorithm, returns 0. */ virtual size_t memory_param() const { return 0; } /** * Some password hashing algorithms have a parallelism parameter. * If the algorithm does not support this notion, then the * function returns zero. This allows distinguishing between a * password hash which just does not support parallel operation, * vs one that does support parallel operation but which has been * configured to use a single lane. */ virtual size_t parallelism() const { return 0; } /** * Returns an estimate of the total memory usage required to perform this * key derivation. * * If this algorithm uses a small and constant amount of memory, with no * effort made towards being memory hard, this function returns 0. */ virtual size_t total_memory_usage() const { return 0; } /** * Derive a key from a password * * @param out buffer to store the derived key, must be of out_len bytes * @param out_len the desired length of the key to produce * @param password the password to derive the key from * @param password_len the length of password in bytes * @param salt a randomly chosen salt * @param salt_len length of salt in bytes * * This function is const, but is not thread safe. Different threads should * either use unique objects, or serialize all access. */ virtual void derive_key(uint8_t out[], size_t out_len, const char* password, size_t password_len, const uint8_t salt[], size_t salt_len) const = 0; }; class BOTAN_PUBLIC_API(2,8) PasswordHashFamily { public: /** * Create an instance based on a name * If provider is empty then best available is chosen. * @param algo_spec algorithm name * @param provider provider implementation to choose * @return a null pointer if the algo/provider combination cannot be found */ static std::unique_ptr create(const std::string& algo_spec, const std::string& provider = ""); /** * Create an instance based on a name, or throw if the * algo/provider combination cannot be found. If provider is * empty then best available is chosen. */ static std::unique_ptr create_or_throw(const std::string& algo_spec, const std::string& provider = ""); /** * @return list of available providers for this algorithm, empty if not available */ static std::vector providers(const std::string& algo_spec); virtual ~PasswordHashFamily() = default; /** * @return name of this PasswordHash */ virtual std::string name() const = 0; /** * Return a new parameter set tuned for this machine * @param output_length how long the output length will be * @param msec the desired execution time in milliseconds * * @param max_memory_usage_mb some password hash functions can use a tunable * amount of memory, in this case max_memory_usage limits the amount of RAM * the returned parameters will require, in mebibytes (2**20 bytes). It may * require some small amount above the request. Set to zero to place no * limit at all. */ virtual std::unique_ptr tune(size_t output_length, std::chrono::milliseconds msec, size_t max_memory_usage_mb = 0) const = 0; /** * Return some default parameter set for this PBKDF that should be good * enough for most users. The value returned may change over time as * processing power and attacks improve. */ virtual std::unique_ptr default_params() const = 0; /** * Return a parameter chosen based on a rough approximation with the * specified iteration count. The exact value this returns for a particular * algorithm may change from over time. Think of it as an alternative to * tune, where time is expressed in terms of PBKDF2 iterations rather than * milliseconds. */ virtual std::unique_ptr from_iterations(size_t iterations) const = 0; /** * Create a password hash using some scheme specific format. * Eg PBKDF2 and PGP-S2K set iterations in i1 * Scrypt uses N,r,p in i{1-3} * Bcrypt-PBKDF just has iterations * Argon2{i,d,id} would use iterations, memory, parallelism for i{1-3}, * and Argon2 type is part of the family. * * Values not needed should be set to 0 */ virtual std::unique_ptr from_params( size_t i1, size_t i2 = 0, size_t i3 = 0) const = 0; }; } #endif