8 #include <botan/bcrypt.h>     9 #include <botan/loadstor.h>    10 #include <botan/libstate.h>    11 #include <botan/blowfish.h>    12 #include <botan/base64.h>    18 std::string bcrypt_base64_encode(
const byte input[], 
size_t length)
    21    const byte OPENBSD_BASE64_SUB[256] = {
    22       0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    23       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    24       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    25       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x38, 0x80, 0x80, 0x80, 0x39,
    26       0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x80, 0x80,
    27       0x80, 0x80, 0x80, 0x80, 0x80, 0x2E, 0x2F, 0x41, 0x42, 0x43, 0x44, 0x45,
    28       0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51,
    29       0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x80, 0x80, 0x80, 0x80, 0x80,
    30       0x80, 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
    31       0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75,
    32       0x76, 0x77, 0x78, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    33       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    34       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    35       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    36       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    37       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    38       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    39       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    40       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    41       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    42       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    43       0x80, 0x80, 0x80, 0x80
    48    while(b64.size() && b64[b64.size()-1] == 
'=')
    49       b64 = b64.substr(0, b64.size() - 1);
    51    for(
size_t i = 0; i != b64.size(); ++i)
    52       b64[i] = OPENBSD_BASE64_SUB[static_cast<byte>(b64[i])];
    57 MemoryVector<byte> bcrypt_base64_decode(std::string input)
    59    const byte OPENBSD_BASE64_SUB[256] = {
    60       0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    61       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    62       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    63       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x41, 0x42,
    64       0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F, 0x80, 0x80,
    65       0x80, 0x80, 0x80, 0x80, 0x80, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
    66       0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55,
    67       0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 0x80, 0x80, 0x80, 0x80, 0x80,
    68       0x80, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D,
    69       0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
    70       0x7A, 0x30, 0x31, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    71       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    72       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    73       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    74       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    75       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    76       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    77       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    78       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    79       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    80       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    81       0x80, 0x80, 0x80, 0x80
    84    for(
size_t i = 0; i != input.size(); ++i)
    85       input[i] = OPENBSD_BASE64_SUB[static_cast<byte>(input[i])];
    90 std::string make_bcrypt(
const std::string& pass,
    91                         const MemoryRegion<byte>& salt,
    94    const byte magic[24] = {
    95       0x4F, 0x72, 0x70, 0x68, 0x65, 0x61, 0x6E, 0x42,
    96       0x65, 0x68, 0x6F, 0x6C, 0x64, 0x65, 0x72, 0x53,
    97       0x63, 0x72, 0x79, 0x44, 0x6F, 0x75, 0x62, 0x74
   100    MemoryVector<byte> ctext(magic, 24);
   105    blowfish.eks_key_schedule(reinterpret_cast<const byte*>(pass.c_str()),
   110    for(
size_t i = 0; i != 64; ++i)
   111       blowfish.encrypt_n(&ctext[0], &ctext[0], 3);
   113    std::string salt_b64 = bcrypt_base64_encode(&salt[0], salt.size());
   115    return "$2a$" + 
to_string(work_factor, 2) + 
"$" + salt_b64.substr(0, 22) +
   116              bcrypt_base64_encode(&ctext[0], ctext.size() - 1);
   125    return make_bcrypt(pass, rng.
random_vec(16), work_factor);
   130    if(hash.size() != 60 ||
   131       hash[0] != 
'$' || hash[1] != 
'2' || hash[2] != 
'a' ||
   132       hash[3] != 
'$' || hash[6] != 
'$')
   141    const std::string compare = make_bcrypt(pass, salt, workfactor);
   143    return (hash == compare);
 size_t base64_decode(byte output[], const char input[], size_t input_length, size_t &input_consumed, bool final_inputs, bool ignore_ws)
SecureVector< byte > random_vec(size_t bytes)
bool check_bcrypt(const std::string &pass, const std::string &hash)
std::string generate_bcrypt(const std::string &pass, RandomNumberGenerator &rng, u16bit work_factor)
std::string to_string(u64bit n, size_t min_len)
u32bit to_u32bit(const std::string &number)
size_t base64_encode(char out[], const byte in[], size_t input_length, size_t &input_consumed, bool final_inputs)