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
|
#include "auth.h"
#include <crypt.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <random>
#include <stdexcept>
// crypt specified password
std::string Auth::generate(const std::string& pw)
{
struct crypt_data data;
memset((void *)&data, '\0', sizeof(data));
std::random_device rd;
std::mt19937 rng{rd()};
std::uniform_int_distribution<int> uid(0, 63);
std::string chars{std::string(std::string::size_type(64), char('a'))};
std::iota(chars.begin() , chars.begin() + 26, 'a');
std::iota(chars.begin() + 26, chars.begin() + 52, 'A');
std::iota(chars.begin() + 52, chars.begin() + 62, '0');
chars[62] = '.';
chars[63] = '/';
std::string salt{{chars[uid(rng)], chars[uid(rng)]}};
char* result;
if ((result = crypt_r(pw.data(), salt.data(), &data)) == nullptr)
throw std::runtime_error("Error on crypt_r()");
return result;
}
// validate specified password against crypted hash
bool Auth::validate(const std::string& crypted, const std::string& pw)
{
struct crypt_data data;
memset((void *)&data, '\0', sizeof(data));
if (crypted.size() < 2) {
std::cerr << "Warning: Bad password hash configured (size)" << std::endl;
return false;
}
std::string salt{crypted.substr(0, 2)};
char* output;
if ((output = crypt_r(pw.data(), salt.data(), &data)) == nullptr) {
std::cerr << "Warning: Error on crypt_r()" << std::endl;
return false;
}
return crypted == output;
}
|