Botan 3.13.0
Crypto and TLS for C&
pwdhash.h
Go to the documentation of this file.
1/*
2* (C) 2018 Ribose Inc
3*
4* Botan is released under the Simplified BSD License (see license.txt)
5*/
6
7#ifndef BOTAN_PWDHASH_H_
8#define BOTAN_PWDHASH_H_
9
10#include <botan/types.h>
11#include <memory>
12#include <optional>
13#include <span>
14#include <string>
15#include <vector>
16
17#if !defined(BOTAN_IS_BEING_BUILT)
18 #include <chrono>
19#endif
20
21namespace Botan {
22
23/**
24* Base class for password based key derivation functions.
25*
26* Converts a password into a key using a salt and iterated hashing to
27* make brute force attacks harder.
28*/
29class BOTAN_PUBLIC_API(2, 8) PasswordHash /* NOLINT(*-special-member-functions) */ {
30 public:
31 virtual ~PasswordHash() = default;
32
33 /**
34 * Return a free-form string identifying the algorithm and parameters
35 */
36 virtual std::string to_string() const = 0;
37
38 /**
39 * Most password hashes have some notion of iterations.
40 */
41 virtual size_t iterations() const = 0;
42
43 /**
44 * Some password hashing algorithms have a parameter which controls how
45 * much memory is used. If not supported by some algorithm, returns 0.
46 */
47 virtual size_t memory_param() const { return 0; }
48
49 /**
50 * Some password hashing algorithms have a parallelism parameter.
51 * If the algorithm does not support this notion, then the
52 * function returns zero. This allows distinguishing between a
53 * password hash which just does not support parallel operation,
54 * vs one that does support parallel operation but which has been
55 * configured to use a single lane.
56 */
57 virtual size_t parallelism() const { return 0; }
58
59 /**
60 * Returns an estimate of the total number of bytes required to perform this
61 * key derivation.
62 *
63 * If this algorithm uses a small and constant amount of memory, with no
64 * effort made towards being memory hard, this function returns 0.
65 */
66 virtual size_t total_memory_usage() const { return 0; }
67
68 /**
69 * Query if this password hash supports a symmetric key
70 *
71 * @returns true if this password hash supports supplying a key
72 */
73 virtual bool supports_keyed_operation() const { return false; }
74
75 /**
76 * Query if this password hash supports associated data
77 *
78 * @returns true if this password hash supports supplying associated data
79 */
80 virtual bool supports_associated_data() const { return false; }
81
82 /**
83 * Hash a password into a bitstring
84 *
85 * Derive a key from the specified @p password and @p salt, placing it into
86 * @p out.
87 *
88 * @param out a span where the derived key will be placed
89 * @param password the password to derive the key from
90 * @param salt a randomly chosen salt
91 *
92 * This function is const, but is not thread safe. Different threads should
93 * either use unique objects, or serialize all access.
94 */
95 void hash(std::span<uint8_t> out, std::string_view password, std::span<const uint8_t> salt) const {
96 this->derive_key(out.data(), out.size(), password.data(), password.size(), salt.data(), salt.size());
97 }
98
99 /**
100 * Hash a password into a bitstring
101 *
102 * Derive a key from the specified @p password, @p salt, @p
103 * associated_data, and secret @p key, placing it into @p out. The
104 * @p associated_data and @p key are both allowed to be empty. Currently
105 * non-empty AD/key is only supported with Argon2.
106 *
107 * @param out a span where the derived key will be placed
108 * @param password the password to derive the key from
109 * @param salt a randomly chosen salt
110 * @param associated_data some additional data
111 * @param key a secret key
112 *
113 * This function is const, but is not thread safe. Different threads should
114 * either use unique objects, or serialize all access.
115 */
116 void hash(std::span<uint8_t> out,
117 std::string_view password,
118 std::span<const uint8_t> salt,
119 std::span<const uint8_t> associated_data,
120 std::span<const uint8_t> key) const {
121 this->derive_key(out.data(),
122 out.size(),
123 password.data(),
124 password.size(),
125 salt.data(),
126 salt.size(),
127 associated_data.data(),
128 associated_data.size(),
129 key.data(),
130 key.size());
131 }
132
133 /**
134 * Derive a key from a password
135 *
136 * @param out buffer to store the derived key, must be of out_len bytes
137 * @param out_len the desired length of the key to produce
138 * @param password the password to derive the key from
139 * @param password_len the length of password in bytes
140 * @param salt a randomly chosen salt
141 * @param salt_len length of salt in bytes
142 *
143 * This function is const, but is not thread safe. Different threads should
144 * either use unique objects, or serialize all access.
145 */
146 virtual void derive_key(uint8_t out[],
147 size_t out_len,
148 const char* password,
149 size_t password_len,
150 const uint8_t salt[],
151 size_t salt_len) const = 0;
152
153 /**
154 * Derive a key from a password plus additional data and/or a secret key
155 *
156 * Currently this is only supported for Argon2. Using a non-empty AD or key
157 * with other algorithms will cause a Not_Implemented exception.
158 *
159 * @param out buffer to store the derived key, must be of out_len bytes
160 * @param out_len the desired length of the key to produce
161 * @param password the password to derive the key from
162 * @param password_len the length of password in bytes
163 * @param salt a randomly chosen salt
164 * @param salt_len length of salt in bytes
165 * @param ad some additional data
166 * @param ad_len length of ad in bytes
167 * @param key a secret key
168 * @param key_len length of key in bytes
169 *
170 * This function is const, but is not thread safe. Different threads should
171 * either use unique objects, or serialize all access.
172 */
173 virtual void derive_key(uint8_t out[],
174 size_t out_len,
175 const char* password,
176 size_t password_len,
177 const uint8_t salt[],
178 size_t salt_len,
179 const uint8_t ad[],
180 size_t ad_len,
181 const uint8_t key[],
182 size_t key_len) const;
183};
184
185/**
186* A factory for PasswordHash parameter sets of a particular algorithm
187*/
188class BOTAN_PUBLIC_API(2, 8) PasswordHashFamily /* NOLINT(*-special-member-functions) */ {
189 public:
190 /**
191 * Create an instance based on a name
192 * If provider is empty then best available is chosen.
193 * @param algo_spec algorithm name
194 * @param provider provider implementation to choose
195 * @return a null pointer if the algo/provider combination cannot be found
196 */
197 static std::unique_ptr<PasswordHashFamily> create(std::string_view algo_spec, std::string_view provider = "");
198
199 /**
200 * Create an instance based on a name, or throw if the
201 * algo/provider combination cannot be found. If provider is
202 * empty then best available is chosen.
203 */
204 static std::unique_ptr<PasswordHashFamily> create_or_throw(std::string_view algo_spec,
205 std::string_view provider = "");
206
207 /**
208 * List the providers available for a given password hash
209 * @return list of available providers for this algorithm, empty if not available
210 */
211 static std::vector<std::string> providers(std::string_view algo_spec);
212
213 virtual ~PasswordHashFamily() = default;
214
215 /**
216 * Return the name of this password hash family
217 * @return name of this PasswordHash
218 */
219 virtual std::string name() const = 0;
220
221 /**
222 * Return a new parameter set tuned for this machine
223 *
224 * Return a password hash instance tuned to run for approximately @p msec
225 * milliseconds when producing an output of length @p output_length.
226 * (Accuracy may vary, use the command line utility ``botan pbkdf_tune`` to
227 * check.)
228 *
229 * The parameters will be selected to use at most @p max_memory_usage_mb
230 * megabytes of memory, or if left as zero any size is allowed.
231 *
232 * This function works by running a short tuning loop to estimate the
233 * performance of the algorithm, then scaling the parameters appropriately
234 * to hit the target size. The length of time the tuning loop runs can be
235 * controlled using the @p tuning_msec parameter.
236 *
237 * @param output_length how long the output length will be
238 * @param desired_runtime_msec the desired execution time in milliseconds
239 *
240 * @param max_memory_usage_mb some password hash functions can use a
241 * tunable amount of memory, in this case max_memory_usage limits the
242 * amount of RAM the returned parameters will require, in mebibytes (2**20
243 * bytes). It may require some small amount above the request. Set to nullopt
244 * to place no limit at all.
245 * @param tuning_msec how long to run the tuning loop
246 */
247 virtual std::unique_ptr<PasswordHash> tune_params(size_t output_length,
248 uint64_t desired_runtime_msec,
249 std::optional<size_t> max_memory_usage_mb = {},
250 uint64_t tuning_msec = 10) const = 0;
251
252#if !defined(BOTAN_IS_BEING_BUILT)
253 /**
254 * Return a new parameter set tuned for this machine
255 *
256 * Return a password hash instance tuned to run for approximately @p msec
257 * milliseconds when producing an output of length @p output_length.
258 * (Accuracy may vary, use the command line utility ``botan pbkdf_tune`` to
259 * check.)
260 *
261 * The parameters will be selected to use at most @p max_memory_usage_mb
262 * megabytes of memory, or if left as zero any size is allowed.
263 *
264 * This function works by running a short tuning loop to estimate the
265 * performance of the algorithm, then scaling the parameters appropriately
266 * to hit the target size. The length of time the tuning loop runs can be
267 * controlled using the @p tuning_msec parameter.
268 *
269 * @param output_length how long the output length will be
270 * @param msec the desired execution time in milliseconds
271 *
272 * @param max_memory_usage_mb some password hash functions can use a
273 * tunable amount of memory, in this case max_memory_usage limits the
274 * amount of RAM the returned parameters will require, in mebibytes (2**20
275 * bytes). It may require some small amount above the request. Set to zero
276 * to place no limit at all.
277 * @param tuning_msec how long to run the tuning loop
278 *
279 * TODO(Botan4) remove this
280 */
281 BOTAN_DEPRECATED("Use tune_params instead")
282 std::unique_ptr<PasswordHash> tune(size_t output_length,
283 std::chrono::milliseconds msec,
284 size_t max_memory_usage_mb = 0,
285 std::chrono::milliseconds tuning_msec = std::chrono::milliseconds(10)) const {
286 std::optional<size_t> max_memory_opt;
287 if(max_memory_usage_mb > 0) {
288 max_memory_opt = max_memory_usage_mb;
289 }
290
291 return this->tune_params(output_length,
292 static_cast<uint64_t>(msec.count()),
293 max_memory_opt,
294 static_cast<uint64_t>(tuning_msec.count()));
295 }
296#endif
297 /**
298 * Return some default parameter set for this PBKDF that should be good
299 * enough for most users. The value returned may change over time as
300 * processing power and attacks improve.
301 */
302 virtual std::unique_ptr<PasswordHash> default_params() const = 0;
303
304 /**
305 * Return a parameter chosen based on a rough approximation with the
306 * specified iteration count. The exact value this returns for a particular
307 * algorithm may change from over time. Think of it as an alternative to
308 * tune, where time is expressed in terms of PBKDF2 iterations rather than
309 * milliseconds.
310 */
311 virtual std::unique_ptr<PasswordHash> from_iterations(size_t iterations) const = 0;
312
313 /**
314 * Create a password hash using some scheme specific format. Parameters are as follows:
315 * - For PBKDF2, PGP-S2K, and Bcrypt-PBKDF, i1 is iterations
316 * - Scrypt uses N, r, p for i{1-3}
317 * - Argon2 family uses memory (in KB), iterations, and parallelism for i{1-3}
318 * - PKCS12-KDF uses iterations for i1 (the hash and id are fixed by the family name,
319 * e.g. "PKCS12-KDF(SHA-256,1)")
320 *
321 * All unneeded parameters should be set to 0 or left blank.
322 */
323 virtual std::unique_ptr<PasswordHash> from_params(size_t i1, size_t i2 = 0, size_t i3 = 0) const = 0;
324};
325
326} // namespace Botan
327
328#endif
#define BOTAN_PUBLIC_API(maj, min)
Definition api.h:21
#define BOTAN_DEPRECATED(msg)
Definition api.h:73
virtual std::string name() const =0
static std::unique_ptr< PasswordHashFamily > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition pwdhash.cpp:123
virtual std::unique_ptr< PasswordHash > from_iterations(size_t iterations) const =0
static std::vector< std::string > providers(std::string_view algo_spec)
Definition pwdhash.cpp:131
virtual ~PasswordHashFamily()=default
virtual std::unique_ptr< PasswordHash > default_params() const =0
static std::unique_ptr< PasswordHashFamily > create(std::string_view algo_spec, std::string_view provider="")
Definition pwdhash.cpp:58
virtual std::unique_ptr< PasswordHash > from_params(size_t i1, size_t i2=0, size_t i3=0) const =0
std::unique_ptr< PasswordHash > tune(size_t output_length, std::chrono::milliseconds msec, size_t max_memory_usage_mb=0, std::chrono::milliseconds tuning_msec=std::chrono::milliseconds(10)) const
Definition pwdhash.h:282
virtual std::unique_ptr< PasswordHash > tune_params(size_t output_length, uint64_t desired_runtime_msec, std::optional< size_t > max_memory_usage_mb={}, uint64_t tuning_msec=10) const =0
void hash(std::span< uint8_t > out, std::string_view password, std::span< const uint8_t > salt, std::span< const uint8_t > associated_data, std::span< const uint8_t > key) const
Definition pwdhash.h:116
virtual bool supports_keyed_operation() const
Definition pwdhash.h:73
void hash(std::span< uint8_t > out, std::string_view password, std::span< const uint8_t > salt) const
Definition pwdhash.h:95
virtual size_t total_memory_usage() const
Definition pwdhash.h:66
virtual size_t parallelism() const
Definition pwdhash.h:57
virtual size_t iterations() const =0
virtual ~PasswordHash()=default
virtual void derive_key(uint8_t out[], size_t out_len, const char *password, size_t password_len, const uint8_t salt[], size_t salt_len) const =0
virtual bool supports_associated_data() const
Definition pwdhash.h:80
virtual size_t memory_param() const
Definition pwdhash.h:47
virtual std::string to_string() const =0