aboutsummaryrefslogtreecommitdiffstats
path: root/src/passhash/passhash9
diff options
context:
space:
mode:
authorlloyd <[email protected]>2011-02-17 19:41:49 +0000
committerlloyd <[email protected]>2011-02-17 19:41:49 +0000
commit20b9d66dc60595e685d99f59a7ef306074d8e0b1 (patch)
treed3f743ce470368cf6764c126021c5aa726267504 /src/passhash/passhash9
parent88a892707f05625cbcf0c8cc4b3e0ed7852967b5 (diff)
Move password hashing schemes to src/passhash
Set the upper limit on bcrypt hashing to workfactor 18, which takes about 25 seconds to run on my desktop machine.
Diffstat (limited to 'src/passhash/passhash9')
-rw-r--r--src/passhash/passhash9/info.txt9
-rw-r--r--src/passhash/passhash9/passhash9.cpp147
-rw-r--r--src/passhash/passhash9/passhash9.h51
3 files changed, 207 insertions, 0 deletions
diff --git a/src/passhash/passhash9/info.txt b/src/passhash/passhash9/info.txt
new file mode 100644
index 000000000..f96809f29
--- /dev/null
+++ b/src/passhash/passhash9/info.txt
@@ -0,0 +1,9 @@
+define PASSHASH9
+
+<requires>
+libstate
+pbkdf2
+rng
+base64
+</requires>
+
diff --git a/src/passhash/passhash9/passhash9.cpp b/src/passhash/passhash9/passhash9.cpp
new file mode 100644
index 000000000..e5f379052
--- /dev/null
+++ b/src/passhash/passhash9/passhash9.cpp
@@ -0,0 +1,147 @@
+/*
+* Passhash9 Password Hashing
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/passhash9.h>
+#include <botan/loadstor.h>
+#include <botan/libstate.h>
+#include <botan/pbkdf2.h>
+#include <botan/b64_filt.h>
+#include <botan/pipe.h>
+
+namespace Botan {
+
+namespace {
+
+const std::string MAGIC_PREFIX = "$9$";
+
+const size_t WORKFACTOR_BYTES = 2;
+const size_t ALGID_BYTES = 1;
+const size_t SALT_BYTES = 12; // 96 bits of salt
+const size_t PASSHASH9_PBKDF_OUTPUT_LEN = 24; // 192 bits output
+
+const byte PASSHASH9_DEFAULT_ALGO = 0; // HMAC(SHA-1)
+
+const size_t WORK_FACTOR_SCALE = 10000;
+
+MessageAuthenticationCode* get_pbkdf_prf(byte alg_id)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ try
+ {
+ if(alg_id == 0)
+ return af.make_mac("HMAC(SHA-1)");
+ else if(alg_id == 1)
+ return af.make_mac("HMAC(SHA-256)");
+ else if(alg_id == 2)
+ return af.make_mac("CMAC(Blowfish)");
+ }
+ catch(Algorithm_Not_Found) {}
+
+ return 0;
+ }
+
+}
+
+std::string generate_passhash9(const std::string& pass,
+ RandomNumberGenerator& rng,
+ u16bit work_factor)
+ {
+ return generate_passhash9(pass, PASSHASH9_DEFAULT_ALGO, rng, work_factor);
+ }
+
+std::string generate_passhash9(const std::string& pass,
+ byte alg_id,
+ RandomNumberGenerator& rng,
+ u16bit work_factor)
+ {
+ MessageAuthenticationCode* prf = get_pbkdf_prf(alg_id);
+
+ if(!prf)
+ throw Invalid_Argument("Passhash9: Algorithm id " + to_string(alg_id) +
+ " is not defined");
+
+ PKCS5_PBKDF2 kdf(prf); // takes ownership of pointer
+
+ SecureVector<byte> salt(SALT_BYTES);
+ rng.randomize(&salt[0], salt.size());
+
+ const size_t kdf_iterations = WORK_FACTOR_SCALE * work_factor;
+
+ SecureVector<byte> pbkdf2_output =
+ kdf.derive_key(PASSHASH9_PBKDF_OUTPUT_LEN,
+ pass,
+ &salt[0], salt.size(),
+ kdf_iterations).bits_of();
+
+ Pipe pipe(new Base64_Encoder);
+ pipe.start_msg();
+ pipe.write(alg_id);
+ 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 MAGIC_PREFIX + pipe.read_all_as_string();
+ }
+
+bool check_passhash9(const std::string& pass, const std::string& hash)
+ {
+ const size_t BINARY_LENGTH =
+ ALGID_BYTES +
+ WORKFACTOR_BYTES +
+ PASSHASH9_PBKDF_OUTPUT_LEN +
+ SALT_BYTES;
+
+ const size_t BASE64_LENGTH =
+ MAGIC_PREFIX.size() + (BINARY_LENGTH * 8) / 6;
+
+ if(hash.size() != BASE64_LENGTH)
+ 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.c_str() + MAGIC_PREFIX.size());
+ pipe.end_msg();
+
+ SecureVector<byte> bin = pipe.read_all();
+
+ if(bin.size() != BINARY_LENGTH)
+ return false;
+
+ byte alg_id = bin[0];
+
+ const size_t kdf_iterations =
+ WORK_FACTOR_SCALE * load_be<u16bit>(&bin[ALGID_BYTES], 0);
+
+ if(kdf_iterations == 0)
+ return false;
+
+ MessageAuthenticationCode* pbkdf_prf = get_pbkdf_prf(alg_id);
+
+ if(pbkdf_prf == 0)
+ return false; // unknown algorithm, reject
+
+ PKCS5_PBKDF2 kdf(pbkdf_prf); // takes ownership of pointer
+
+ SecureVector<byte> cmp = kdf.derive_key(
+ PASSHASH9_PBKDF_OUTPUT_LEN,
+ pass,
+ &bin[ALGID_BYTES + WORKFACTOR_BYTES], SALT_BYTES,
+ kdf_iterations).bits_of();
+
+ return same_mem(&cmp[0],
+ &bin[ALGID_BYTES + WORKFACTOR_BYTES + SALT_BYTES],
+ PASSHASH9_PBKDF_OUTPUT_LEN);
+ }
+
+}
diff --git a/src/passhash/passhash9/passhash9.h b/src/passhash/passhash9/passhash9.h
new file mode 100644
index 000000000..92cc391dc
--- /dev/null
+++ b/src/passhash/passhash9/passhash9.h
@@ -0,0 +1,51 @@
+/*
+* Passhash9 Password Hashing
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_PASSHASH9_H__
+#define BOTAN_PASSHASH9_H__
+
+#include <botan/rng.h>
+
+namespace Botan {
+
+/**
+* Create a password hash using PBKDF2
+* @param password the password
+* @param rng a random number generator
+* @param work_factor how much work to do to slow down guessing attacks
+*/
+std::string BOTAN_DLL generate_passhash9(const std::string& password,
+ RandomNumberGenerator& rng,
+ u16bit work_factor = 10);
+
+/**
+* Create a password hash using PBKDF2
+* @param password the password
+* @param alg_id specifies which PRF to use with PBKDF2
+* 0 is HMAC(SHA-1)
+* 1 is HMAC(SHA-256)
+* 2 is CMAC(Blowfish)
+* all other values are currently undefined
+* @param rng a random number generator
+* @param work_factor how much work to do to slow down guessing attacks
+*/
+std::string BOTAN_DLL generate_passhash9(const std::string& password,
+ byte alg_id,
+ RandomNumberGenerator& rng,
+ u16bit work_factor = 10);
+
+/**
+* Check a previously created password hash
+* @param password the password to check against
+* @param hash the stored hash to check against
+*/
+bool BOTAN_DLL check_passhash9(const std::string& password,
+ const std::string& hash);
+
+}
+
+#endif