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) {
51 template<std::
size_t len>
52 std::string hexencode_hash(
const std::array<uint8_t, len>& input) {
53 std::ostringstream sout;
55 for(uint8_t
c : input) {
56 sout << static_cast<int>(
c);
68 EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
69 unsigned int md5_digest_len = EVP_MD_size(EVP_md5());
73 EVP_DigestInit_ex(mdctx, EVP_md5(), NULL);
76 EVP_DigestUpdate(mdctx, input.c_str(), input.size());
79 EVP_DigestFinal_ex(mdctx,
hash.data(), &md5_digest_len);
80 EVP_MD_CTX_free(mdctx);
82 CC_MD5(input.data(),
static_cast<CC_LONG
>(input.size()),
hash.data());
92 return hash.substr(4,8);
97 return hash.substr(0,3) == hash_prefix;
101 if(
hash.size() != 34)
return false;
105 if(iteration_count < 7 || iteration_count > 30)
return false;
110 md5::md5(
const std::string& password,
const std::string& salt,
int iteration_count)
112 iteration_count = 1 << iteration_count;
114 hash =
md5(salt + password).raw_digest();
116 hash =
md5(std::string(
hash.begin(),
hash.end()).append(password)).raw_digest();
117 }
while(--iteration_count);
122 return hexencode_hash<DIGEST_SIZE>(
hash);
127 return encode_hash<DIGEST_SIZE>(
hash);
142 std::string bcrypt_salt = input.substr(0,
hash.iteration_count_delim_pos + 23);
145 strcpy(
hash.hash.data(), bcrypt_salt.c_str());
155 strcpy(
hash.hash.data(), input.c_str());
170 return ((
hash.compare(0, 4,
"$2a$") == 0)
171 || (
hash.compare(0, 4,
"$2b$") == 0)
172 || (
hash.compare(0, 4,
"$2x$") == 0)
173 || (
hash.compare(0, 4,
"$2y$") == 0));
181 return std::string(
hash.data(), salt_pos);
186 return std::string(
hash.data());
191 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_string_view bytes)
std::vector< uint8_t > decode(std::string_view in)
std::basic_string_view< uint8_t > byte_string_view