1 /*
2 * Bcrypt Password Hashing
3 * (C) 2010 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
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>
13 
14 namespace Botan {
15 
16 namespace {
17 
bcrypt_base64_encode(const byte input[],size_t length)18 std::string bcrypt_base64_encode(const byte input[], size_t length)
19    {
20    // Bcrypt uses a non-standard base64 alphabet
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
44    };
45 
46    std::string b64 = base64_encode(input, length);
47 
48    while(b64.size() && b64[b64.size()-1] == '=')
49       b64 = b64.substr(0, b64.size() - 1);
50 
51    for(size_t i = 0; i != b64.size(); ++i)
52       b64[i] = OPENBSD_BASE64_SUB[static_cast<byte>(b64[i])];
53 
54    return b64;
55    }
56 
bcrypt_base64_decode(std::string input)57 MemoryVector<byte> bcrypt_base64_decode(std::string input)
58    {
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
82    };
83 
84    for(size_t i = 0; i != input.size(); ++i)
85       input[i] = OPENBSD_BASE64_SUB[static_cast<byte>(input[i])];
86 
87    return base64_decode(input);
88    }
89 
make_bcrypt(const std::string & pass,const MemoryRegion<byte> & salt,u16bit work_factor)90 std::string make_bcrypt(const std::string& pass,
91                         const MemoryRegion<byte>& salt,
92                         u16bit work_factor)
93    {
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
98    };
99 
100    MemoryVector<byte> ctext(magic, 24);
101 
102    Blowfish blowfish;
103 
104    // Include the trailing NULL byte
105    blowfish.eks_key_schedule(reinterpret_cast<const byte*>(pass.c_str()),
106                              pass.length() + 1,
107                              salt,
108                              work_factor);
109 
110    for(size_t i = 0; i != 64; ++i)
111       blowfish.encrypt_n(&ctext[0], &ctext[0], 3);
112 
113    std::string salt_b64 = bcrypt_base64_encode(&salt[0], salt.size());
114 
115    return "$2a$" + to_string(work_factor, 2) + "$" + salt_b64.substr(0, 22) +
116              bcrypt_base64_encode(&ctext[0], ctext.size() - 1);
117    }
118 
119 }
120 
generate_bcrypt(const std::string & pass,RandomNumberGenerator & rng,u16bit work_factor)121 std::string generate_bcrypt(const std::string& pass,
122                             RandomNumberGenerator& rng,
123                             u16bit work_factor)
124    {
125    return make_bcrypt(pass, rng.random_vec(16), work_factor);
126    }
127 
check_bcrypt(const std::string & pass,const std::string & hash)128 bool check_bcrypt(const std::string& pass, const std::string& hash)
129    {
130    if(hash.size() != 60 ||
131       hash[0] != '$' || hash[1] != '2' || hash[2] != 'a' ||
132       hash[3] != '$' || hash[6] != '$')
133       {
134       return false;
135       }
136 
137    const u16bit workfactor = to_u32bit(hash.substr(4, 2));
138 
139    MemoryVector<byte> salt = bcrypt_base64_decode(hash.substr(7, 22));
140 
141    const std::string compare = make_bcrypt(pass, salt, workfactor);
142 
143    return (hash == compare);
144    }
145 
146 }
147