aboutsummaryrefslogtreecommitdiffstats
path: root/src/cli/cc_enc.cpp
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2015-12-19 15:36:40 -0500
committerJack Lloyd <[email protected]>2015-12-19 15:36:40 -0500
commitb48e6fb097c62bb246629ee7a182c57e497e4130 (patch)
tree0cb8ea2d05a89f5e90467f323ae56268d4d3480e /src/cli/cc_enc.cpp
parentd774a9edc46ffcebb28205a678058f083ea75c28 (diff)
CLI rewrite
The command line tools' origin as a collection of examples and test programs glued together led to some unfortunate problems; lots of hardcoded values, missing parameters, and obsolete crypto. Adds a small library for writing command line programs of the sort needed here (cli.h), which cuts the length of many of the commands in half and makes commands more pleasant to write and extend. Generalizes a lot of the commands also, eg previously only signing/verification with DSA/SHA-1 was included! Removes the fuzzer entry point since that's fairly useless outside of an instrumented build. Removes the in-library API for benchmarking.
Diffstat (limited to 'src/cli/cc_enc.cpp')
-rw-r--r--src/cli/cc_enc.cpp161
1 files changed, 161 insertions, 0 deletions
diff --git a/src/cli/cc_enc.cpp b/src/cli/cc_enc.cpp
new file mode 100644
index 000000000..25c9b960b
--- /dev/null
+++ b/src/cli/cc_enc.cpp
@@ -0,0 +1,161 @@
+/*
+* (C) 2014,2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "cli.h"
+#include <botan/hex.h>
+
+#if defined(BOTAN_HAS_FPE_FE1) && defined(BOTAN_HAS_PBKDF)
+
+#include <botan/fpe_fe1.h>
+#include <botan/pbkdf.h>
+
+namespace Botan_CLI {
+
+namespace {
+
+uint8_t luhn_checksum(uint64_t cc_number)
+ {
+ uint8_t sum = 0;
+
+ bool alt = false;
+ while(cc_number)
+ {
+ uint8_t digit = cc_number % 10;
+ if(alt)
+ {
+ digit *= 2;
+ if(digit > 9)
+ digit -= 9;
+ }
+
+ sum += digit;
+
+ cc_number /= 10;
+ alt = !alt;
+ }
+
+ return (sum % 10);
+ }
+
+bool luhn_check(uint64_t cc_number)
+ {
+ return (luhn_checksum(cc_number) == 0);
+ }
+
+uint64_t cc_rank(uint64_t cc_number)
+ {
+ // Remove Luhn checksum
+ return cc_number / 10;
+ }
+
+uint64_t cc_derank(uint64_t cc_number)
+ {
+ for(size_t i = 0; i != 10; ++i)
+ {
+ if(luhn_check(cc_number * 10 + i))
+ {
+ return (cc_number * 10 + i);
+ }
+ }
+
+ return 0;
+ }
+
+uint64_t encrypt_cc_number(uint64_t cc_number,
+ const Botan::secure_vector<uint8_t>& key,
+ const std::vector<uint8_t>& tweak)
+ {
+ const Botan::BigInt n = 1000000000000000;
+
+ const uint64_t cc_ranked = cc_rank(cc_number);
+
+ const Botan::BigInt c = Botan::FPE::fe1_encrypt(n, cc_ranked, key, tweak);
+
+ if(c.bits() > 50)
+ throw std::runtime_error("FPE produced a number too large");
+
+ uint64_t enc_cc = 0;
+ for(size_t i = 0; i != 7; ++i)
+ enc_cc = (enc_cc << 8) | c.byte_at(6-i);
+ return cc_derank(enc_cc);
+ }
+
+uint64_t decrypt_cc_number(uint64_t enc_cc,
+ const Botan::secure_vector<uint8_t>& key,
+ const std::vector<uint8_t>& tweak)
+ {
+ const Botan::BigInt n = 1000000000000000;
+
+ const uint64_t cc_ranked = cc_rank(enc_cc);
+
+ const Botan::BigInt c = Botan::FPE::fe1_decrypt(n, cc_ranked, key, tweak);
+
+ if(c.bits() > 50)
+ throw CLI_Error("FPE produced a number too large");
+
+ uint64_t dec_cc = 0;
+ for(size_t i = 0; i != 7; ++i)
+ dec_cc = (dec_cc << 8) | c.byte_at(6-i);
+ return cc_derank(dec_cc);
+ }
+
+}
+
+class CC_Encrypt : public Command
+ {
+ public:
+ CC_Encrypt() : Command("cc_encrypt CC passphrase --tweak=") {}
+
+ void go()
+ {
+ const uint64_t cc_number = std::stoull(get_arg("CC"));
+ const std::vector<uint8_t> tweak = Botan::hex_decode(get_arg("tweak"));
+ const std::string pass = get_arg("passphrase");
+
+ std::unique_ptr<Botan::PBKDF> pbkdf(Botan::PBKDF::create("PBKDF2(SHA-256)"));
+ if(!pbkdf)
+ throw CLI_Error_Unsupported("PBKDF", "PBKDF2(SHA-256)");
+
+ Botan::secure_vector<uint8_t> key =
+ pbkdf->pbkdf_iterations(32, pass,
+ tweak.data(), tweak.size(),
+ 100000);
+
+ output() << encrypt_cc_number(cc_number, key, tweak) << "\n";
+ }
+ };
+
+BOTAN_REGISTER_COMMAND(CC_Encrypt);
+
+class CC_Decrypt : public Command
+ {
+ public:
+ CC_Decrypt() : Command("cc_decrypt CC passphrase --tweak=") {}
+
+ void go() override
+ {
+ const uint64_t cc_number = std::stoull(get_arg("CC"));
+ const std::vector<uint8_t> tweak = Botan::hex_decode(get_arg("tweak"));
+ const std::string pass = get_arg("passphrase");
+
+ std::unique_ptr<Botan::PBKDF> pbkdf(Botan::PBKDF::create("PBKDF2(SHA-256)"));
+ if(!pbkdf)
+ throw CLI_Error_Unsupported("PBKDF", "PBKDF2(SHA-256)");
+
+ Botan::secure_vector<uint8_t> key =
+ pbkdf->pbkdf_iterations(32, pass,
+ tweak.data(), tweak.size(),
+ 100000);
+
+ output() << decrypt_cc_number(cc_number, key, tweak) << "\n";
+ }
+ };
+
+BOTAN_REGISTER_COMMAND(CC_Decrypt);
+
+}
+
+#endif // FPE && PBKDF