31 #include <openssl/evp.h>
35 #include <CommonCrypto/CommonDigest.h>
43 const std::string hash_prefix =
"$H$";
45 template<std::
size_t len>
46 std::string encode_hash(
const std::array<uint8_t, len>& bytes) {
50 template<std::
size_t len>
51 std::string hexencode_hash(
const std::array<uint8_t, len>& input) {
52 std::ostringstream sout;
54 for(uint8_t
c : input) {
55 sout << static_cast<int>(
c);
67 EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
68 unsigned int md5_digest_len = EVP_MD_size(EVP_md5());
72 EVP_DigestInit_ex(mdctx, EVP_md5(),
nullptr);
75 EVP_DigestUpdate(mdctx, input.c_str(), input.size());
78 EVP_DigestFinal_ex(mdctx,
hash.data(), &md5_digest_len);
79 EVP_MD_CTX_free(mdctx);
81 CC_MD5(input.data(),
static_cast<CC_LONG
>(input.size()),
hash.data());
91 return hash.substr(4,8);
96 return hash.substr(0,3) == hash_prefix;
100 if(
hash.size() != 34)
return false;
104 if(iteration_count < 7 || iteration_count > 30)
return false;
109 md5::md5(
const std::string& password,
const std::string& salt,
int iteration_count)
111 iteration_count = 1 << iteration_count;
113 hash =
md5(salt + password).raw_digest();
115 hash =
md5(std::string(
hash.begin(),
hash.end()).append(password)).raw_digest();
116 }
while(--iteration_count);
121 return hexencode_hash<DIGEST_SIZE>(
hash);
126 return encode_hash<DIGEST_SIZE>(
hash);
141 std::string bcrypt_salt = input.substr(0,
hash.iteration_count_delim_pos + 23);
144 strcpy(
hash.hash.data(), bcrypt_salt.c_str());
154 strcpy(
hash.hash.data(), input.c_str());
169 return ((
hash.compare(0, 4,
"$2a$") == 0)
170 || (
hash.compare(0, 4,
"$2b$") == 0)
171 || (
hash.compare(0, 4,
"$2x$") == 0)
172 || (
hash.compare(0, 4,
"$2y$") == 0));
180 return std::string(
hash.data(), salt_pos);
185 return std::string(
hash.data());
190 return std::string(
hash.data());
std::size_t iteration_count_delim_pos
virtual std::string base64_digest() const override
static bool is_valid_prefix(const std::string &hash)
std::string get_salt() const
static bcrypt from_hash_string(const std::string &input)
virtual std::string hex_digest() const override
static bcrypt from_salted_salt(const std::string &input)
static bcrypt hash_pw(const std::string &password, bcrypt &salt)
static const unsigned int DIGEST_SIZE
std::array< uint8_t, sz > hash
static bool is_valid_prefix(const std::string &hash)
virtual std::string base64_digest() const override
static std::string get_salt(const std::string &hash)
virtual std::string hex_digest() const override
static int get_iteration_count(const std::string &hash)
static bool is_valid_hash(const std::string &hash)
md5(const std::string &input)
char * php_crypt_blowfish_rn(const char *key, const char *setting, char *output, int size)
static const int BCRYPT_HASHSIZE
std::string encode(utils::byte_view bytes)
std::vector< uint8_t > decode(std::string_view in)