11 #include "errors/exceptions.h"
12 #include "memory/memory.h"
13 #include "string/encoding.h"
14 #include "string/format.h"
15 #include "utility/countof.h"
19 #include <openssl/evp.h>
20 #include <openssl/hmac.h>
25 : _secret_length(secret_length), _pin_length(pin_length)
27 assert((
secret_length >= 6) &&
"Secret should be at least 6 bytes!");
29 throwex CppCommon::SecurityException(
"Invalid secret length!");
30 assert(((
pin_length >= 3) && (
pin_length <= 10)) &&
"Pin should be at least 3 digits and not more than 10 digits!");
32 throwex CppCommon::SecurityException(
"Invalid pin length!");
38 CppCommon::Memory::CryptoFill(result.data(), result.size());
44 return std::password(CppCommon::Encoding::Base32Encode(password));
50 uint8_t hash[EVP_MAX_MD_SIZE];
51 unsigned int size = EVP_MAX_MD_SIZE;
52 if (HMAC(EVP_sha1(), password.data(), (
int)password.size(), (
const uint8_t*)salt.data(), (
int)salt.size(), hash, &size) ==
nullptr)
53 throwex CppCommon::SecurityException(
"HMAC-SHA1 calculation error!");
57 for (
size_t i = 0; i < result.size(); ++i)
58 result[i] = hash[i % size];
64 return std::password(CppCommon::Encoding::URLEncode(CppCommon::format(
"otpauth://totp/{}?secret={}", identifier, secret)));
69 return std::password(CppCommon::format(
"https://chart.apis.google.com/chart?cht=qr&chs={}x{}&chl={}", width, height, url));
75 uint64_t seconds = timestamp.seconds() / 30;
79 for (
size_t i = 8; i--; seconds >>= 8)
80 challenge[i] = seconds & 0xFF;
86 uint8_t hash[EVP_MAX_MD_SIZE];
87 unsigned int size = EVP_MAX_MD_SIZE;
88 if (HMAC(EVP_sha1(), key.data(), (
int)key.size(), challenge, CppCommon::countof(challenge), hash, &size) ==
nullptr)
89 throwex CppCommon::SecurityException(
"HMAC-SHA1 calculation error!");
92 size_t offset = hash[size - 1] & 0xF;
96 for (
size_t i = 0; i < 4; ++i)
99 truncated |= hash[offset + i];
108 truncated &= 0x7FFFFFFF;
size_t pin_length() const noexcept
Get the pin length.
size_t GenerateToken(std::string_view secret, const CppCommon::Timestamp ×tamp=CppCommon::UtcTimestamp()) const
Generate the Google Authenticator token for the given secret and UTC timestamp.
std::password GenerateURL(std::string_view identifier, std::string_view secret) const
Generate the Google Authenticator URL.
std::string GenerateSalt() const
Generate the unique password salt.
GoogleAuthenticator(size_t secret_length=12, size_t pin_length=6)
Initialize Google Authenticator with required parameters.
std::password GenerateQRCodeLink(std::string_view url, size_t width=100, size_t height=100) const
Generate the Google Authenticator QR Code link.
std::password GenerateSecret(std::string_view password) const
Generate the Google Authenticator secret from the given user password.
size_t secret_length() const noexcept
Get the secret length.
bool Validate(size_t token, std::string_view secret, const CppCommon::Timestamp ×tamp=CppCommon::UtcTimestamp()) const
Validate the Google Authenticator token over the given secret and UTC timestamp.
Google Authenticator definition.