-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathHash.cpp
More file actions
118 lines (99 loc) · 4.12 KB
/
Copy pathHash.cpp
File metadata and controls
118 lines (99 loc) · 4.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*
* Copyright (c) 2026 Kirill Sergeev, Nikolay Sugonyako, Andrey Agarkov, Gleb Safyannikov
* SPDX-License-Identifier: LGPL-3.0-or-later
*
* This file is part of lightlib.
*
* lightlib is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* lightlib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with lightlib; if not, see <https://www.gnu.org/licenses/>.
*/
#include "../include/lightlib/vendor/Facades/Hash.hpp"
using namespace lightlib;
std::vector<unsigned char> Hash::generateSalt(size_t length) {
std::vector<unsigned char> salt(length);
if (RAND_bytes(salt.data(), length) != 1) {
Logger::log("Failed to generate salt", "ERROR");
return {};
}
return salt;
}
std::pair<std::string, std::vector<unsigned char>> Hash::hash(const std::string& password, std::vector<unsigned char> salt) {
std::vector<unsigned char> output(output_length);
uint32_t actual_iterations = iterations;
EVP_KDF* kdf = EVP_KDF_fetch(nullptr, "ARGON2ID", nullptr);
if (!kdf) {
Logger::log("Error: Argon2 not supported in OpenSSL", "ERROR");
return { "", std::vector<unsigned char> {} };
}
EVP_KDF_CTX* ctx = EVP_KDF_CTX_new(kdf);
if (!ctx) {
Logger::log("Error: Failed to create KDF context", "ERROR");
EVP_KDF_free(kdf);
return { "", std::vector<unsigned char> {} };
}
salt = salt.size() > 0 ? salt : generateSalt(64);
OSSL_PARAM params[] = {
OSSL_PARAM_construct_octet_string("pass", const_cast<char*>(password.data()), password.size()),
OSSL_PARAM_construct_octet_string("salt", salt.data(), salt.size()),
OSSL_PARAM_construct_uint("iter", &actual_iterations),
OSSL_PARAM_construct_uint("memcost", &memory_cost),
OSSL_PARAM_construct_uint("parallelism", ¶llelism),
OSSL_PARAM_construct_end()
};
if (EVP_KDF_derive(ctx, output.data(), output.size(), params) <= 0) {
Logger::log("Error: Argon2 hashing failed", "ERROR");
EVP_KDF_CTX_free(ctx);
EVP_KDF_free(kdf);
return { "", std::vector<unsigned char> {} };
}
std::ostringstream oss;
for (unsigned char byte : output) {
oss << std::hex << std::setw(2) << std::setfill('0') << (int)byte;
}
EVP_KDF_CTX_free(ctx);
EVP_KDF_free(kdf);
return { oss.str(), salt };
}
std::vector<uint8_t> Hash::hexStringToBytes(const std::string& hex) {
std::vector<uint8_t> bytes;
for (size_t i = 0; i < hex.length(); i += 2) {
std::string byteString = hex.substr(i, 2);
uint8_t byte = static_cast<uint8_t>(strtol(byteString.c_str(), nullptr, 16));
bytes.push_back(byte);
}
return bytes;
}
std::string Hash::bytesToHexString(const std::vector<uint8_t>& bytes) {
std::ostringstream oss;
oss << std::hex << std::setfill('0');
for (uint8_t byte : bytes) {
oss << std::setw(2) << static_cast<int>(byte);
}
return oss.str();
}
bool Hash::verify(const std::string& password, const std::string& stored_hash, const std::vector<unsigned char>& salt) {
auto [new_hash, _] = Hash::hash(password, salt);
auto stored_bytes = Hash::hexStringToBytes(stored_hash);
auto new_bytes = Hash::hexStringToBytes(new_hash);
bool match = stored_bytes == new_bytes;
return match;
}
boost::asio::awaitable<std::pair<std::string, std::vector<unsigned char>>> Hash::awaitableHash(
const std::string& password,
std::vector<unsigned char> salt) {
co_return Hash::hash(password, salt);
}
boost::asio::awaitable<bool> Hash::awaitableVerify(
const std::string& password, const std::string& stored_hash, const std::vector<unsigned char>& salt) {
co_return Hash::verify(password, stored_hash, salt);
}