Botan  2.12.1
Crypto and TLS for C++11
argon2fmt.cpp
Go to the documentation of this file.
1 /**
2 * (C) 2019 Jack Lloyd
3 *
4 * Botan is released under the Simplified BSD License (see license.txt)
5 */
6 
7 #include <botan/argon2.h>
8 #include <botan/rng.h>
9 #include <botan/base64.h>
10 #include <botan/parsing.h>
11 #include <sstream>
12 
13 namespace Botan {
14 
15 namespace {
16 
17 std::string strip_padding(std::string s)
18  {
19  while(s.size() > 0 && s[s.size()-1] == '=')
20  s.resize(s.size() - 1);
21  return s;
22  }
23 
24 }
25 
26 std::string argon2_generate_pwhash(const char* password, size_t password_len,
28  size_t p, size_t M, size_t t,
29  uint8_t y, size_t salt_len, size_t output_len)
30  {
31  std::vector<uint8_t> salt(salt_len);
32  rng.randomize(salt.data(), salt.size());
33 
34  std::vector<uint8_t> output(output_len);
35  argon2(output.data(), output.size(),
36  password, password_len,
37  salt.data(), salt.size(),
38  nullptr, 0,
39  nullptr, 0,
40  y, p, M, t);
41 
42  std::ostringstream oss;
43 
44  if(y == 0)
45  oss << "$argon2d$";
46  else if(y == 1)
47  oss << "$argon2i$";
48  else
49  oss << "$argon2id$";
50 
51  oss << "v=19$m=" << M << ",t=" << t << ",p=" << p << "$";
52  oss << strip_padding(base64_encode(salt)) << "$" << strip_padding(base64_encode(output));
53 
54  return oss.str();
55  }
56 
57 bool argon2_check_pwhash(const char* password, size_t password_len,
58  const std::string& input_hash)
59  {
60  const std::vector<std::string> parts = split_on(input_hash, '$');
61 
62  if(parts.size() != 5)
63  return false;
64 
65  uint8_t family = 0;
66 
67  if(parts[0] == "argon2d")
68  family = 0;
69  else if(parts[0] == "argon2i")
70  family = 1;
71  else if(parts[0] == "argon2id")
72  family = 2;
73  else
74  return false;
75 
76  if(parts[1] != "v=19")
77  return false;
78 
79  const std::vector<std::string> params = split_on(parts[2], ',');
80 
81  if(params.size() != 3)
82  return false;
83 
84  size_t M = 0, t = 0, p = 0;
85 
86  for(auto param_str : params)
87  {
88  const std::vector<std::string> param = split_on(param_str, '=');
89 
90  if(param.size() != 2)
91  return false;
92 
93  const std::string key = param[0];
94  const size_t val = to_u32bit(param[1]);
95  if(key == "m")
96  M = val;
97  else if(key == "t")
98  t = val;
99  else if(key == "p")
100  p = val;
101  else
102  return false;
103  }
104 
105  std::vector<uint8_t> salt(base64_decode_max_output(parts[3].size()));
106  salt.resize(base64_decode(salt.data(), parts[3], false));
107 
108  std::vector<uint8_t> hash(base64_decode_max_output(parts[4].size()));
109  hash.resize(base64_decode(hash.data(), parts[4], false));
110 
111  if(hash.size() < 4)
112  return false;
113 
114  std::vector<uint8_t> generated(hash.size());
115  argon2(generated.data(), generated.size(),
116  password, password_len,
117  salt.data(), salt.size(),
118  nullptr, 0,
119  nullptr, 0,
120  family, p, M, t);
121 
122  return constant_time_compare(generated.data(), hash.data(), generated.size());
123  }
124 
125 }
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=2, size_t salt_len=16, size_t output_len=32)
Definition: argon2fmt.cpp:26
bool argon2_check_pwhash(const char *password, size_t password_len, const std::string &hash)
Definition: argon2fmt.cpp:57
virtual void randomize(uint8_t output[], size_t length)=0
size_t base64_decode_max_output(size_t input_length)
Definition: base64.cpp:224
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:148
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.h:81
uint32_t to_u32bit(const std::string &str)
Definition: parsing.cpp:35
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
Definition: base64.cpp:166
size_t salt_len
Definition: x509_obj.cpp:25
Definition: alg_id.cpp:13
size_t base64_decode(uint8_t out[], const char in[], size_t input_length, size_t &input_consumed, bool final_inputs, bool ignore_ws)
Definition: base64.cpp:181
void argon2(uint8_t output[], size_t output_len, const char *password, size_t password_len, const uint8_t salt[], size_t salt_len, const uint8_t key[], size_t key_len, const uint8_t ad[], size_t ad_len, uint8_t mode, size_t threads, size_t M, size_t t)
Definition: argon2.cpp:410
MechanismType hash