• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5111374265

29 May 2023 11:19AM UTC coverage: 92.227% (+0.5%) from 91.723%
5111374265

push

github

randombit
Next release will be 3.1.0. Update release notes

75588 of 81959 relevant lines covered (92.23%)

11886470.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.72
/src/lib/passhash/argon2fmt/argon2fmt.cpp
1
/**
2
* (C) 2019 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include <botan/argon2fmt.h>
8

9
#include <botan/base64.h>
10
#include <botan/pwdhash.h>
11
#include <botan/rng.h>
12
#include <botan/internal/fmt.h>
13
#include <botan/internal/parsing.h>
14

15
namespace Botan {
16

17
namespace {
18

19
std::string strip_padding(std::string s) {
12✔
20
   while(!s.empty() && s[s.size() - 1] == '=')
36✔
21
      s.resize(s.size() - 1);
24✔
22
   return s;
12✔
23
}
24

25
std::string argon2_family(uint8_t y) {
14✔
26
   if(y == 0)
14✔
27
      return "Argon2d";
3✔
28
   else if(y == 1)
11✔
29
      return "Argon2i";
3✔
30
   else if(y == 2)
8✔
31
      return "Argon2id";
8✔
32
   else
33
      throw Not_Implemented("Unknown Argon2 family type");
×
34
}
35

36
}  // namespace
37

38
std::string argon2_generate_pwhash(const char* password,
6✔
39
                                   size_t password_len,
40
                                   RandomNumberGenerator& rng,
41
                                   size_t p,
42
                                   size_t M,
43
                                   size_t t,
44
                                   uint8_t y,
45
                                   size_t salt_len,
46
                                   size_t output_len) {
47
   std::vector<uint8_t> salt(salt_len);
6✔
48
   rng.randomize(salt.data(), salt.size());
6✔
49

50
   std::vector<uint8_t> output(output_len);
6✔
51

52
   auto pwdhash_fam = PasswordHashFamily::create_or_throw(argon2_family(y));
6✔
53
   auto pwdhash = pwdhash_fam->from_params(M, t, p);
6✔
54

55
   pwdhash->derive_key(output.data(), output.size(), password, password_len, salt.data(), salt.size());
6✔
56

57
   const auto enc_salt = strip_padding(base64_encode(salt));
6✔
58
   const auto enc_output = strip_padding(base64_encode(output));
6✔
59

60
   const std::string argon2_mode = [&]() -> std::string {
12✔
61
      if(y == 0)
6✔
62
         return "d";
1✔
63
      else if(y == 1)
5✔
64
         return "i";
1✔
65
      else
66
         return "id";
4✔
67
   }();
6✔
68

69
   return fmt("$argon2{}$v=19$m={},t={},p={}${}${}", argon2_mode, M, t, p, enc_salt, enc_output);
6✔
70
}
42✔
71

72
bool argon2_check_pwhash(const char* password, size_t password_len, std::string_view input_hash) {
8✔
73
   const std::vector<std::string> parts = split_on(input_hash, '$');
8✔
74

75
   if(parts.size() != 5)
8✔
76
      return false;
77

78
   uint8_t family = 0;
8✔
79

80
   if(parts[0] == "argon2d")
8✔
81
      family = 0;
82
   else if(parts[0] == "argon2i")
6✔
83
      family = 1;
84
   else if(parts[0] == "argon2id")
4✔
85
      family = 2;
86
   else
87
      return false;
88

89
   if(parts[1] != "v=19")
8✔
90
      return false;
91

92
   const std::vector<std::string> params = split_on(parts[2], ',');
8✔
93

94
   if(params.size() != 3)
8✔
95
      return false;
96

97
   size_t M = 0, t = 0, p = 0;
98

99
   for(const auto& param_str : params) {
32✔
100
      const std::vector<std::string> param = split_on(param_str, '=');
24✔
101

102
      if(param.size() != 2)
24✔
103
         return false;
104

105
      std::string_view key = param[0];
24✔
106
      const size_t val = to_u32bit(param[1]);
24✔
107
      if(key == "m")
48✔
108
         M = val;
109
      else if(key == "t")
32✔
110
         t = val;
111
      else if(key == "p")
16✔
112
         p = val;
113
      else
114
         return false;
×
115
   }
24✔
116

117
   std::vector<uint8_t> salt(base64_decode_max_output(parts[3].size()));
8✔
118
   salt.resize(base64_decode(salt.data(), parts[3], false));
8✔
119

120
   std::vector<uint8_t> hash(base64_decode_max_output(parts[4].size()));
8✔
121
   hash.resize(base64_decode(hash.data(), parts[4], false));
8✔
122

123
   if(hash.size() < 4)
8✔
124
      return false;
125

126
   std::vector<uint8_t> generated(hash.size());
8✔
127
   auto pwdhash_fam = PasswordHashFamily::create_or_throw(argon2_family(family));
8✔
128
   auto pwdhash = pwdhash_fam->from_params(M, t, p);
8✔
129

130
   pwdhash->derive_key(generated.data(), generated.size(), password, password_len, salt.data(), salt.size());
8✔
131

132
   return constant_time_compare(generated.data(), hash.data(), generated.size());
8✔
133
}
40✔
134

135
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc