diff options
-rw-r--r-- | checks/common.h | 3 | ||||
-rw-r--r-- | checks/dolook.cpp | 35 | ||||
-rw-r--r-- | checks/validate.dat | 10 | ||||
-rw-r--r-- | doc/api.tex | 16 | ||||
-rw-r--r-- | doc/examples/decrypt.cpp | 20 | ||||
-rw-r--r-- | doc/examples/encrypt.cpp | 22 | ||||
-rw-r--r-- | doc/examples/readme.txt | 2 | ||||
-rw-r--r-- | doc/examples/row_encryptor.cpp | 28 | ||||
-rw-r--r-- | doc/log.txt | 1 | ||||
-rw-r--r-- | doc/tutorial.tex | 53 | ||||
-rw-r--r-- | src/libstate/get_enc.cpp | 4 | ||||
-rw-r--r-- | src/libstate/info.txt | 2 | ||||
-rw-r--r-- | src/libstate/lookup.h | 28 | ||||
-rw-r--r-- | src/pbkdf/info.txt (renamed from src/s2k/info.txt) | 0 | ||||
-rw-r--r-- | src/pbkdf/pbkdf.h (renamed from src/s2k/s2k.h) | 32 | ||||
-rw-r--r-- | src/pbkdf/pbkdf1/info.txt (renamed from src/s2k/pbkdf1/info.txt) | 0 | ||||
-rw-r--r-- | src/pbkdf/pbkdf1/pbkdf1.cpp (renamed from src/s2k/pbkdf1/pbkdf1.cpp) | 16 | ||||
-rw-r--r-- | src/pbkdf/pbkdf1/pbkdf1.h (renamed from src/s2k/pbkdf1/pbkdf1.h) | 33 | ||||
-rw-r--r-- | src/pbkdf/pbkdf2/info.txt (renamed from src/s2k/pbkdf2/info.txt) | 0 | ||||
-rw-r--r-- | src/pbkdf/pbkdf2/pbkdf2.cpp (renamed from src/s2k/pbkdf2/pbkdf2.cpp) | 22 | ||||
-rw-r--r-- | src/pbkdf/pbkdf2/pbkdf2.h (renamed from src/s2k/pbkdf2/pbkdf2.h) | 25 | ||||
-rw-r--r-- | src/pbkdf/pgps2k/info.txt (renamed from src/s2k/pgps2k/info.txt) | 0 | ||||
-rw-r--r-- | src/pbkdf/pgps2k/pgp_s2k.cpp (renamed from src/s2k/pgps2k/pgp_s2k.cpp) | 18 | ||||
-rw-r--r-- | src/pbkdf/pgps2k/pgp_s2k.h (renamed from src/s2k/pgps2k/pgp_s2k.h) | 30 | ||||
-rw-r--r-- | src/wrap/sqlite/codec.cpp | 8 | ||||
-rw-r--r-- | src/wrap/sqlite/codec.h | 8 |
26 files changed, 205 insertions, 211 deletions
diff --git a/checks/common.h b/checks/common.h index b849ce721..1b1e89bbf 100644 --- a/checks/common.h +++ b/checks/common.h @@ -34,7 +34,8 @@ Botan::Filter* lookup_hash(const std::string&); Botan::Filter* lookup_mac(const std::string&, const std::string&); Botan::Filter* lookup_rng(const std::string&, const std::string&); Botan::Filter* lookup_encoder(const std::string&); -Botan::Filter* lookup_s2k(const std::string&, const std::vector<std::string>&); +Botan::Filter* lookup_pbkdf(const std::string&, + const std::vector<std::string>&); Botan::Filter* lookup_kdf(const std::string&, const std::string&, const std::string&); diff --git a/checks/dolook.cpp b/checks/dolook.cpp index 1eecfa9fc..71bb65725 100644 --- a/checks/dolook.cpp +++ b/checks/dolook.cpp @@ -55,38 +55,39 @@ using namespace Botan; #include "common.h" -/* A weird little hack to fit S2K algorithms into the validation suite - You probably wouldn't ever want to actually use the S2K algorithms like - this, the raw S2K interface is more convenient for actually using them +/* A weird little hack to fit PBKDF algorithms into the validation +* suite You probably wouldn't ever want to actually use the PBKDF +* algorithms like this, the raw PBKDF interface is more convenient +* for actually using them */ -class S2K_Filter : public Filter +class PBKDF_Filter : public Filter { public: - std::string name() const { return s2k->name(); } + std::string name() const { return pbkdf->name(); } void write(const byte in[], u32bit len) { passphrase += std::string(reinterpret_cast<const char*>(in), len); } void end_msg() { - SymmetricKey x = s2k->derive_key(outlen, passphrase, + SymmetricKey x = pbkdf->derive_key(outlen, passphrase, &salt[0], salt.size(), iterations); send(x.bits_of()); } - S2K_Filter(S2K* algo, const SymmetricKey& s, u32bit o, u32bit i) + PBKDF_Filter(PBKDF* algo, const SymmetricKey& s, u32bit o, u32bit i) { - s2k = algo; + pbkdf = algo; outlen = o; iterations = i; salt = s.bits_of(); } - ~S2K_Filter() { delete s2k; } + ~PBKDF_Filter() { delete pbkdf; } private: std::string passphrase; - S2K* s2k; + PBKDF* pbkdf; SecureVector<byte> salt; u32bit outlen, iterations; }; @@ -133,19 +134,19 @@ class KDF_Filter : public Filter u32bit outlen; }; -Filter* lookup_s2k(const std::string& algname, +Filter* lookup_pbkdf(const std::string& algname, const std::vector<std::string>& params) { - S2K* s2k = 0; + PBKDF* pbkdf = 0; try { - s2k = get_s2k(algname); + pbkdf = get_pbkdf(algname); } catch(...) { } - if(s2k) - return new S2K_Filter(s2k, params[0], to_u32bit(params[1]), - to_u32bit(params[2])); + if(pbkdf) + return new PBKDF_Filter(pbkdf, params[0], to_u32bit(params[1]), + to_u32bit(params[2])); return 0; } @@ -298,7 +299,7 @@ Filter* lookup(const std::string& algname, filter = lookup_encoder(algname); if(filter) return filter; - filter = lookup_s2k(algname, params); + filter = lookup_pbkdf(algname, params); if(filter) return filter; return 0; diff --git a/checks/validate.dat b/checks/validate.dat index aaeb7f013..cea1f18fc 100644 --- a/checks/validate.dat +++ b/checks/validate.dat @@ -1,8 +1,8 @@ # Main Botan validation file -# This has test vectors for block ciphers in ECB mode, stream ciphers, hash -# functions, MACs, KDFs, S2K algorithms, encoders/decoders, and block cipher -# modes (CBC, CTS, CFB, OFB, CTR, and EAX) +# This has test vectors for block ciphers in ECB mode, stream ciphers, +# hash functions, MACs, KDFs, PBKDFs, encoders/decoders, and block +# cipher modes (CBC, CTS, CFB, OFB, CTR, XTS, and EAX) # MARKER: Block Ciphers @@ -60553,9 +60553,9 @@ A09661392376F7044D9052A397883246B67F5F1EF63EB5FB::24 0123456789ABCDEFFEDCBA98765432010123456789ABCDEFFEDCBA9876543201\ 0123456789ABCDEFFEDCBA98765432010123456789ABCDEFFEDCBA9876543201:16 -# MARKER: S2K Algorithms +# MARKER: PBKDF Algorithms -# S2K format: passphrase:output:salt:out_len:iterations +# PBKDF format: passphrase:output:salt:out_len:iterations [OpenPGP-S2K(SHA-1)] 666F6F:0BEEC7B5EA3F0FDBC95D0DD47F3C5BC275DA8A335A8CAA4039FDBC02C01A649C::32:0 diff --git a/doc/api.tex b/doc/api.tex index 27bed084e..c4a998164 100644 --- a/doc/api.tex +++ b/doc/api.tex @@ -2477,17 +2477,17 @@ much memory is needed for internal I/O buffers will be used. \section{Miscellaneous} -This section has documentation for anything that just didn't fit into any of -the major categories. Many of them (Timers, Allocators) will rarely be used in -actual application code, but others, like the S2K algorithms, have a wide -degree of applicability. +This section has documentation for anything that just didn't fit into +any of the major categories. Many of them (Timers, Allocators) will +rarely be used in actual application code, but others, like the PBKDF +algorithms, have a wide degree of applicability. -\subsection{S2K Algorithms} +\subsection{PBKDF Algorithms} There are various procedures (usually 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 +\filename{pbkdf.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 @@ -2498,9 +2498,9 @@ 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 +of at least 10000. Currently defined PBKDF algorithms are ``PBKDF1(digest)'', ``PBKDF2(digest)'', and ``OpenPGP-S2K(digest)''; -you can retrieve any of these using the \function{get\_s2k}, found in +you can retrieve any of these using the \function{get\_pbkdf}, 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. diff --git a/doc/examples/decrypt.cpp b/doc/examples/decrypt.cpp index de261b5f3..2e913d2d3 100644 --- a/doc/examples/decrypt.cpp +++ b/doc/examples/decrypt.cpp @@ -105,23 +105,23 @@ int main(int argc, char* argv[]) const u32bit key_len = max_keylength_of(algo); const u32bit iv_len = block_size_of(algo); - std::auto_ptr<S2K> s2k(get_s2k("PBKDF2(SHA-1)")); + std::auto_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(SHA-1)")); 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); + SymmetricKey bc_key = pbkdf->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); + InitializationVector iv = pbkdf->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); + SymmetricKey mac_key = pbkdf->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 4999fa086..b5568ca50 100644 --- a/doc/examples/encrypt.cpp +++ b/doc/examples/encrypt.cpp @@ -124,22 +124,24 @@ int main(int argc, char* argv[]) AutoSeeded_RNG rng; - std::auto_ptr<S2K> s2k(get_s2k("PBKDF2(SHA-1)")); + std::auto_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(SHA-1)")); 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); + SymmetricKey bc_key = pbkdf->derive_key(key_len, "BLK" + passphrase, + &salt[0], salt.size(), + PBKDF2_ITERATIONS); + + InitializationVector iv = pbkdf->derive_key(iv_len, "IVL" + passphrase, + &salt[0], salt.size(), + PBKDF2_ITERATIONS); + + SymmetricKey mac_key = pbkdf->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; diff --git a/doc/examples/readme.txt b/doc/examples/readme.txt index 48686db71..fb6a03ddf 100644 --- a/doc/examples/readme.txt +++ b/doc/examples/readme.txt @@ -32,7 +32,7 @@ pkcs10: Generates a PKCS #10 certificate request for a 1024 bit RSA key self_sig: Generates a self-signed X.509v3 certificate with a 1024 bit RSA key -------- -* RSA examples (also uses X.509, PKCS #8, block ciphers, MACs, S2K algorithms) +* RSA examples (also uses X.509, PKCS #8, block ciphers, MACs, PBKDF algorithms) -------- rsa_kgen: Generate an RSA key, encrypt the private key with a passphrase, output the keys to a pair of files diff --git a/doc/examples/row_encryptor.cpp b/doc/examples/row_encryptor.cpp index 7c234105d..8c1df66a0 100644 --- a/doc/examples/row_encryptor.cpp +++ b/doc/examples/row_encryptor.cpp @@ -16,8 +16,8 @@ using namespace Botan; -/** -Encrypt and decrypt small rows +/* +* Encrypt and decrypt small rows */ class Row_Encryptor { @@ -34,14 +34,14 @@ class Row_Encryptor std::string decrypt(const std::string& input, const MemoryRegion<byte>& salt); - SecureVector<byte> get_s2k_salt() const { return s2k_salt; } + SecureVector<byte> get_pbkdf_salt() const { return pbkdf_salt; } private: void init(const std::string& passphrase); Row_Encryptor(const Row_Encryptor&) {} Row_Encryptor& operator=(const Row_Encryptor&) { return (*this); } - SecureVector<byte> s2k_salt; + SecureVector<byte> pbkdf_salt; Pipe enc_pipe, dec_pipe; EAX_Encryption* eax_enc; // owned by enc_pipe EAX_Decryption* eax_dec; // owned by dec_pipe; @@ -50,24 +50,24 @@ class Row_Encryptor Row_Encryptor::Row_Encryptor(const std::string& passphrase, RandomNumberGenerator& rng) { - s2k_salt.resize(10); // 80 bits - rng.randomize(&s2k_salt[0], s2k_salt.size()); + pbkdf_salt.resize(10); // 80 bits + rng.randomize(&pbkdf_salt[0], pbkdf_salt.size()); init(passphrase); } Row_Encryptor::Row_Encryptor(const std::string& passphrase, const MemoryRegion<byte>& salt) { - s2k_salt = salt; + pbkdf_salt = salt; init(passphrase); } void Row_Encryptor::init(const std::string& passphrase) { - std::auto_ptr<S2K> s2k(get_s2k("PBKDF2(SHA-160)")); + std::auto_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(SHA-160)")); - SecureVector<byte> key = s2k->derive_key(32, passphrase, - &s2k_salt[0], s2k_salt.size(), + SecureVector<byte> key = pbkdf->derive_key(32, passphrase, + &pbkdf_salt[0], pbkdf_salt.size(), 10000).bits_of(); /* @@ -159,13 +159,13 @@ int main() std::cout << "BOOM " << i << "\n"; } - Row_Encryptor test_s2k_salt_copy(secret_passphrase, - encryptor.get_s2k_salt()); + Row_Encryptor test_pbkdf_salt_copy(secret_passphrase, + encryptor.get_pbkdf_salt()); salt.clear(); // all-0 - std::string test = test_s2k_salt_copy.decrypt(encrypted_values[0], salt); + std::string test = test_pbkdf_salt_copy.decrypt(encrypted_values[0], salt); if(test != original_inputs[0]) - std::cout << "S2K salt copy failed to decrypt properly\n"; + std::cout << "PBKDF salt copy failed to decrypt properly\n"; return 0; } diff --git a/doc/log.txt b/doc/log.txt index ce0f1b6e3..42d749a4b 100644 --- a/doc/log.txt +++ b/doc/log.txt @@ -1,6 +1,7 @@ * 1.9.10-dev, ????-??-?? - Fix benchmarking of block ciphers in ECB mode + - Rename S2K to PBKDF * 1.9.9, 2010-06-28 - Add new X509::BER_encode and PKCS8::BER_encode diff --git a/doc/tutorial.tex b/doc/tutorial.tex index 4023ab20d..ee3bc936b 100644 --- a/doc/tutorial.tex +++ b/doc/tutorial.tex @@ -169,23 +169,22 @@ but an attacker, trying out a large list of potential passphrases, will be seriously annoyed (and slowed down) by this. In this iteration of the example, we'll kill these two birds with one -stone, and derive the key from the passphrase using a S2K (string to -key) algorithm (these are also often called PBKDF algorithms, for -Password-Based Key Derivation Function). In this example, we use +stone, and derive the key from the passphrase using a PBKDF +(Password-Based Key Derivation Function). In this example, we use PBKDF2 with Hash Message Authentication Code (HMAC(SHA-256)), which is specified in PKCS \#5. We replace the first four lines of code from the first example with: \begin{verbatim} - S2K* s2k = get_s2k("PBKDF2(SHA-256)"); + PBKDF* pbkdf = get_pbkdf("PBKDF2(SHA-256)"); // hard-coded iteration count for simplicity; should be sufficient - s2k->set_iterations(4096); + pbkdf->set_iterations(10000); // 8 octets == 64-bit salt; again, good enough - s2k->new_random_salt(8); - SecureVector<byte> the_salt = s2k->current_salt(); + pbkdf->new_random_salt(8); + SecureVector<byte> the_salt = pbkdf->current_salt(); // 48 octets == 32 for key + 16 for IV - SecureVector<byte> key_and_IV = s2k->derive_key(48, passphrase).bits_of(); + SecureVector<byte> key_and_IV = pbkdf->derive_key(48, passphrase).bits_of(); SymmetricKey key(key_and_IV, 32); InitializationVector iv(key_and_IV + 32, 16); @@ -193,7 +192,7 @@ the first example with: To complete the example, we have to remember to write out the salt (stored in \variable{the\_salt}) at the beginning of the file. The receiving side needs to -know this value in order to restore it (by calling the \variable{s2k} object's +know this value in order to restore it (by calling the \variable{pbkdf} object's \function{change\_salt} function) so it can derive the same key and IV from the passphrase. @@ -211,7 +210,7 @@ same key; that is very much a no-no. \begin{verbatim} // 80 octets == 32 for cipher key + 16 for IV + 32 for hmac key - SecureVector<byte> keys_and_IV = s2k->derive_key(80, passphrase); + SecureVector<byte> keys_and_IV = pbkdf->derive_key(80, passphrase); SymmetricKey key(keys_and_IV, 32); InitializationVector iv(keys_and_IV + 32, 16); @@ -258,15 +257,15 @@ key'', etc) makes sure that each of the three derived variables will have different values. \begin{verbatim} - S2K* s2k = get_s2k("PBKDF2(SHA-256)"); + PBKDF* pbkdf = get_pbkdf("PBKDF2(SHA-256)"); // hard-coded iteration count for simplicity; should be sufficient - s2k->set_iterations(4096); + pbkdf->set_iterations(10000); // 8 octet == 64-bit salt; again, good enough - s2k->new_random_salt(8); + pbkdf->new_random_salt(8); // store the salt so we can write it to a file later - SecureVector<byte> the_salt = s2k->current_salt(); + SecureVector<byte> the_salt = pbkdf->current_salt(); - SymmetricKey master_key = s2k->derive_key(48, passphrase); + SymmetricKey master_key = pbkdf->derive_key(48, passphrase); KDF* kdf = get_kdf("KDF2(SHA-256)"); @@ -281,12 +280,12 @@ Here is the final version of the encryption code, with all the changes we've made: \begin{verbatim} - S2K* s2k = get_s2k("PBKDF2(SHA-256)"); - s2k->set_iterations(4096); - s2k->new_random_salt(8); - SecureVector<byte> the_salt = s2k->current_salt(); + PBKDF* pbkdf = get_pbkdf("PBKDF2(SHA-256)"); + pbkdf->set_iterations(10000); + pbkdf->new_random_salt(8); + SecureVector<byte> the_salt = pbkdf->current_salt(); - SymmetricKey master_key = s2k->derive_key(48, passphrase); + SymmetricKey master_key = pbkdf->derive_key(48, passphrase); KDF* kdf = get_kdf("KDF2(SHA-256)"); @@ -356,12 +355,12 @@ In this case, we'll hex-encode the salt and the MAC, and output them both to standard output (the salt followed by the MAC). \begin{verbatim} - S2K* s2k = get_s2k("PBKDF2(SHA-256)"); - s2k->set_iterations(4096); - s2k->new_random_salt(8); - OctetString the_salt = s2k->current_salt(); + PBKDF* pbkdf = get_pbkdf("PBKDF2(SHA-256)"); + pbkdf->set_iterations(10000); + pbkdf->new_random_salt(8); + OctetString the_salt = pbkdf->current_salt(); - SymmetricKey hmac_key = s2k->derive_key(32, passphrase); + SymmetricKey hmac_key = pbkdf->derive_key(32, passphrase); Pipe pipe(new MAC_Filter("HMAC(SHA-256)", mac_key), new Hex_Encoder @@ -396,7 +395,7 @@ number generator (RNG): After reading the challenge, the client generates a response based on the challenge and the passphrase. In this case, we will do it by repeatedly hashing the challenge, the passphrase, and (if applicable) -the previous digest. We iterate this construction 4096 times, to make +the previous digest. We iterate this construction 10000 times, to make brute force attacks on the passphrase hard to do. Since we are already using 160-bit challenges, a 160-bit response seems warranted, so we'll use SHA-1. @@ -404,7 +403,7 @@ use SHA-1. \begin{verbatim} HashFunction* hash = get_hash("SHA-1"); SecureVector<byte> digest; - for(u32bit j = 0; j != 4096; j++) + for(u32bit j = 0; j != 10000; j++) { hash->update(digest, digest.size()); hash->update(passphrase); diff --git a/src/libstate/get_enc.cpp b/src/libstate/get_enc.cpp index ab4d15896..a825a5d24 100644 --- a/src/libstate/get_enc.cpp +++ b/src/libstate/get_enc.cpp @@ -81,9 +81,9 @@ namespace Botan { /* -* Get a S2K algorithm by name +* Get a PBKDF algorithm by name */ -S2K* get_s2k(const std::string& algo_spec) +PBKDF* get_pbkdf(const std::string& algo_spec) { SCAN_Name request(algo_spec); diff --git a/src/libstate/info.txt b/src/libstate/info.txt index 0829506fb..749b6afaf 100644 --- a/src/libstate/info.txt +++ b/src/libstate/info.txt @@ -35,10 +35,10 @@ mac mode_pad mutex noop_mutex +pbkdf pk_pad pubkey rng -s2k stream system_alloc </requires> diff --git a/src/libstate/lookup.h b/src/libstate/lookup.h index debcee52b..178f80428 100644 --- a/src/libstate/lookup.h +++ b/src/libstate/lookup.h @@ -15,7 +15,7 @@ #include <botan/kdf.h> #include <botan/eme.h> #include <botan/emsa.h> -#include <botan/s2k.h> +#include <botan/pbkdf.h> namespace Botan { @@ -130,11 +130,21 @@ inline MessageAuthenticationCode* get_mac(const std::string& algo_spec) } /** -* String to key algorithm factory method. -* @param algo_spec the name of the desired string to key (S2K) algorithm -* @return pointer to the string to key algorithm object +* Password based key derivation function factory method +* @param algo_spec the name of the desired PBKDF algorithm +* @return pointer to newly allocated object of that type */ -BOTAN_DLL S2K* get_s2k(const std::string& algo_spec); +BOTAN_DLL PBKDF* get_pbkdf(const std::string& algo_spec); + +/** +* @deprecated Use get_pbkdf +* @param algo_spec the name of the desired algorithm +* @return pointer to newly allocated object of that type +*/ +inline PBKDF* get_s2k(const std::string& algo_spec) + { + return get_pbkdf(algo_spec); + } /* * Get an EMSA/EME/KDF/MGF function @@ -145,7 +155,7 @@ BOTAN_DLL S2K* get_s2k(const std::string& algo_spec); /** * Factory method for EME (message-encoding methods for encryption) objects * @param algo_spec the name of the EME to create -* @return pointer to the desired EME object +* @return pointer to newly allocated object of that type */ BOTAN_DLL EME* get_eme(const std::string& algo_spec); @@ -153,14 +163,14 @@ BOTAN_DLL EME* get_eme(const std::string& algo_spec); * Factory method for EMSA (message-encoding methods for signatures * with appendix) objects * @param algo_spec the name of the EME to create -* @return pointer to the desired EME object +* @return pointer to newly allocated object of that type */ BOTAN_DLL EMSA* get_emsa(const std::string& algo_spec); /** * Factory method for KDF (key derivation function) * @param algo_spec the name of the KDF to create -* @return pointer to the desired KDF object +* @return pointer to newly allocated object of that type */ BOTAN_DLL KDF* get_kdf(const std::string& algo_spec); @@ -176,7 +186,7 @@ BOTAN_DLL KDF* get_kdf(const std::string& algo_spec); * @param iv the initialization vector to be used * @param direction determines whether the filter will be an encrypting * or decrypting filter -* @return pointer to the encryption or decryption filter +* @return pointer to newly allocated encryption or decryption filter */ BOTAN_DLL Keyed_Filter* get_cipher(const std::string& algo_spec, const SymmetricKey& key, diff --git a/src/s2k/info.txt b/src/pbkdf/info.txt index 861b6f760..861b6f760 100644 --- a/src/s2k/info.txt +++ b/src/pbkdf/info.txt diff --git a/src/s2k/s2k.h b/src/pbkdf/pbkdf.h index 59e789a15..eaad1fca9 100644 --- a/src/s2k/s2k.h +++ b/src/pbkdf/pbkdf.h @@ -1,33 +1,34 @@ /* -* S2K +* PBKDF * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ -#ifndef BOTAN_S2K_H__ -#define BOTAN_S2K_H__ +#ifndef BOTAN_PBKDF_H__ +#define BOTAN_PBKDF_H__ #include <botan/symkey.h> namespace Botan { /** -* Base class for S2K (string to key) operations, which convert a -* password/passphrase into a key +* Base class for PBKDF (password based key derivation function) +* implementations. Converts a password into a key using a salt +* and iterated hashing to make brute force attacks harder. */ -class BOTAN_DLL S2K +class BOTAN_DLL PBKDF { public: /** * @return new instance of this same algorithm */ - virtual S2K* clone() const = 0; + virtual PBKDF* clone() const = 0; /** * Get the algorithm name. - * @return name of this S2K algorithm + * @return name of this PBKDF algorithm */ virtual std::string name() const = 0; @@ -37,7 +38,7 @@ class BOTAN_DLL S2K virtual void clear() {} /** - * Derive a key from a passphrase with this S2K object. It will use + * Derive a key from a passphrase with this PBKDF object. It will use * the salt value and number of iterations configured in this object. * @param output_len the desired length of the key to produce * @param passphrase the password to derive the key from @@ -50,13 +51,18 @@ class BOTAN_DLL S2K const byte salt[], u32bit salt_len, u32bit iterations) const = 0; - S2K() {} - virtual ~S2K() {} + PBKDF() {} + virtual ~PBKDF() {} private: - S2K(const S2K&) {} - S2K& operator=(const S2K&) { return (*this); } + PBKDF(const PBKDF&) {} + PBKDF& operator=(const PBKDF&) { return (*this); } }; +/** +* For compatability with 1.8 +*/ +typedef PBKDF S2K; + } #endif diff --git a/src/s2k/pbkdf1/info.txt b/src/pbkdf/pbkdf1/info.txt index e51b44886..e51b44886 100644 --- a/src/s2k/pbkdf1/info.txt +++ b/src/pbkdf/pbkdf1/info.txt diff --git a/src/s2k/pbkdf1/pbkdf1.cpp b/src/pbkdf/pbkdf1/pbkdf1.cpp index a8270e26f..02d2c6cc0 100644 --- a/src/s2k/pbkdf1/pbkdf1.cpp +++ b/src/pbkdf/pbkdf1/pbkdf1.cpp @@ -37,20 +37,4 @@ OctetString PKCS5_PBKDF1::derive_key(u32bit key_len, return OctetString(key, std::min(key_len, key.size())); } -/* -* Clone this type -*/ -S2K* PKCS5_PBKDF1::clone() const - { - return new PKCS5_PBKDF1(hash->clone()); - } - -/* -* Return the name of this type -*/ -std::string PKCS5_PBKDF1::name() const - { - return "PBKDF1(" + hash->name() + ")"; - } - } diff --git a/src/s2k/pbkdf1/pbkdf1.h b/src/pbkdf/pbkdf1/pbkdf1.h index c0508d127..d10536f7e 100644 --- a/src/s2k/pbkdf1/pbkdf1.h +++ b/src/pbkdf/pbkdf1/pbkdf1.h @@ -8,25 +8,19 @@ #ifndef BOTAN_PBKDF1_H__ #define BOTAN_PBKDF1_H__ -#include <botan/s2k.h> +#include <botan/pbkdf.h> #include <botan/hash.h> namespace Botan { /** -* This class implements the PKCS #5 PBKDF1 functionality. +* PKCS #5 v1 PBKDF, aka PBKDF1 +* Can only generate a key up to the size of the hash output. +* Unless needed for backwards compatability, use PKCS5_PBKDF2 */ -class BOTAN_DLL PKCS5_PBKDF1 : public S2K +class BOTAN_DLL PKCS5_PBKDF1 : public PBKDF { public: - 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_in pointer to a hash function object to use @@ -38,9 +32,24 @@ class BOTAN_DLL PKCS5_PBKDF1 : public S2K * @param other the object to copy */ PKCS5_PBKDF1(const PKCS5_PBKDF1& other) : - S2K(), hash(other.hash->clone()) {} + PBKDF(), hash(other.hash->clone()) {} ~PKCS5_PBKDF1() { delete hash; } + + std::string name() const + { + return "PBKDF1(" + hash->name() + ")"; + } + + PBKDF* clone() const + { + return new PKCS5_PBKDF1(hash->clone()); + } + + OctetString derive_key(u32bit output_len, + const std::string& passphrase, + const byte salt[], u32bit salt_len, + u32bit iterations) const; private: HashFunction* hash; }; diff --git a/src/s2k/pbkdf2/info.txt b/src/pbkdf/pbkdf2/info.txt index 5462b2e1b..5462b2e1b 100644 --- a/src/s2k/pbkdf2/info.txt +++ b/src/pbkdf/pbkdf2/info.txt diff --git a/src/s2k/pbkdf2/pbkdf2.cpp b/src/pbkdf/pbkdf2/pbkdf2.cpp index f1fc6e29f..e88a5749a 100644 --- a/src/s2k/pbkdf2/pbkdf2.cpp +++ b/src/pbkdf/pbkdf2/pbkdf2.cpp @@ -12,7 +12,7 @@ namespace Botan { /* -* Return a PKCS#5 PBKDF2 derived key +* Return a PKCS #5 PBKDF2 derived key */ OctetString PKCS5_PBKDF2::derive_key(u32bit key_len, const std::string& passphrase, @@ -59,24 +59,4 @@ OctetString PKCS5_PBKDF2::derive_key(u32bit key_len, return key; } -/* -* Return the name of this type -*/ -std::string PKCS5_PBKDF2::name() const - { - return "PBKDF2(" + mac->name() + ")"; - } - -S2K* PKCS5_PBKDF2::clone() const - { - return new PKCS5_PBKDF2(mac->clone()); - } - -/* -* PKCS5_PBKDF2 Constructor -*/ -PKCS5_PBKDF2::PKCS5_PBKDF2(MessageAuthenticationCode* m) : mac(m) {} - -PKCS5_PBKDF2::~PKCS5_PBKDF2() { delete mac; } - } diff --git a/src/s2k/pbkdf2/pbkdf2.h b/src/pbkdf/pbkdf2/pbkdf2.h index b6d231916..2b25a7b1d 100644 --- a/src/s2k/pbkdf2/pbkdf2.h +++ b/src/pbkdf/pbkdf2/pbkdf2.h @@ -8,19 +8,26 @@ #ifndef BOTAN_PBKDF2_H__ #define BOTAN_PBKDF2_H__ -#include <botan/s2k.h> +#include <botan/pbkdf.h> #include <botan/mac.h> namespace Botan { /** -* This class implements the PKCS #5 PBKDF2 functionality. +* PKCS #5 PBKDF2 */ -class BOTAN_DLL PKCS5_PBKDF2 : public S2K +class BOTAN_DLL PKCS5_PBKDF2 : public PBKDF { public: - std::string name() const; - S2K* clone() const; + std::string name() const + { + return "PBKDF2(" + mac->name() + ")"; + } + + PBKDF* clone() const + { + return new PKCS5_PBKDF2(mac->clone()); + } OctetString derive_key(u32bit output_len, const std::string& passphrase, @@ -31,8 +38,12 @@ class BOTAN_DLL PKCS5_PBKDF2 : public S2K * Create a PKCS #5 instance using the specified message auth code * @param mac the MAC to use */ - PKCS5_PBKDF2(MessageAuthenticationCode* mac); - ~PKCS5_PBKDF2(); + PKCS5_PBKDF2(MessageAuthenticationCode* m) : mac(m) {} + + /** + * Destructor + */ + ~PKCS5_PBKDF2() { delete mac; } private: MessageAuthenticationCode* mac; }; diff --git a/src/s2k/pgps2k/info.txt b/src/pbkdf/pgps2k/info.txt index 8be9c79f8..8be9c79f8 100644 --- a/src/s2k/pgps2k/info.txt +++ b/src/pbkdf/pgps2k/info.txt diff --git a/src/s2k/pgps2k/pgp_s2k.cpp b/src/pbkdf/pgps2k/pgp_s2k.cpp index 49ff6892c..db18adaf1 100644 --- a/src/s2k/pgps2k/pgp_s2k.cpp +++ b/src/pbkdf/pgps2k/pgp_s2k.cpp @@ -6,8 +6,6 @@ */ #include <botan/pgp_s2k.h> -#include <algorithm> -#include <memory> namespace Botan { @@ -56,20 +54,4 @@ OctetString OpenPGP_S2K::derive_key(u32bit key_len, return key; } -/* -* Return the name of this type -*/ -std::string OpenPGP_S2K::name() const - { - return "OpenPGP-S2K(" + hash->name() + ")"; - } - -/* -* Return a clone of this object -*/ -S2K* OpenPGP_S2K::clone() const - { - return new OpenPGP_S2K(hash->clone()); - } - } diff --git a/src/s2k/pgps2k/pgp_s2k.h b/src/pbkdf/pgps2k/pgp_s2k.h index cfe9bf5d5..9fb09af5a 100644 --- a/src/s2k/pgps2k/pgp_s2k.h +++ b/src/pbkdf/pgps2k/pgp_s2k.h @@ -1,5 +1,5 @@ /* -* OpenPGP S2K +* OpenPGP PBKDF * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license @@ -8,7 +8,7 @@ #ifndef BOTAN_OPENPGP_S2K_H__ #define BOTAN_OPENPGP_S2K_H__ -#include <botan/s2k.h> +#include <botan/pbkdf.h> #include <botan/hash.h> namespace Botan { @@ -16,22 +16,30 @@ namespace Botan { /** * OpenPGP's S2K */ -class BOTAN_DLL OpenPGP_S2K : public S2K +class BOTAN_DLL OpenPGP_S2K : public PBKDF { public: - 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; - /** * @param hash_in the hash function to use */ OpenPGP_S2K(HashFunction* hash_in) : hash(hash_in) {} + ~OpenPGP_S2K() { delete hash; } + + std::string name() const + { + return "OpenPGP-S2K(" + hash->name() + ")"; + } + + PBKDF* clone() const + { + return new OpenPGP_S2K(hash->clone()); + } + + OctetString derive_key(u32bit output_len, + const std::string& passphrase, + const byte salt[], u32bit salt_len, + u32bit iterations) const; private: HashFunction* hash; }; diff --git a/src/wrap/sqlite/codec.cpp b/src/wrap/sqlite/codec.cpp index 5dfcea82e..60c8f6a21 100644 --- a/src/wrap/sqlite/codec.cpp +++ b/src/wrap/sqlite/codec.cpp @@ -54,12 +54,12 @@ Codec::InitializeCodec(void *db) void Codec::GenerateWriteKey(const char* userPassword, int passwordLength) { - S2K* s2k = get_s2k(S2K_STR); - s2k->set_iterations(S2K_ITERATIONS); - s2k->change_salt((const byte*)SALT_STR.c_str(), SALT_SIZE); + PBKDF* pbkdf = get_pbkdf(PBKDF_STR); + pbkdf->set_iterations(PBKDF_ITERATIONS); + pbkdf->change_salt((const byte*)SALT_STR.c_str(), SALT_SIZE); SymmetricKey masterKey = - s2k->derive_key(KEY_SIZE + IV_DERIVATION_KEY_SIZE, std::string(userPassword, passwordLength)); + pbkdf->derive_key(KEY_SIZE + IV_DERIVATION_KEY_SIZE, std::string(userPassword, passwordLength)); m_writeKey = SymmetricKey(masterKey.bits_of(), KEY_SIZE); m_ivWriteKey = SymmetricKey(masterKey.bits_of() + KEY_SIZE, IV_DERIVATION_KEY_SIZE); diff --git a/src/wrap/sqlite/codec.h b/src/wrap/sqlite/codec.h index 8b753be62..c254f9fde 100644 --- a/src/wrap/sqlite/codec.h +++ b/src/wrap/sqlite/codec.h @@ -50,9 +50,9 @@ using namespace Botan; //make sure to add "/NoPadding" for modes that use padding schemes const string BLOCK_CIPHER_STR = "Twofish/XTS"; -//S2K_STR: Key derivation function used to derive both the encryption +//PBKDF_STR: Key derivation function used to derive both the encryption //and IV derivation keys from the given database passphrase -const string S2K_STR = "PBKDF2(SHA-160)"; +const string PBKDF_STR = "PBKDF2(SHA-160)"; //SALT_STR: Hard coded salt used to derive the key from the passphrase. const string SALT_STR = "&g#nB'9]"; @@ -61,9 +61,9 @@ const string SALT_STR = "&g#nB'9]"; //encryption const string MAC_STR = "CMAC(Twofish)"; -//S2K_ITERATIONS: Number of hash iterations used in the key derivation +//PBKDF_ITERATIONS: Number of hash iterations used in the key derivation //process. -const int S2K_ITERATIONS = 10000; +const int PBKDF_ITERATIONS = 10000; //SALT_SIZE: Size of the salt in bytes (as given in SALT_STR) const int SALT_SIZE = 64/8; //64 bit, 8 byte salt |