7#include <botan/argon2fmt.h>
9#include <botan/base64.h>
10#include <botan/mem_ops.h>
11#include <botan/pwdhash.h>
13#include <botan/internal/ct_utils.h>
14#include <botan/internal/fmt.h>
15#include <botan/internal/parsing.h>
21std::string strip_padding(std::string s) {
22 while(!s.empty() && s[s.size() - 1] ==
'=') {
23 s.resize(s.size() - 1);
28std::string argon2_family(uint8_t y) {
36 throw Not_Implemented(
"Unknown Argon2 family type");
51 std::vector<uint8_t> salt(salt_len);
54 std::vector<uint8_t> output(output_len);
57 auto pwdhash = pwdhash_fam->from_params(M, t, p);
59 pwdhash->derive_key(output.data(), output.size(), password, password_len, salt.data(), salt.size());
64 const std::string argon2_mode = [&]() -> std::string {
74 return fmt(
"$argon2{}$v=19$m={},t={},p={}${}${}", argon2_mode, M, t, p, enc_salt, enc_output);
78 const std::vector<std::string> parts =
split_on(input_hash,
'$');
80 if(parts.size() != 5) {
86 if(parts[0] ==
"argon2d") {
88 }
else if(parts[0] ==
"argon2i") {
90 }
else if(parts[0] ==
"argon2id") {
96 if(parts[1] !=
"v=19") {
100 const std::vector<std::string> params =
split_on(parts[2],
',');
102 if(params.size() != 3) {
106 size_t M = 0, t = 0, p = 0;
108 for(
const auto& param_str : params) {
109 const std::vector<std::string> param =
split_on(param_str,
'=');
111 if(param.size() != 2) {
115 std::string_view key = param[0];
119 }
else if(key ==
"t") {
121 }
else if(key ==
"p") {
134 if(hash.size() < 4) {
138 std::vector<uint8_t> generated(hash.size());
140 auto pwdhash = pwdhash_fam->from_params(M, t, p);
142 pwdhash->derive_key(generated.data(), generated.size(), password, password_len, salt.data(), salt.size());
144 return CT::is_equal(generated.data(), hash.data(), generated.size()).as_bool();
static std::unique_ptr< PasswordHashFamily > create_or_throw(std::string_view algo_spec, std::string_view provider="")
void randomize(std::span< uint8_t > output)
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
uint32_t to_u32bit(std::string_view str_view)
std::string fmt(std::string_view format, const T &... args)
std::vector< std::string > split_on(std::string_view str, char delim)
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
size_t base64_decode(uint8_t out[], const char in[], size_t input_length, size_t &input_consumed, bool final_inputs, bool ignore_ws)
bool argon2_check_pwhash(const char *password, size_t password_len, std::string_view input_hash)
std::string argon2_generate_pwhash(const char *password, size_t password_len, RandomNumberGenerator &rng, size_t p, size_t M, size_t t, uint8_t y, size_t salt_len, size_t output_len)
size_t base64_decode_max_output(size_t input_length)