From 67fc02d47f52987df5060142782d1aea2dd65436 Mon Sep 17 00:00:00 2001 From: lloyd Date: Wed, 24 Sep 2008 12:49:29 +0000 Subject: Add an example database row encryptor --- doc/examples/row_encryptor.cpp | 134 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 doc/examples/row_encryptor.cpp (limited to 'doc/examples/row_encryptor.cpp') diff --git a/doc/examples/row_encryptor.cpp b/doc/examples/row_encryptor.cpp new file mode 100644 index 000000000..dc15ee6c4 --- /dev/null +++ b/doc/examples/row_encryptor.cpp @@ -0,0 +1,134 @@ +#include +#include +#include +#include + +#include +#include +#include + +using namespace Botan; + +/** +Encrypt and decrypt small rows +*/ +class Row_Encryptor + { + public: + Row_Encryptor(const std::string& passphrase, + RandomNumberGenerator& rng); + + std::string encrypt(const std::string& input, + const MemoryRegion& salt); + + std::string decrypt(const std::string& input, + const MemoryRegion& salt); + + private: + Row_Encryptor(const Row_Encryptor&) {} + Row_Encryptor& operator=(const Row_Encryptor&) { return (*this); } + + Pipe enc_pipe, dec_pipe; + EAX_Encryption* eax_enc; // owned by enc_pipe + EAX_Decryption* eax_dec; // owned by dec_pipe; + }; + +Row_Encryptor::Row_Encryptor(const std::string& passphrase, + RandomNumberGenerator& rng) + { + std::auto_ptr s2k(get_s2k("PBKDF2(SHA-160)")); + + s2k->set_iterations(10000); + + s2k->new_random_salt(rng, 10); // 10 bytes == 80 bits + + SecureVector key = s2k->derive_key(32, passphrase).bits_of(); + + /* + Save pointers to the EAX objects so we can change the IV as needed + */ + enc_pipe.append(eax_enc = new EAX_Encryption("Serpent")); + dec_pipe.append(eax_dec = new EAX_Decryption("Serpent")); + + eax_enc->set_key(key); + eax_dec->set_key(key); + } + +std::string Row_Encryptor::encrypt(const std::string& input, + const MemoryRegion& salt) + { + eax_enc->set_iv(salt); + + enc_pipe.start_msg(); + enc_pipe.write(input); + enc_pipe.end_msg(); + + return enc_pipe.read_all_as_string(Pipe::LAST_MESSAGE); + } + +std::string Row_Encryptor::decrypt(const std::string& input, + const MemoryRegion& salt) + { + eax_dec->set_iv(salt); + + dec_pipe.start_msg(); + dec_pipe.write(input); + dec_pipe.end_msg(); + + return dec_pipe.read_all_as_string(Pipe::LAST_MESSAGE); + } + +/************************* + Test code follows: +*/ + +#include + +int main() + { + LibraryInitializer init; + + std::auto_ptr rng(RandomNumberGenerator::make_rng()); + + Row_Encryptor encryptor("secret passphrase", *rng); + + std::vector original_inputs; + + for(u32bit i = 0; i != 15000; ++i) + { + std::ostringstream out; + + // This will actually generate variable length inputs (when + // there are leading 0s, which are skipped), which is good + // since it assures performance is OK across a mix of lengths + // TODO: Maybe randomize the length slightly? + + for(u32bit j = 0; j != 32; ++j) + out << std::hex << (int)rng->next_byte(); + + original_inputs.push_back(out.str()); + } + + std::vector encrypted_values; + MemoryVector salt(4); // keep out of loop to avoid excessive dynamic allocation + + for(u32bit i = 0; i != original_inputs.size(); ++i) + { + std::string input = original_inputs[i]; + store_le(i, salt); + + encrypted_values.push_back(encryptor.encrypt(input, salt)); + } + + for(u32bit i = 0; i != encrypted_values.size(); ++i) + { + std::string ciphertext = encrypted_values[i]; + store_le(i, salt); // NOTE: same salt value as previous loop (index value) + + std::string output = encryptor.decrypt(ciphertext, salt); + + if(output != original_inputs[i]) + std::cout << "BOOM " << i << "\n"; + } + + } -- cgit v1.2.3