MySQL 8.3.0
Source Code Documentation
kdf_sha_crypt.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2018, 2023, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23*/
24#ifndef ROUTER_KDF_SHA_CRYPT_INCLUDED
25#define ROUTER_KDF_SHA_CRYPT_INCLUDED
26
27#include <string>
28#include <utility> // std::pair
29#include <vector>
30
31#include "digest.h"
32#include "mcf_error.h"
34
35/**
36 * sha256_crypt and sha512_crypt are SHA based crypt() key derivation functions.
37 * @see https://www.akkadia.org/drepper/SHA-crypt.txt
38 *
39 * caching_sha2_password is key derivation function taken from an internal
40 * MySQL authentication mechanism
41 */
43 public:
44 enum class Type { Sha256, Sha512, CachingSha2Password };
45 static std::string salt();
46 static std::string derive(Type digest, unsigned long rounds,
47 const std::string &salt,
48 const std::string &password);
49
50 private:
51 /**
52 * crypt specific base64 encode.
53 *
54 * different alphabet than RFC4648
55 */
56 static std::string base64_encode(const std::vector<uint8_t> &data);
57};
58
60 public:
62
63 static std::pair<bool, std::string> name(Type type) noexcept {
64 switch (type) {
65 case Type::Sha256:
66 return std::make_pair(true, kTypeSha256);
67 case Type::Sha512:
68 return std::make_pair(true, kTypeSha512);
70 return std::make_pair(true, kTypeCachingSha2Password);
71 }
72
73 return std::make_pair(false, std::string{});
74 }
75
76 static std::pair<bool, Type> type(const std::string &name) noexcept {
77 if (name == kTypeSha256) {
78 return std::make_pair(true, Type::Sha256);
79 } else if (name == kTypeSha512) {
80 return std::make_pair(true, Type::Sha512);
81 } else if (name == kTypeCachingSha2Password) {
82 return std::make_pair(true, Type::CachingSha2Password);
83 }
84
85 return std::make_pair(false, Type{});
86 }
87
88 static bool supports_name(const std::string &name) noexcept {
89 if (name == kTypeSha256) {
90 return true;
91 } else if (name == kTypeSha512) {
92 return true;
93 } else if (name == kTypeCachingSha2Password) {
94 return true;
95 }
96
97 return false;
98 }
99
100 private:
101 static constexpr char kTypeSha256[] = "5";
102 static constexpr char kTypeSha512[] = "6";
103 static constexpr char kTypeCachingSha2Password[] = "A";
104};
105
106/**
107 * MCF reader/writer for ShaCrypt
108 */
110 public:
113
115
116 /**
117 * number of rounds if no rounds was specified in from_mcf().
118 */
119 static constexpr unsigned long kDefaultRounds = 5000;
120 /**
121 * minimum rounds.
122 */
123 static constexpr unsigned long kMinRounds = 1000;
124 /**
125 * maximum rounds.
126 */
127 static constexpr unsigned long kMaxRounds = 999999999;
128 /**
129 * maximum length of the salt.
130 *
131 * only the first kMaxSaltLength bytes of the salt will be used.
132 */
133 static constexpr size_t kMaxSaltLength = 16;
134
135 ShaCryptMcfAdaptor(Type digest, unsigned long rounds, const std::string &salt,
136 const std::string &checksum)
137 : digest_{digest}, rounds_{rounds}, salt_{salt}, checksum_{checksum} {
138 // limit salt, for caching_sha2_password salt has a fixed length of 20
139 if (digest != Type::CachingSha2Password && salt_.size() > kMaxSaltLength) {
140 salt_.resize(kMaxSaltLength);
141 }
142
143 // limit rounds to allowed range
144 if (rounds_ < kMinRounds) rounds_ = kMinRounds;
145 if (rounds_ > kMaxRounds) rounds_ = kMaxRounds;
146 }
147
148 /**
149 * name of the digest according to MCF.
150 *
151 * - 5 for SHA256
152 * - 6 for SHA512
153 * - A for caching_sha2_password
154 */
155 std::string mcf_digest_name() const {
156 auto r = mcf_type::name(digest());
157 if (r.first) return r.second;
158
159 throw std::invalid_argument("failed to map digest to a name");
160 }
161
162 /**
163 * checksum.
164 *
165 * in crypt-specific base64 encoding
166 */
167 std::string checksum() const { return checksum_; }
168
169 /**
170 * salt.
171 *
172 * @pre must be [a-z0-9]*
173 */
174 std::string salt() const { return salt_; }
175
176 /**
177 *
178 */
179 Type digest() const { return digest_; }
180
181 /**
182 * rounds.
183 *
184 * number of rounds the hash will be applied
185 */
186 unsigned long rounds() const { return rounds_; }
187
188 /**
189 * build ShaCrypt from a MCF notation.
190 *
191 * - ${prefix}$rounds={rounds}${salt}${checksum}
192 * - ${prefix}$rounds={rounds}${salt}
193 * - ${prefix}${salt}${checksum}
194 * - ${prefix}${salt}
195 *
196 * prefix
197 * : [56] (5 is SHA256, 6 is SHA512)
198 *
199 * rounds
200 * : [0-9]+
201 *
202 * salt
203 * : [^$]*
204 *
205 * checksum
206 * : [./a-zA-Z0-0]*
207 */
208 static ShaCryptMcfAdaptor from_mcf(const std::string &data);
209
210 /**
211 * encode to MCF.
212 *
213 * MCF (Modular Crypt Format)
214 */
215 std::string to_mcf() const;
216
217 /**
218 * hash a password into checksum.
219 *
220 * updates checksum
221 */
222 void hash(const std::string &password) {
223 checksum_ = kdf_type::derive(digest_, rounds_, salt_, password);
224 }
225
226 static bool supports_mcf_id(const std::string mcf_id) {
227 return mcf_type::supports_name(mcf_id);
228 }
229
230 static std::error_code validate(const std::string &mcf_line,
231 const std::string &password) {
232 try {
233 auto me = from_mcf(mcf_line);
234 if (kdf_type::derive(me.digest(), me.rounds(), me.salt(), password) ==
235 me.checksum()) {
236 return {};
237 } else {
239 }
240 } catch (const std::exception &) {
241 // treat all exceptions as parse-errors
243 }
244 }
245
246 private:
248 unsigned long rounds_;
249 std::string salt_;
250 std::string checksum_;
251};
252
254 public:
255 static ShaCryptMcfAdaptor from_mcf(const std::string &crypt_data);
256
257 static constexpr unsigned long kCachingSha2SaltLength = 20;
258};
259
260#endif
Definition: kdf_sha_crypt.h:253
static constexpr unsigned long kCachingSha2SaltLength
Definition: kdf_sha_crypt.h:257
static ShaCryptMcfAdaptor from_mcf(const std::string &crypt_data)
Definition: kdf_sha_crypt.cc:124
Definition: authentication.h:42
MCF reader/writer for ShaCrypt.
Definition: kdf_sha_crypt.h:109
static std::error_code validate(const std::string &mcf_line, const std::string &password)
Definition: kdf_sha_crypt.h:230
static bool supports_mcf_id(const std::string mcf_id)
Definition: kdf_sha_crypt.h:226
unsigned long rounds_
Definition: kdf_sha_crypt.h:248
std::string checksum_
Definition: kdf_sha_crypt.h:250
std::string mcf_digest_name() const
name of the digest according to MCF.
Definition: kdf_sha_crypt.h:155
void hash(const std::string &password)
hash a password into checksum.
Definition: kdf_sha_crypt.h:222
std::string salt() const
salt.
Definition: kdf_sha_crypt.h:174
ShaCryptMcfAdaptor(Type digest, unsigned long rounds, const std::string &salt, const std::string &checksum)
Definition: kdf_sha_crypt.h:135
unsigned long rounds() const
rounds.
Definition: kdf_sha_crypt.h:186
Type digest() const
Definition: kdf_sha_crypt.h:179
Type digest_
Definition: kdf_sha_crypt.h:247
std::string salt_
Definition: kdf_sha_crypt.h:249
std::string checksum() const
checksum.
Definition: kdf_sha_crypt.h:167
Definition: kdf_sha_crypt.h:59
static bool supports_name(const std::string &name) noexcept
Definition: kdf_sha_crypt.h:88
static constexpr char kTypeSha512[]
Definition: kdf_sha_crypt.h:102
static constexpr char kTypeSha256[]
Definition: kdf_sha_crypt.h:101
static std::pair< bool, Type > type(const std::string &name) noexcept
Definition: kdf_sha_crypt.h:76
static std::pair< bool, std::string > name(Type type) noexcept
Definition: kdf_sha_crypt.h:63
static constexpr char kTypeCachingSha2Password[]
Definition: kdf_sha_crypt.h:103
sha256_crypt and sha512_crypt are SHA based crypt() key derivation functions.
Definition: kdf_sha_crypt.h:42
Type
Definition: kdf_sha_crypt.h:44
#define HTTP_AUTH_BACKEND_LIB_EXPORT
Definition: http_auth_backend_lib_export.h:15
static int base64_encode(const void *src, size_t src_len, char *dst)
Definition: base64.h:242
@ kPasswordNotMatched
static char * password
Definition: mysql_secure_installation.cc:57
std::error_code make_error_code(DynamicLoaderErrc ec)
make error_code from a DynamicLoaderErrc.
Definition: dynamic_loader.cc:78
Type
Definition: resource_group_basic_types.h:32
const mysql_service_registry_t * r
Definition: pfs_example_plugin_employee.cc:85
case opt name
Definition: sslopt-case.h:32
Constants and functionality that facilitate working with digests.