diff options
author | lloyd <[email protected]> | 2010-02-01 16:29:38 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2010-02-01 16:29:38 +0000 |
commit | 454e45b7c4fece11a7f43ffa412148b4a274c90f (patch) | |
tree | 5ae87c2104fba534548e59fa477d6a5f2f5a5e29 | |
parent | ae6a404ec14cc3c86a96cd3e5c67c9c23be38147 (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.cpp | 6 | ||||
-rw-r--r-- | doc/api.tex | 81 | ||||
-rw-r--r-- | doc/examples/decrypt.cpp | 20 | ||||
-rw-r--r-- | doc/examples/encrypt.cpp | 21 | ||||
-rw-r--r-- | doc/examples/encrypt2.cpp | 15 | ||||
-rw-r--r-- | doc/examples/passhash.cpp | 27 | ||||
-rw-r--r-- | doc/examples/row_encryptor.cpp | 7 | ||||
-rw-r--r-- | src/constructs/cryptobox/cryptobox.cpp | 12 | ||||
-rw-r--r-- | src/pbe/pbes1/pbes1.cpp | 6 | ||||
-rw-r--r-- | src/pbe/pbes2/pbes2.cpp | 6 | ||||
-rw-r--r-- | src/s2k/pbkdf1/pbkdf1.cpp | 8 | ||||
-rw-r--r-- | src/s2k/pbkdf1/pbkdf1.h | 8 | ||||
-rw-r--r-- | src/s2k/pbkdf2/pbkdf2.cpp | 8 | ||||
-rw-r--r-- | src/s2k/pbkdf2/pbkdf2.h | 8 | ||||
-rw-r--r-- | src/s2k/pgps2k/pgp_s2k.cpp | 7 | ||||
-rw-r--r-- | src/s2k/pgps2k/pgp_s2k.h | 8 | ||||
-rw-r--r-- | src/s2k/s2k.cpp | 55 | ||||
-rw-r--r-- | src/s2k/s2k.h | 58 |
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; }; } |