35struct hashing::Argon2HashingEngine::Data {
43 Data(Algorithm algorithm, uint32_t timeCost, uint32_t memoryCost, uint32_t parallelism,
string salt,
size_t hashLen)
44 : algorithm(algorithm), timeCost(timeCost), memoryCost(memoryCost), parallelism(parallelism),
45 salt(std::move(salt)), hashLen(hashLen) {}
51 uint32_t timeCost, uint32_t memoryCost, uint32_t parallelism,
52 std::
string salt,
size_t hashLen) {
53 data = make_unique<Data>(algorithm, timeCost, memoryCost, parallelism, std::move(salt), hashLen);
56std::string hashing::Argon2HashingEngine::generateHash(std::string input)
const {
59 if (!data->salt.empty() && data->salt.length() < ARGON2_MIN_SALT_LENGTH) {
61 "Provided user-defined salt is not long enough");
64 string actualSalt = data->salt;
65 if (data->salt.empty()) {
69 if (rd.entropy() == 32) {
70 uniform_int_distribution<uint32_t> distribution(0, 0xffffffff);
71 for (
int i = 0; i < 4; ++i) {
72 uint32_t val = distribution(rd);
73 sstr << (char) (val & 0xff);
74 sstr << (char) ((val >> 8) & 0xff);
75 sstr << (char) ((val >> 16) & 0xff);
76 sstr << (char) ((val >> 24) & 0xff);
79 uniform_int_distribution<uint16_t> distribution(0, 0xffff);
80 for (
int i = 0; i < 8; ++i) {
81 uint16_t val = distribution(rd);
82 sstr << (char) (val & 0xff);
83 sstr << (char) ((val >> 8) & 0xff);
86 actualSalt = sstr.str();
90 size_t encodedHashCeil = 50 + (actualSalt.length() * 4) / 3 + (data->hashLen * 4) / 3;
91 char c_hash[encodedHashCeil];
92 memset(c_hash,
'\0', encodedHashCeil);
94 switch (data->algorithm) {
96 errorCode = argon2i_hash_encoded(data->timeCost, data->memoryCost, data->parallelism,
97 (
void*) input.c_str(), input.length(),
98 (
void*) actualSalt.c_str(), actualSalt.length(), data->hashLen, c_hash,
102 errorCode = argon2d_hash_encoded(data->timeCost, data->memoryCost, data->parallelism,
103 (
void*) input.c_str(), input.length(),
104 (
void*) actualSalt.c_str(), actualSalt.length(), data->hashLen, c_hash,
108 errorCode = argon2id_hash_encoded(data->timeCost, data->memoryCost, data->parallelism,
109 (
void*) input.c_str(), input.length(),
110 (
void*) actualSalt.c_str(), actualSalt.length(), data->hashLen, c_hash,
116 if (errorCode != ARGON2_OK) {
118 string(
"Argon2 error: ") + argon2_error_message(errorCode));
128 R
"(\$argon2(i|d|id)\$(v=([0-9]+))?\$m=([0-9]+),t=([0-9]+),p=([0-9]+)\$([A-Za-z0-9+\/]+={0,2})\$([A-Za-z0-9+\/]+={0,2}))");
130 regex_match(hash, matches, rgx);
133 uint32_t memoryCost1;
135 uint32_t parallelism1;
138 if (matches.size() == 9) {
139 if (matches[1] ==
"d")
140 algorithm1 = Algorithm::ARGON2D;
141 else if (matches[1] ==
"id")
142 algorithm1 = Algorithm::ARGON2ID;
144 algorithm1 = Algorithm::ARGON2I;
146 version1 = stoul(matches[3]);
147 memoryCost1 = stoul(matches[4]);
148 timeCost1 = stoul(matches[5]);
149 parallelism1 = stoul(matches[6]);
158 if (version1 != 19) {
162 auto engine1 =
Argon2HashingEngine(algorithm1, timeCost1, memoryCost1, parallelism1, salt1, hash1.length());
165 inputHash = engine1.generateHash(input);
171 if (hash1.length() != inputHash.length())
174 auto u1 = (
const unsigned char*) hash1.c_str();
175 auto u2 = (
const unsigned char*) inputHash.c_str();
178 for (
int i = 0; i < hash1.length(); ++i)
179 ret |= (u1[i] ^ u2[i]);
Exception class that can be used by apps to catch errors resulting from nawa function calls.
bool verifyHash(std::string input, std::string hash) const override
Namespace containing functions for text encoding and decoding.
#define NAWA_DEFAULT_DESTRUCTOR_IMPL_WITH_NS(Namespace, Class)
std::string base64Decode(std::string const &input)