aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2010-02-01 16:29:38 +0000
committerlloyd <[email protected]>2010-02-01 16:29:38 +0000
commit454e45b7c4fece11a7f43ffa412148b4a274c90f (patch)
tree5ae87c2104fba534548e59fa477d6a5f2f5a5e29
parentae6a404ec14cc3c86a96cd3e5c67c9c23be38147 (diff)
Modify the S2K interface. Instead of being stateful in terms of the salt
and iteration count, force it to be passed to each call to derive_key. So remove current_salt, set_iterations, new_random_salt, and change_salt functions from S2K interface. Update examples and test application to match. While I was in there, change the passhash example to use 64 bit salts and 128 bit PBKDF2 outputs.
-rw-r--r--checks/dolook.cpp6
-rw-r--r--doc/api.tex81
-rw-r--r--doc/examples/decrypt.cpp20
-rw-r--r--doc/examples/encrypt.cpp21
-rw-r--r--doc/examples/encrypt2.cpp15
-rw-r--r--doc/examples/passhash.cpp27
-rw-r--r--doc/examples/row_encryptor.cpp7
-rw-r--r--src/constructs/cryptobox/cryptobox.cpp12
-rw-r--r--src/pbe/pbes1/pbes1.cpp6
-rw-r--r--src/pbe/pbes2/pbes2.cpp6
-rw-r--r--src/s2k/pbkdf1/pbkdf1.cpp8
-rw-r--r--src/s2k/pbkdf1/pbkdf1.h8
-rw-r--r--src/s2k/pbkdf2/pbkdf2.cpp8
-rw-r--r--src/s2k/pbkdf2/pbkdf2.h8
-rw-r--r--src/s2k/pgps2k/pgp_s2k.cpp7
-rw-r--r--src/s2k/pgps2k/pgp_s2k.h8
-rw-r--r--src/s2k/s2k.cpp55
-rw-r--r--src/s2k/s2k.h58
18 files changed, 150 insertions, 211 deletions
diff --git a/checks/dolook.cpp b/checks/dolook.cpp
index 28ac60c1b..aa2d58e1f 100644
--- a/checks/dolook.cpp
+++ b/checks/dolook.cpp
@@ -60,9 +60,9 @@ class S2K_Filter : public Filter
{ passphrase += std::string(reinterpret_cast<const char*>(in), len); }
void end_msg()
{
- s2k->change_salt(salt, salt.size());
- s2k->set_iterations(iterations);
- SymmetricKey x = s2k->derive_key(outlen, passphrase);
+ SymmetricKey x = s2k->derive_key(outlen, passphrase,
+ &salt[0], salt.size(),
+ iterations);
send(x.bits_of());
}
S2K_Filter(S2K* algo, const SymmetricKey& s, u32bit o, u32bit i)
diff --git a/doc/api.tex b/doc/api.tex
index 556e76aa0..20177a9f8 100644
--- a/doc/api.tex
+++ b/doc/api.tex
@@ -2621,53 +2621,46 @@ degree of applicability.
\subsection{S2K Algorithms}
-There are various procedures (usually fairly ad-hoc) for turning a passphrase
-into a (mostly) arbitrary length key for a symmetric cipher. A general
-interface for such algorithms is presented in \filename{s2k.h}. The main
-function is \function{derive\_key}, which takes a passphrase, and the desired
-length of the output key, and returns a key of that length, deterministically
-produced from the passphrase. If an algorithm can't produce a key of that size,
-it will throw an exception (most notably, PKCS \#5's PBKDF1 can only produce
-strings between 1 and $n$ bytes, where $n$ is the output size of the underlying
-hash function).
-
-Most such algorithms allow the use of a ``salt'', which provides some extra
-randomness and helps against dictionary attacks on the passphrase. Simply call
-\function{change\_salt} (there are variations of it for most of the ways you
-might wish to specify a salt, check the header for details) with a block of
-random data. You can also have the class generate a new salt for you with
-\function{new\_random\_salt}; the salt that was generated can be retrieved with
-\function{current\_salt}.
-
-Additionally some algorithms allow you to set some sort of iteration
-count, which will make the algorithm take longer to compute the final
-key (reducing the speed of brute-force attacks of various kinds). This
-can be changed with the \function{set\_iterations} function. Most
-standards recommend an iteration count of at least 1000. Currently
-defined S2K algorithms are ``PBKDF1(digest)'', ``PBKDF2(digest)'', and
-``OpenPGP-S2K(digest)''; you can retrieve any of these using the
-\function{get\_s2k}, found in \filename{lookup.h}. As of this writing,
-``PBKDF2(SHA-256)'' with 10000 iterations and an 8 byte salt is
-recommend for new applications.
+There are various procedures (usually fairly ad-hoc) for turning a
+passphrase into a (mostly) arbitrary length key for a symmetric
+cipher. A general interface for such algorithms is presented in
+\filename{s2k.h}. The main function is \function{derive\_key}, which
+takes a passphrase, a salt, an iteration count, and the desired length
+of the output key, and returns a key of that length, deterministically
+produced from the passphrase and salt. If an algorithm can't produce a
+key of that size, it will throw an exception (most notably, PKCS \#5's
+PBKDF1 can only produce strings between 1 and $n$ bytes, where $n$ is
+the output size of the underlying hash function).
+
+The purpose of the iteration count is to make the algorithm take
+longer to compute the final key (reducing the speed of brute-force
+attacks of various kinds). Most standards recommend an iteration count
+of at least 10000. Currently defined S2K algorithms are
+``PBKDF1(digest)'', ``PBKDF2(digest)'', and ``OpenPGP-S2K(digest)'';
+you can retrieve any of these using the \function{get\_s2k}, found in
+\filename{lookup.h}. As of this writing, ``PBKDF2(SHA-256)'' with
+10000 iterations and a 16 byte salt is recommend for new applications.
\subsubsection{OpenPGP S2K}
-There are some oddities about OpenPGP's S2K algorithms that are documented
-here. For one thing, it uses the iteration count in a strange manner; instead
-of specifying how many times to iterate the hash, it tells how many
-\emph{bytes} should be hashed in total (including the salt). So the exact
-iteration count will depend on the size of the salt (which is fixed at 8 bytes
-by the OpenPGP standard, though the implementation will allow any salt size)
-and the size of the passphrase.
-
-To get what OpenPGP calls ``Simple S2K'', set iterations to 0 (the default for
-OpenPGP S2K), and do not specify a salt. To get ``Salted S2K'', again leave the
-iteration count at 0, but give an 8-byte salt. ``Salted and Iterated S2K''
-requires an 8-byte salt and some iteration count (this should be significantly
-larger than the size of the longest passphrase that might reasonably be used;
-somewhere from 1024 to 65536 would probably be about right). Using both a
-reasonably sized salt and a large iteration count is highly recommended to
-prevent password guessing attempts.
+There are some oddities about OpenPGP's S2K algorithms that are
+documented here. For one thing, it uses the iteration count in a
+strange manner; instead of specifying how many times to iterate the
+hash, it tells how many \emph{bytes} should be hashed in total
+(including the salt). So the exact iteration count will depend on the
+size of the salt (which is fixed at 8 bytes by the OpenPGP standard,
+though the implementation will allow any salt size) and the size of
+the passphrase.
+
+To get what OpenPGP calls ``Simple S2K'', set iterations to 0, and do
+not specify a salt. To get ``Salted S2K'', again leave the iteration
+count at 0, but give an 8-byte salt. ``Salted and Iterated S2K''
+requires an 8-byte salt and some iteration count (this should be
+significantly larger than the size of the longest passphrase that
+might reasonably be used; somewhere from 1024 to 65536 would probably
+be about right). Using both a reasonably sized salt and a large
+iteration count is highly recommended to prevent password guessing
+attempts.
\subsection{Checksums}
diff --git a/doc/examples/decrypt.cpp b/doc/examples/decrypt.cpp
index ebab5d804..de261b5f3 100644
--- a/doc/examples/decrypt.cpp
+++ b/doc/examples/decrypt.cpp
@@ -106,12 +106,22 @@ int main(int argc, char* argv[])
const u32bit iv_len = block_size_of(algo);
std::auto_ptr<S2K> s2k(get_s2k("PBKDF2(SHA-1)"));
- s2k->set_iterations(8192);
- s2k->change_salt(b64_decode(salt_str));
- SymmetricKey bc_key = s2k->derive_key(key_len, "BLK" + passphrase);
- InitializationVector iv = s2k->derive_key(iv_len, "IVL" + passphrase);
- SymmetricKey mac_key = s2k->derive_key(16, "MAC" + passphrase);
+ const u32bit PBKDF2_ITERATIONS = 8192;
+
+ SecureVector<byte> salt = b64_decode(salt_str);
+
+ SymmetricKey bc_key = s2k->derive_key(key_len, "BLK" + passphrase,
+ &salt[0], salt.size(),
+ PBKDF2_ITERATIONS);
+
+ InitializationVector iv = s2k->derive_key(iv_len, "IVL" + passphrase,
+ &salt[0], salt.size(),
+ PBKDF2_ITERATIONS);
+
+ SymmetricKey mac_key = s2k->derive_key(16, "MAC" + passphrase,
+ &salt[0], salt.size(),
+ PBKDF2_ITERATIONS);
Pipe pipe(new Base64_Decoder,
get_cipher(algo + "/CBC", bc_key, iv, DECRYPTION),
diff --git a/doc/examples/encrypt.cpp b/doc/examples/encrypt.cpp
index f903c2f24..4999fa086 100644
--- a/doc/examples/encrypt.cpp
+++ b/doc/examples/encrypt.cpp
@@ -125,17 +125,26 @@ int main(int argc, char* argv[])
AutoSeeded_RNG rng;
std::auto_ptr<S2K> s2k(get_s2k("PBKDF2(SHA-1)"));
- s2k->set_iterations(8192);
- s2k->new_random_salt(rng, 8);
- SymmetricKey bc_key = s2k->derive_key(key_len, "BLK" + passphrase);
- InitializationVector iv = s2k->derive_key(iv_len, "IVL" + passphrase);
- SymmetricKey mac_key = s2k->derive_key(16, "MAC" + passphrase);
+ SecureVector<byte> salt(8);
+ rng.randomize(&salt[0], salt.size());
+
+ const u32bit PBKDF2_ITERATIONS = 8192;
+
+ SymmetricKey bc_key = s2k->derive_key(key_len, "BLK" + passphrase,
+ &salt[0], salt.size(),
+ PBKDF2_ITERATIONS);
+ InitializationVector iv = s2k->derive_key(iv_len, "IVL" + passphrase,
+ &salt[0], salt.size(),
+ PBKDF2_ITERATIONS);
+ SymmetricKey mac_key = s2k->derive_key(16, "MAC" + passphrase,
+ &salt[0], salt.size(),
+ PBKDF2_ITERATIONS);
// Just to be all fancy we even write a (simple) header.
out << "-------- ENCRYPTED FILE --------" << std::endl;
out << algo << std::endl;
- out << b64_encode(s2k->current_salt()) << std::endl;
+ out << b64_encode(salt) << std::endl;
Pipe pipe(new Fork(
new Chain(new MAC_Filter("HMAC(SHA-1)", mac_key),
diff --git a/doc/examples/encrypt2.cpp b/doc/examples/encrypt2.cpp
index dac2f8314..41f4fb478 100644
--- a/doc/examples/encrypt2.cpp
+++ b/doc/examples/encrypt2.cpp
@@ -26,16 +26,21 @@ int main()
PKCS5_PBKDF2 pbkdf2(new HMAC(new SHA_160));
- pbkdf2.set_iterations(4096);
- pbkdf2.new_random_salt(rng, 8);
- SecureVector<byte> the_salt = pbkdf2.current_salt();
+ const u32bit PBKDF2_ITERATIONS = 8192;
- SecureVector<byte> master_key = pbkdf2.derive_key(48, passphrase).bits_of();
+ SecureVector<byte> salt(8);
+ rng.randomize(&salt[0], salt.size());
+
+ SecureVector<byte> master_key = pbkdf2.derive_key(48, passphrase,
+ &salt[0], salt.size(),
+ PBKDF2_ITERATIONS).bits_of();
KDF* kdf = get_kdf("KDF2(SHA-1)");
SymmetricKey key = kdf->derive_key(20, master_key, "cipher key");
+
SymmetricKey mac_key = kdf->derive_key(20, master_key, "hmac key");
+
InitializationVector iv = kdf->derive_key(8, master_key, "cipher iv");
Pipe pipe(new Fork(
@@ -50,7 +55,7 @@ int main()
)
);
- outfile.write((const char*)the_salt.begin(), the_salt.size());
+ outfile.write((const char*)salt.begin(), salt.size());
pipe.start_msg();
infile >> pipe;
diff --git a/doc/examples/passhash.cpp b/doc/examples/passhash.cpp
index 24f7ff674..8c50de072 100644
--- a/doc/examples/passhash.cpp
+++ b/doc/examples/passhash.cpp
@@ -55,18 +55,26 @@ int main(int argc, char* argv[])
return 0;
}
+const u32bit SALT_BYTES = 8; // 64 bits of salt
+const u32bit PBKDF_OUTPUT_LEN = 16; // 128 bits output
+const u32bit KDF_ITERATIONS = 100000;
+
std::string password_hash(const std::string& pass,
RandomNumberGenerator& rng)
{
PKCS5_PBKDF2 kdf(new HMAC(new SHA_160));
- kdf.set_iterations(10000);
- kdf.new_random_salt(rng, 6); // 48 bits
+ SecureVector<byte> salt(SALT_BYTES);
+ rng.randomize(&salt[0], salt.size());
+
+ // Encode the salt plus 96 bits of PBKDF2 output
Pipe pipe(new Base64_Encoder);
pipe.start_msg();
- pipe.write(kdf.current_salt());
- pipe.write(kdf.derive_key(12, pass).bits_of());
+ pipe.write(salt);
+ pipe.write(kdf.derive_key(PBKDF_OUTPUT_LEN, pass,
+ &salt[0], salt.size(),
+ KDF_ITERATIONS).bits_of());
pipe.end_msg();
return pipe.read_all_as_string();
@@ -81,12 +89,15 @@ bool password_hash_ok(const std::string& pass, const std::string& hash)
SecureVector<byte> hash_bin = pipe.read_all();
- PKCS5_PBKDF2 kdf(new HMAC(new SHA_160));
+ if(hash_bin.size() != (PBKDF_OUTPUT_LEN + SALT_BYTES))
+ return false;
- kdf.set_iterations(10000);
- kdf.change_salt(hash_bin, 6);
+ PKCS5_PBKDF2 kdf(new HMAC(new SHA_160));
- SecureVector<byte> cmp = kdf.derive_key(12, pass).bits_of();
+ SecureVector<byte> cmp = kdf.derive_key(
+ PBKDF_OUTPUT_LEN, pass,
+ &hash_bin[0], SALT_BYTES,
+ KDF_ITERATIONS).bits_of();
return same_mem(cmp.begin(), hash_bin.begin() + 6, 12);
}
diff --git a/doc/examples/row_encryptor.cpp b/doc/examples/row_encryptor.cpp
index 17f44ce7b..7c234105d 100644
--- a/doc/examples/row_encryptor.cpp
+++ b/doc/examples/row_encryptor.cpp
@@ -66,10 +66,9 @@ void Row_Encryptor::init(const std::string& passphrase)
{
std::auto_ptr<S2K> s2k(get_s2k("PBKDF2(SHA-160)"));
- s2k->set_iterations(10000);
- s2k->change_salt(&s2k_salt[0], s2k_salt.size());
-
- SecureVector<byte> key = s2k->derive_key(32, passphrase).bits_of();
+ SecureVector<byte> key = s2k->derive_key(32, passphrase,
+ &s2k_salt[0], s2k_salt.size(),
+ 10000).bits_of();
/*
Save pointers to the EAX objects so we can change the IV as needed
diff --git a/src/constructs/cryptobox/cryptobox.cpp b/src/constructs/cryptobox/cryptobox.cpp
index 20435fa59..c862b5c50 100644
--- a/src/constructs/cryptobox/cryptobox.cpp
+++ b/src/constructs/cryptobox/cryptobox.cpp
@@ -48,10 +48,10 @@ std::string encrypt(const byte input[], u32bit input_len,
rng.randomize(pbkdf_salt.begin(), pbkdf_salt.size());
PKCS5_PBKDF2 pbkdf(new HMAC(new SHA_512));
- pbkdf.change_salt(pbkdf_salt.begin(), pbkdf_salt.size());
- pbkdf.set_iterations(PBKDF_ITERATIONS);
- OctetString mk = pbkdf.derive_key(PBKDF_OUTPUT_LEN, passphrase);
+ OctetString mk = pbkdf.derive_key(PBKDF_OUTPUT_LEN, passphrase,
+ &pbkdf_salt[0], pbkdf_salt.size(),
+ PBKDF_ITERATIONS);
SymmetricKey cipher_key(mk.begin(), CIPHER_KEY_LEN);
SymmetricKey mac_key(mk.begin() + CIPHER_KEY_LEN, MAC_KEY_LEN);
@@ -109,10 +109,10 @@ std::string decrypt(const byte input[], u32bit input_len,
SecureVector<byte> pbkdf_salt(ciphertext + VERSION_CODE_LEN, PBKDF_SALT_LEN);
PKCS5_PBKDF2 pbkdf(new HMAC(new SHA_512));
- pbkdf.change_salt(pbkdf_salt.begin(), pbkdf_salt.size());
- pbkdf.set_iterations(PBKDF_ITERATIONS);
- OctetString mk = pbkdf.derive_key(PBKDF_OUTPUT_LEN, passphrase);
+ OctetString mk = pbkdf.derive_key(PBKDF_OUTPUT_LEN, passphrase,
+ &pbkdf_salt[0], pbkdf_salt.size(),
+ PBKDF_ITERATIONS);
SymmetricKey cipher_key(mk.begin(), CIPHER_KEY_LEN);
SymmetricKey mac_key(mk.begin() + CIPHER_KEY_LEN, MAC_KEY_LEN);
diff --git a/src/pbe/pbes1/pbes1.cpp b/src/pbe/pbes1/pbes1.cpp
index 1d851d1a5..36cfaa6b4 100644
--- a/src/pbe/pbes1/pbes1.cpp
+++ b/src/pbe/pbes1/pbes1.cpp
@@ -80,9 +80,9 @@ void PBE_PKCS5v15::set_key(const std::string& passphrase)
{
PKCS5_PBKDF1 pbkdf(hash_function->clone());
- pbkdf.set_iterations(iterations);
- pbkdf.change_salt(salt, salt.size());
- SymmetricKey key_and_iv = pbkdf.derive_key(16, passphrase);
+ SymmetricKey key_and_iv = pbkdf.derive_key(16, passphrase,
+ &salt[0], salt.size(),
+ iterations);
key.set(key_and_iv.begin(), 8);
iv.set(key_and_iv.begin() + 8, 8);
diff --git a/src/pbe/pbes2/pbes2.cpp b/src/pbe/pbes2/pbes2.cpp
index bd24c449b..63772263f 100644
--- a/src/pbe/pbes2/pbes2.cpp
+++ b/src/pbe/pbes2/pbes2.cpp
@@ -87,9 +87,9 @@ void PBE_PKCS5v20::set_key(const std::string& passphrase)
{
PKCS5_PBKDF2 pbkdf(new HMAC(hash_function->clone()));
- pbkdf.set_iterations(iterations);
- pbkdf.change_salt(salt, salt.size());
- key = pbkdf.derive_key(key_length, passphrase).bits_of();
+ key = pbkdf.derive_key(key_length, passphrase,
+ &salt[0], salt.size(),
+ iterations).bits_of();
}
/**
diff --git a/src/s2k/pbkdf1/pbkdf1.cpp b/src/s2k/pbkdf1/pbkdf1.cpp
index fcc5b9a97..8e521e988 100644
--- a/src/s2k/pbkdf1/pbkdf1.cpp
+++ b/src/s2k/pbkdf1/pbkdf1.cpp
@@ -12,10 +12,10 @@ namespace Botan {
/*
* Return a PKCS#5 PBKDF1 derived key
*/
-OctetString PKCS5_PBKDF1::derive(u32bit key_len,
- const std::string& passphrase,
- const byte salt[], u32bit salt_size,
- u32bit iterations) const
+OctetString PKCS5_PBKDF1::derive_key(u32bit key_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_size,
+ u32bit iterations) const
{
if(iterations == 0)
throw Invalid_Argument("PKCS5_PBKDF1: Invalid iteration count");
diff --git a/src/s2k/pbkdf1/pbkdf1.h b/src/s2k/pbkdf1/pbkdf1.h
index 4e5cafdb0..053a2dbe1 100644
--- a/src/s2k/pbkdf1/pbkdf1.h
+++ b/src/s2k/pbkdf1/pbkdf1.h
@@ -22,6 +22,11 @@ class BOTAN_DLL PKCS5_PBKDF1 : public S2K
std::string name() const;
S2K* clone() const;
+ OctetString derive_key(u32bit output_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_len,
+ u32bit iterations) const;
+
/**
* Create a PKCS #5 instance using the specified hash function.
* @param hash a pointer to a hash function object to use
@@ -33,9 +38,6 @@ class BOTAN_DLL PKCS5_PBKDF1 : public S2K
~PKCS5_PBKDF1() { delete hash; }
private:
- OctetString derive(u32bit, const std::string&,
- const byte[], u32bit, u32bit) const;
-
HashFunction* hash;
};
diff --git a/src/s2k/pbkdf2/pbkdf2.cpp b/src/s2k/pbkdf2/pbkdf2.cpp
index 6f790c06b..e7aebbfe2 100644
--- a/src/s2k/pbkdf2/pbkdf2.cpp
+++ b/src/s2k/pbkdf2/pbkdf2.cpp
@@ -14,10 +14,10 @@ namespace Botan {
/*
* Return a PKCS#5 PBKDF2 derived key
*/
-OctetString PKCS5_PBKDF2::derive(u32bit key_len,
- const std::string& passphrase,
- const byte salt[], u32bit salt_size,
- u32bit iterations) const
+OctetString PKCS5_PBKDF2::derive_key(u32bit key_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_size,
+ u32bit iterations) const
{
if(iterations == 0)
throw Invalid_Argument("PKCS#5 PBKDF2: Invalid iteration count");
diff --git a/src/s2k/pbkdf2/pbkdf2.h b/src/s2k/pbkdf2/pbkdf2.h
index 7510338bb..b6d231916 100644
--- a/src/s2k/pbkdf2/pbkdf2.h
+++ b/src/s2k/pbkdf2/pbkdf2.h
@@ -22,6 +22,11 @@ class BOTAN_DLL PKCS5_PBKDF2 : public S2K
std::string name() const;
S2K* clone() const;
+ OctetString derive_key(u32bit output_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_len,
+ u32bit iterations) const;
+
/**
* Create a PKCS #5 instance using the specified message auth code
* @param mac the MAC to use
@@ -29,9 +34,6 @@ class BOTAN_DLL PKCS5_PBKDF2 : public S2K
PKCS5_PBKDF2(MessageAuthenticationCode* mac);
~PKCS5_PBKDF2();
private:
- OctetString derive(u32bit, const std::string&,
- const byte[], u32bit, u32bit) const;
-
MessageAuthenticationCode* mac;
};
diff --git a/src/s2k/pgps2k/pgp_s2k.cpp b/src/s2k/pgps2k/pgp_s2k.cpp
index 86394d84d..49ff6892c 100644
--- a/src/s2k/pgps2k/pgp_s2k.cpp
+++ b/src/s2k/pgps2k/pgp_s2k.cpp
@@ -14,9 +14,10 @@ namespace Botan {
/*
* Derive a key using the OpenPGP S2K algorithm
*/
-OctetString OpenPGP_S2K::derive(u32bit key_len, const std::string& passphrase,
- const byte salt_buf[], u32bit salt_size,
- u32bit iterations) const
+OctetString OpenPGP_S2K::derive_key(u32bit key_len,
+ const std::string& passphrase,
+ const byte salt_buf[], u32bit salt_size,
+ u32bit iterations) const
{
SecureVector<byte> key(key_len), hash_buf;
diff --git a/src/s2k/pgps2k/pgp_s2k.h b/src/s2k/pgps2k/pgp_s2k.h
index 00e95f7fa..7f25623f3 100644
--- a/src/s2k/pgps2k/pgp_s2k.h
+++ b/src/s2k/pgps2k/pgp_s2k.h
@@ -22,12 +22,14 @@ class BOTAN_DLL OpenPGP_S2K : public S2K
std::string name() const;
S2K* clone() const;
+ OctetString derive_key(u32bit output_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_len,
+ u32bit iterations) const;
+
OpenPGP_S2K(HashFunction* hash_in) : hash(hash_in) {}
~OpenPGP_S2K() { delete hash; }
private:
- OctetString derive(u32bit, const std::string&,
- const byte[], u32bit, u32bit) const;
-
HashFunction* hash;
};
diff --git a/src/s2k/s2k.cpp b/src/s2k/s2k.cpp
deleted file mode 100644
index 42064529d..000000000
--- a/src/s2k/s2k.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-* S2K
-* (C) 1999-2007 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/s2k.h>
-
-namespace Botan {
-
-/*
-* Derive a key from a passphrase
-*/
-OctetString S2K::derive_key(u32bit key_len,
- const std::string& passphrase) const
- {
- return derive(key_len, passphrase, salt, salt.size(), iterations());
- }
-
-/*
-* Set the number of iterations
-*/
-void S2K::set_iterations(u32bit i)
- {
- iter = i;
- }
-
-/*
-* Change the salt
-*/
-void S2K::change_salt(const byte new_salt[], u32bit length)
- {
- salt.set(new_salt, length);
- }
-
-/*
-* Change the salt
-*/
-void S2K::change_salt(const MemoryRegion<byte>& new_salt)
- {
- change_salt(new_salt.begin(), new_salt.size());
- }
-
-/*
-* Create a new random salt
-*/
-void S2K::new_random_salt(RandomNumberGenerator& rng,
- u32bit length)
- {
- salt.resize(length);
- rng.randomize(salt, length);
- }
-
-}
diff --git a/src/s2k/s2k.h b/src/s2k/s2k.h
index 7af92519b..82f5abeef 100644
--- a/src/s2k/s2k.h
+++ b/src/s2k/s2k.h
@@ -39,62 +39,22 @@ class BOTAN_DLL S2K
/**
* Derive a key from a passphrase with this S2K object. It will use
* the salt value and number of iterations configured in this object.
- * @param key_len the desired length of the key to produce
+ * @param output_len the desired length of the key to produce
* @param passphrase the password to derive the key from
+ * @param salt the randomly chosen salt
+ * @param salt_len length of salt in bytes
+ * @param iterations the number of iterations to use (use 10K or more)
*/
- OctetString derive_key(u32bit key_len,
- const std::string& passphrase) const;
+ virtual OctetString derive_key(u32bit output_len,
+ const std::string& passphrase,
+ const byte salt[], u32bit salt_len,
+ u32bit iterations) const = 0;
- /**
- * Set the number of iterations for the one-way function during
- * key generation.
- * @param n the desired number of iterations
- */
- void set_iterations(u32bit n);
-
- /**
- * Set a new salt value.
- * @param new_salt a byte array defining the new salt value
- * @param len the length of the above byte array
- */
- void change_salt(const byte new_salt[], u32bit len);
-
- /**
- * Set a new salt value.
- * @param new_salt the new salt value
- */
- void change_salt(const MemoryRegion<byte>& new_salt);
-
- /**
- * Create a new random salt value using the rng
- * @param rng the random number generator to use
- * @param len the desired length of the new salt value
- */
- void new_random_salt(RandomNumberGenerator& rng, u32bit len);
-
- /**
- * Get the number of iterations for the key derivation currently
- * configured in this S2K object.
- * @return the current number of iterations
- */
- u32bit iterations() const { return iter; }
-
- /**
- * Get the currently configured salt value of this S2K object.
- * @return the current salt value
- */
- SecureVector<byte> current_salt() const { return salt; }
-
- S2K() { iter = 0; }
+ S2K() {}
virtual ~S2K() {}
private:
S2K(const S2K&) {}
S2K& operator=(const S2K&) { return (*this); }
-
- virtual OctetString derive(u32bit, const std::string&,
- const byte[], u32bit, u32bit) const = 0;
- SecureVector<byte> salt;
- u32bit iter;
};
}