8 #include <botan/passhash9.h>
9 #include <botan/loadstor.h>
10 #include <botan/pbkdf2.h>
11 #include <botan/base64.h>
17 const std::string MAGIC_PREFIX =
"$9$";
19 const size_t WORKFACTOR_BYTES = 2;
20 const size_t ALGID_BYTES = 1;
21 const size_t SALT_BYTES = 12;
22 const size_t PASSHASH9_PBKDF_OUTPUT_LEN = 24;
24 const size_t WORK_FACTOR_SCALE = 10000;
26 std::unique_ptr<MessageAuthenticationCode> get_pbkdf_prf(uint8_t alg_id)
48 std::unique_ptr<MessageAuthenticationCode> prf = get_pbkdf_prf(alg_id);
60 const size_t kdf_iterations = WORK_FACTOR_SCALE * work_factor;
63 blob.push_back(alg_id);
64 blob.push_back(
get_byte(0, work_factor));
65 blob.push_back(
get_byte(1, work_factor));
67 blob += kdf.derive_key(PASSHASH9_PBKDF_OUTPUT_LEN,
69 salt.data(), salt.size(),
70 kdf_iterations).bits_of();
77 const size_t BINARY_LENGTH =
80 PASSHASH9_PBKDF_OUTPUT_LEN +
83 const size_t BASE64_LENGTH =
84 MAGIC_PREFIX.size() + (BINARY_LENGTH * 8) / 6;
86 if(hash.size() != BASE64_LENGTH)
89 for(
size_t i = 0; i != MAGIC_PREFIX.size(); ++i)
90 if(hash[i] != MAGIC_PREFIX[i])
95 if(bin.size() != BINARY_LENGTH)
98 uint8_t alg_id = bin[0];
106 if(work_factor > 512)
110 const size_t kdf_iterations = WORK_FACTOR_SCALE * work_factor;
112 std::unique_ptr<MessageAuthenticationCode> pbkdf_prf = get_pbkdf_prf(alg_id);
120 PASSHASH9_PBKDF_OUTPUT_LEN,
122 &bin[ALGID_BYTES + WORKFACTOR_BYTES], SALT_BYTES,
126 &bin[ALGID_BYTES + WORKFACTOR_BYTES + SALT_BYTES],
127 PASSHASH9_PBKDF_OUTPUT_LEN);
secure_vector< uint8_t > bits_of() const
static std::unique_ptr< MessageAuthenticationCode > create(const std::string &algo_spec, const std::string &provider="")
bool same_mem(const T *p1, const T *p2, size_t n)
virtual void randomize(uint8_t output[], size_t length)=0
size_t base64_decode(uint8_t output[], const char input[], size_t input_length, size_t &input_consumed, bool final_inputs, bool ignore_ws)
uint16_t load_be< uint16_t >(const uint8_t in[], size_t off)
OctetString derive_key(size_t out_len, const std::string &passphrase, const uint8_t salt[], size_t salt_len, size_t iterations) const
bool check_passhash9(const std::string &pass, const std::string &hash)
std::string to_string(const BER_Object &obj)
std::vector< T, secure_allocator< T >> secure_vector
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
uint8_t get_byte(size_t byte_num, T input)
std::string generate_passhash9(const std::string &pass, RandomNumberGenerator &rng, uint16_t work_factor, uint8_t alg_id)