diff options
Diffstat (limited to 'doc')
-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 |
7 files changed, 72 insertions, 70 deletions
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); |