Botan 1.10.17
bcrypt.cpp
Go to the documentation of this file.
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
14namespace Botan {
15
16namespace {
17
18std::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
57MemoryVector<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
90std::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
121std::string generate_bcrypt(const std::string& pass,
123 u16bit work_factor)
124 {
125 return make_bcrypt(pass, rng.random_vec(16), work_factor);
126 }
127
128bool 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}
void eks_key_schedule(const byte key[], size_t key_length, const byte salt[16], size_t workfactor)
Definition blowfish.cpp:111
SecureVector< byte > random_vec(size_t bytes)
Definition rng.h:40
std::string generate_bcrypt(const std::string &pass, RandomNumberGenerator &rng, u16bit work_factor)
Definition bcrypt.cpp:121
std::string to_string(u64bit n, size_t min_len)
Definition parsing.cpp:42
u32bit to_u32bit(const std::string &number)
Definition parsing.cpp:18
size_t base64_encode(char out[], const byte in[], size_t input_length, size_t &input_consumed, bool final_inputs)
Definition base64.cpp:36
unsigned short u16bit
Definition types.h:27
size_t base64_decode(byte output[], const char input[], size_t input_length, size_t &input_consumed, bool final_inputs, bool ignore_ws)
Definition base64.cpp:100
bool check_bcrypt(const std::string &pass, const std::string &hash)
Definition bcrypt.cpp:128