diff options
author | Jack Lloyd <[email protected]> | 2015-09-22 12:10:24 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2015-09-29 17:57:50 -0400 |
commit | 2a6f5f10cc9713230bdd6204c57219451584f4a4 (patch) | |
tree | 804a78cbd34d69f01aed3a337fd4a693c59297bc /src/cmd | |
parent | ac9689990da914cd58788dab9d5e0d7bebb72e30 (diff) |
McEliece cleanups
Remove and consolidate various headers
Reduce memory usage of GF2m_Field by sharing the log and exponent
tables across all instances of a particular word size.
Remove McEliece_Public_Operation and McEliece_Private_Operation which
were difficult to use safely. Instead only the KEM operations are exposed.
Add McEliece_PublicKey::random_plaintext_element
Add command line `mce` tool and some McEliece documentation
Convert the speed program to check McEliece keys of the suggested size
Add McEliece KATs for both key generation and KEM
Fix HMAC_DRBG constructor which derefed a pointer before its time
Diffstat (limited to 'src/cmd')
-rw-r--r-- | src/cmd/implementation/speed_public_key.cpp | 19 | ||||
-rw-r--r-- | src/cmd/mce.cpp | 117 |
2 files changed, 127 insertions, 9 deletions
diff --git a/src/cmd/implementation/speed_public_key.cpp b/src/cmd/implementation/speed_public_key.cpp index 73bbd7c1e..83c0156ae 100644 --- a/src/cmd/implementation/speed_public_key.cpp +++ b/src/cmd/implementation/speed_public_key.cpp @@ -734,20 +734,21 @@ void benchmark_mce(RandomNumberGenerator& rng, Benchmark_Report& report) { const std::vector<std::pair<size_t, size_t>> params = { - { 1024, 35 }, - { 2048, 50 }, - { 2960, 56 }, + { 1632, 33 }, + { 2480, 45 }, + { 2960, 57 }, + { 3408, 67 }, + { 4264, 95 }, { 6624, 115 } }; const std::string algo_name = "McEliece"; - const std::string padding = "Raw"; for(auto& param : params) { Timer keygen_timer("keygen"); - Timer enc_timer(padding + " encrypt"); - Timer dec_timer(padding + " decrypt"); + Timer enc_timer("encrypt"); + Timer dec_timer("decrypt"); keygen_timer.start(); McEliece_PrivateKey priv_key(rng, param.first, param.second); @@ -776,9 +777,9 @@ void benchmark_mce(RandomNumberGenerator& rng, std::to_string(param.second); std::ostringstream keysize_report; - keysize_report << "(size " << pub_key.x509_subject_public_key().size() << " pub " - << priv_key.pkcs8_private_key().size() << " priv " - << pub_key.estimated_strength() << " work factor)"; + keysize_report << "(work factor " << pub_key.estimated_strength() << ", " + << "pub bytes " << pub_key.x509_subject_public_key().size() << " " + << "priv bytes " << priv_key.pkcs8_private_key().size() << ")"; report.report(nm + " " + keysize_report.str(), keygen_timer); report.report(nm, enc_timer); diff --git a/src/cmd/mce.cpp b/src/cmd/mce.cpp new file mode 100644 index 000000000..3b33df661 --- /dev/null +++ b/src/cmd/mce.cpp @@ -0,0 +1,117 @@ +#include "apps.h" + +#if defined(BOTAN_HAS_MCELIECE) + +#include <botan/mceliece.h> +#include <botan/mceies.h> +#include <botan/pkcs8.h> +#include <fstream> + +namespace { + +int mce(int argc, char* argv[]) + { + if(argc < 4) + { + std::cout << "Usage: " << argv[0] << " [keygen n t pass|keybits n t|encrypt file key|decrypt file key pass]\n"; + return 1; + } + + const std::string cmd = argv[1]; + + AutoSeeded_RNG rng; + + if(cmd == "keygen") + { + const size_t n = std::stol(argv[2]); + const size_t t = std::stol(argv[3]); + const std::string pass = argv[4]; + + McEliece_PrivateKey pk(rng, n, t); + + bool ok = pk.check_key(rng, true); + + if(!ok) + { + std::cout << "Keygen failed self-test\n"; + return 2; + } + + /* + secure_vector<byte> priv = PKCS8::BER_encode(pk); + std::vector<byte> pub = X509::BER_encode(pk); + std::cout << priv.size()/1024.0 << " " << pub.size()/1024.0 << "\n"; + */ + + std::ofstream pub_file("mce.pub"); + pub_file << X509::PEM_encode(pk); + pub_file.close(); + + std::ofstream priv_file("mce.priv"); + priv_file << PKCS8::PEM_encode(pk, rng, pass); + priv_file.close(); + } + else if(cmd == "keybits") + { + const size_t n = std::stol(argv[2]); + const size_t t = std::stol(argv[3]); + std::cout << "McEliece key with params (" << n << "," << t << ") has " + << mceliece_work_factor(n, t) << " bit security\n"; + } + else if(cmd == "encrypt") + { + std::unique_ptr<Public_Key> p8(X509::load_key(argv[3])); + const McEliece_PublicKey* key = dynamic_cast<McEliece_PublicKey*>(p8.get()); + + if(!key) + { + throw std::runtime_error("Loading McEliece public key failed"); + } + + const std::string input_path = argv[2]; + std::ifstream in(input_path, std::ios::binary); + std::string pt((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>()); + + secure_vector<byte> ct = mceies_encrypt(*key, + reinterpret_cast<const byte*>(pt.data()), + pt.size(), + nullptr, 0, rng, "AES-128/GCM"); + + std::cout << pt.size() << " -> " << ct.size() << "\n"; + + std::ofstream out(std::string(input_path) + ".ct", std::ios::binary); + out.write(reinterpret_cast<const char*>(ct.data()), ct.size()); + out.close(); + } + else if(cmd == "decrypt") + { + const std::string key_file = argv[3]; + const std::string pass = argv[4]; + std::unique_ptr<Private_Key> p8(PKCS8::load_key(key_file, rng, pass)); + const McEliece_PrivateKey* key = dynamic_cast<McEliece_PrivateKey*>(p8.get()); + + if(!key) + { + throw std::runtime_error("Loading McEliece private key failed"); + } + + std::ifstream in(argv[2], std::ios::binary); + std::string ct((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>()); + + secure_vector<byte> pt = mceies_decrypt(*key, + reinterpret_cast<const byte*>(ct.data()), + ct.size(), + nullptr, 0, "AES-128/GCM"); + + std::ofstream out("mce.plaintext", std::ios::binary); + out.write(reinterpret_cast<const char*>(pt.data()), pt.size()); + out.close(); + } + return 0; + } + +} + +REGISTER_APP(mce); + +#endif |