diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/constructs/passhash/info.txt | 3 | ||||
-rw-r--r-- | src/constructs/passhash/passhash.cpp | 42 | ||||
-rw-r--r-- | src/constructs/passhash/passhash.h | 2 |
3 files changed, 31 insertions, 16 deletions
diff --git a/src/constructs/passhash/info.txt b/src/constructs/passhash/info.txt index b2f54ef0a..fdc68deac 100644 --- a/src/constructs/passhash/info.txt +++ b/src/constructs/passhash/info.txt @@ -1,9 +1,8 @@ define PASSHASH <requires> +libstate pbkdf2 -sha2 -hmac rng base64 </requires> diff --git a/src/constructs/passhash/passhash.cpp b/src/constructs/passhash/passhash.cpp index dade15ddb..d3571808d 100644 --- a/src/constructs/passhash/passhash.cpp +++ b/src/constructs/passhash/passhash.cpp @@ -6,9 +6,9 @@ */ #include <botan/passhash.h> +#include <botan/loadstor.h> +#include <botan/libstate.h> #include <botan/pbkdf2.h> -#include <botan/hmac.h> -#include <botan/sha2_64.h> #include <botan/base64.h> #include <botan/pipe.h> @@ -16,17 +16,21 @@ namespace Botan { namespace { -const u32bit SALT_BYTES = 8; // 64 bits of salt +const std::string MAGIC_PREFIX = "$9$"; +const u32bit SALT_BYTES = 10; // 80 bits of salt const u32bit PBKDF_OUTPUT_LEN = 15; // 112 bits output const u32bit WORK_FACTOR_SCALE = 10000; +const std::string PBKDF_MAC = "HMAC(SHA-1)"; } std::string password_hash(const std::string& pass, RandomNumberGenerator& rng, - byte work_factor) + u16bit work_factor) { - PKCS5_PBKDF2 kdf(new HMAC(new SHA_512)); + PKCS5_PBKDF2 kdf( + global_state().algorithm_factory().make_mac(PBKDF_MAC) + ); SecureVector<byte> salt(SALT_BYTES); rng.randomize(&salt[0], salt.size()); @@ -40,40 +44,52 @@ std::string password_hash(const std::string& pass, Pipe pipe(new Base64_Encoder); pipe.start_msg(); - pipe.write(work_factor); + pipe.write(get_byte(0, work_factor)); + pipe.write(get_byte(1, work_factor)); pipe.write(salt); pipe.write(pbkdf2_output); pipe.end_msg(); - return pipe.read_all_as_string(); + return MAGIC_PREFIX + pipe.read_all_as_string(); } bool password_hash_ok(const std::string& pass, const std::string& hash) { + if(hash.size() != (36 + MAGIC_PREFIX.size())) + return false; + + for(size_t i = 0; i != MAGIC_PREFIX.size(); ++i) + if(hash[i] != MAGIC_PREFIX[i]) + return false; + Pipe pipe(new Base64_Decoder); pipe.start_msg(); - pipe.write(hash); + pipe.write(hash.c_str() + MAGIC_PREFIX.size()); pipe.end_msg(); SecureVector<byte> bin = pipe.read_all(); - if(bin.size() != (1 + PBKDF_OUTPUT_LEN + SALT_BYTES)) + const u32bit WORKFACTOR_BYTES = 2; + + if(bin.size() != (WORKFACTOR_BYTES + PBKDF_OUTPUT_LEN + SALT_BYTES)) return false; - u32bit kdf_iterations = WORK_FACTOR_SCALE * bin[0]; + u32bit kdf_iterations = WORK_FACTOR_SCALE * load_be<u16bit>(bin, 0); if(kdf_iterations == 0) return false; - PKCS5_PBKDF2 kdf(new HMAC(new SHA_512)); + PKCS5_PBKDF2 kdf( + global_state().algorithm_factory().make_mac(PBKDF_MAC) + ); SecureVector<byte> cmp = kdf.derive_key( PBKDF_OUTPUT_LEN, pass, - &bin[1], SALT_BYTES, + &bin[WORKFACTOR_BYTES], SALT_BYTES, kdf_iterations).bits_of(); return same_mem(cmp.begin(), - bin.begin() + 1 + SALT_BYTES, + bin.begin() + WORKFACTOR_BYTES + SALT_BYTES, PBKDF_OUTPUT_LEN); } diff --git a/src/constructs/passhash/passhash.h b/src/constructs/passhash/passhash.h index e3b0419fe..9676ff85e 100644 --- a/src/constructs/passhash/passhash.h +++ b/src/constructs/passhash/passhash.h @@ -20,7 +20,7 @@ namespace Botan { */ std::string BOTAN_DLL password_hash(const std::string& password, RandomNumberGenerator& rng, - byte work_factor = 10); + u16bit work_factor = 10); /** * Check a previously created password hash |