diff options
author | lloyd <[email protected]> | 2010-02-01 17:28:20 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2010-02-01 17:28:20 +0000 |
commit | 121ca16daa158315682373213e150d9c18c28cdb (patch) | |
tree | 3dc90121a407ff31a89aa1d24632447b9993ccaa /src/constructs/passhash/passhash.cpp | |
parent | 05a9ad7281fb528636534a669db3ba8ae15b1d3b (diff) |
Password hashing is a pretty useful service, really. Move the guts of
the passhash example to the library. Support variable work factors;
default work factor of 10 takes about half a second to do one password
on my Core2. Switch to using SHA-512 instead of SHA-1 in PBKDF2. To keep
the output evenly sized for base64 purposes, reduce PBKDF2 output size by
one byte (to 112 bits).
Diffstat (limited to 'src/constructs/passhash/passhash.cpp')
-rw-r--r-- | src/constructs/passhash/passhash.cpp | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/constructs/passhash/passhash.cpp b/src/constructs/passhash/passhash.cpp new file mode 100644 index 000000000..dade15ddb --- /dev/null +++ b/src/constructs/passhash/passhash.cpp @@ -0,0 +1,80 @@ +/* +* Password Hashing +* (C) 2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/passhash.h> +#include <botan/pbkdf2.h> +#include <botan/hmac.h> +#include <botan/sha2_64.h> +#include <botan/base64.h> +#include <botan/pipe.h> + +namespace Botan { + +namespace { + +const u32bit SALT_BYTES = 8; // 64 bits of salt +const u32bit PBKDF_OUTPUT_LEN = 15; // 112 bits output +const u32bit WORK_FACTOR_SCALE = 10000; + +} + +std::string password_hash(const std::string& pass, + RandomNumberGenerator& rng, + byte work_factor) + { + PKCS5_PBKDF2 kdf(new HMAC(new SHA_512)); + + SecureVector<byte> salt(SALT_BYTES); + rng.randomize(&salt[0], salt.size()); + + u32bit kdf_iterations = WORK_FACTOR_SCALE * work_factor; + + SecureVector<byte> pbkdf2_output = + kdf.derive_key(PBKDF_OUTPUT_LEN, pass, + &salt[0], salt.size(), + kdf_iterations).bits_of(); + + Pipe pipe(new Base64_Encoder); + pipe.start_msg(); + pipe.write(work_factor); + pipe.write(salt); + pipe.write(pbkdf2_output); + pipe.end_msg(); + + return pipe.read_all_as_string(); + } + +bool password_hash_ok(const std::string& pass, const std::string& hash) + { + Pipe pipe(new Base64_Decoder); + pipe.start_msg(); + pipe.write(hash); + pipe.end_msg(); + + SecureVector<byte> bin = pipe.read_all(); + + if(bin.size() != (1 + PBKDF_OUTPUT_LEN + SALT_BYTES)) + return false; + + u32bit kdf_iterations = WORK_FACTOR_SCALE * bin[0]; + + if(kdf_iterations == 0) + return false; + + PKCS5_PBKDF2 kdf(new HMAC(new SHA_512)); + + SecureVector<byte> cmp = kdf.derive_key( + PBKDF_OUTPUT_LEN, pass, + &bin[1], SALT_BYTES, + kdf_iterations).bits_of(); + + return same_mem(cmp.begin(), + bin.begin() + 1 + SALT_BYTES, + PBKDF_OUTPUT_LEN); + } + +} |