aboutsummaryrefslogtreecommitdiffstats
path: root/src/block/blowfish
diff options
context:
space:
mode:
authorlloyd <[email protected]>2011-02-16 21:45:13 +0000
committerlloyd <[email protected]>2011-02-16 21:45:13 +0000
commit88a892707f05625cbcf0c8cc4b3e0ed7852967b5 (patch)
treeb63eb83222d4ebbe9d705f901f915c6f4a65bff9 /src/block/blowfish
parentd996f15128ff12fb268f342cbbc0a855666caae4 (diff)
Add support for bcrypt, the Blowfish-based password hashing scheme
used in OpenBSD. Tested as compatible with a common Java implementation (http://www.mindrot.org/projects/jBCrypt/)
Diffstat (limited to 'src/block/blowfish')
-rw-r--r--src/block/blowfish/blowfish.cpp52
-rw-r--r--src/block/blowfish/blowfish.h19
2 files changed, 64 insertions, 7 deletions
diff --git a/src/block/blowfish/blowfish.cpp b/src/block/blowfish/blowfish.cpp
index ea227e93e..6610decd8 100644
--- a/src/block/blowfish/blowfish.cpp
+++ b/src/block/blowfish/blowfish.cpp
@@ -1,6 +1,6 @@
/*
* Blowfish
-* (C) 1999-2009 Jack Lloyd
+* (C) 1999-2011 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -87,20 +87,61 @@ void Blowfish::key_schedule(const byte key[], size_t length)
{
clear();
+ const byte null_salt[16] = { 0 };
+
+ key_expansion(key, length, null_salt);
+ }
+
+void Blowfish::key_expansion(const byte key[],
+ size_t length,
+ const byte salt[16])
+ {
for(size_t i = 0, j = 0; i != 18; ++i, j += 4)
P[i] ^= make_u32bit(key[(j ) % length], key[(j+1) % length],
key[(j+2) % length], key[(j+3) % length]);
u32bit L = 0, R = 0;
- generate_sbox(P, L, R);
- generate_sbox(S, L, R);
+ generate_sbox(P, L, R, salt, 0);
+ generate_sbox(S, L, R, salt, 2);
+ }
+
+/*
+* Modified key schedule used for bcrypt password hashing
+*/
+void Blowfish::eks_key_schedule(const byte key[], size_t length,
+ const byte salt[16], size_t workfactor)
+ {
+ if(length == 0 || length >= 56)
+ throw Invalid_Key_Length("EKSBlowfish", length);
+
+ if(workfactor == 0)
+ throw std::invalid_argument("Bcrypt work factor must be at least 1");
+
+ if(workfactor > 24) // ok?
+ throw std::invalid_argument("Requested Bcrypt work factor too large");
+
+ clear();
+
+ const byte null_salt[16] = { 0 };
+
+ key_expansion(key, length, salt);
+
+ const size_t rounds = 1 << workfactor;
+
+ for(size_t r = 0; r != rounds; ++r)
+ {
+ key_expansion(key, length, null_salt);
+ key_expansion(salt, 16, null_salt);
+ }
}
/*
* Generate one of the Sboxes
*/
void Blowfish::generate_sbox(MemoryRegion<u32bit>& box,
- u32bit& L, u32bit& R) const
+ u32bit& L, u32bit& R,
+ const byte salt[16],
+ size_t salt_off) const
{
const u32bit* S1 = &S[0];
const u32bit* S2 = &S[256];
@@ -109,6 +150,9 @@ void Blowfish::generate_sbox(MemoryRegion<u32bit>& box,
for(size_t i = 0; i != box.size(); i += 2)
{
+ L ^= load_be<u32bit>(salt, (i + salt_off) % 4);
+ R ^= load_be<u32bit>(salt, (i + salt_off + 1) % 4);
+
for(size_t j = 0; j != 16; j += 2)
{
L ^= P[j];
diff --git a/src/block/blowfish/blowfish.h b/src/block/blowfish/blowfish.h
index b89ffcaaa..13706d21e 100644
--- a/src/block/blowfish/blowfish.h
+++ b/src/block/blowfish/blowfish.h
@@ -1,6 +1,6 @@
/*
* Blowfish
-* (C) 1999-2009 Jack Lloyd
+* (C) 1999-2011 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -21,15 +21,28 @@ class BOTAN_DLL Blowfish : public Block_Cipher_Fixed_Params<8, 1, 56>
void encrypt_n(const byte in[], byte out[], size_t blocks) const;
void decrypt_n(const byte in[], byte out[], size_t blocks) const;
+ /**
+ * Modified EKSBlowfish key schedule, used for bcrypt password hashing
+ */
+ void eks_key_schedule(const byte key[], size_t key_length,
+ const byte salt[16], size_t workfactor);
+
void clear();
std::string name() const { return "Blowfish"; }
BlockCipher* clone() const { return new Blowfish; }
Blowfish() : S(1024), P(18) {}
private:
- void key_schedule(const byte[], size_t);
+ void key_schedule(const byte key[], size_t length);
+
+ void key_expansion(const byte key[],
+ size_t key_length,
+ const byte salt[16]);
+
void generate_sbox(MemoryRegion<u32bit>& box,
- u32bit& L, u32bit& R) const;
+ u32bit& L, u32bit& R,
+ const byte salt[16],
+ size_t salt_off) const;
static const u32bit P_INIT[18];
static const u32bit S_INIT[1024];