diff options
Diffstat (limited to 'src/cli/fpe.cpp')
-rw-r--r-- | src/cli/fpe.cpp | 153 |
1 files changed, 0 insertions, 153 deletions
diff --git a/src/cli/fpe.cpp b/src/cli/fpe.cpp deleted file mode 100644 index 10b3096bf..000000000 --- a/src/cli/fpe.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* -* (C) 2014,2015 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include "apps.h" - -#if defined(BOTAN_HAS_FPE_FE1) && defined(BOTAN_HAS_SHA1) - -#include <botan/fpe_fe1.h> -#include <botan/sha160.h> - -using namespace Botan; - -namespace { - -byte luhn_checksum(u64bit cc_number) - { - byte sum = 0; - - bool alt = false; - while(cc_number) - { - byte 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(u64bit cc_number) - { - return (luhn_checksum(cc_number) == 0); - } - -u64bit cc_rank(u64bit cc_number) - { - // Remove Luhn checksum - return cc_number / 10; - } - -u64bit cc_derank(u64bit cc_number) - { - for(u32bit i = 0; i != 10; ++i) - if(luhn_check(cc_number * 10 + i)) - return (cc_number * 10 + i); - return 0; - } - -/* -* Use the SHA-1 hash of the account name or ID as a tweak -*/ -std::vector<byte> sha1(const std::string& acct_name) - { - SHA_160 hash; - hash.update(acct_name); - return unlock(hash.final()); - } - -u64bit encrypt_cc_number(u64bit cc_number, - const SymmetricKey& key, - const std::string& acct_name) - { - BigInt n = 1000000000000000; - - u64bit cc_ranked = cc_rank(cc_number); - - BigInt c = FPE::fe1_encrypt(n, cc_ranked, key, sha1(acct_name)); - - if(c.bits() > 50) - throw std::runtime_error("FPE produced a number too large"); - - u64bit enc_cc = 0; - for(u32bit i = 0; i != 7; ++i) - enc_cc = (enc_cc << 8) | c.byte_at(6-i); - return cc_derank(enc_cc); - } - -u64bit decrypt_cc_number(u64bit enc_cc, - const SymmetricKey& key, - const std::string& acct_name) - { - BigInt n = 1000000000000000; - - u64bit cc_ranked = cc_rank(enc_cc); - - BigInt c = FPE::fe1_decrypt(n, cc_ranked, key, sha1(acct_name)); - - if(c.bits() > 50) - throw std::runtime_error("FPE produced a number too large"); - - u64bit dec_cc = 0; - for(u32bit i = 0; i != 7; ++i) - dec_cc = (dec_cc << 8) | c.byte_at(6-i); - return cc_derank(dec_cc); - } - -int fpe(const std::vector<std::string> &args) - { - if(args.size() != 4) - { - std::cout << "Usage: " << args[0] << " cc-number acct-name passwd" << std::endl; - return 1; - } - - u64bit cc_number = atoll(args[1].c_str()); - std::string acct_name = args[2]; - std::string passwd = args[3]; - - std::cout << "Input was: " << cc_number << ' ' - << luhn_check(cc_number) << std::endl; - - /* - * In practice something like PBKDF2 with a salt and high iteration - * count would be a good idea. - */ - SymmetricKey key(sha1(passwd)); - - u64bit enc_cc = encrypt_cc_number(cc_number, key, acct_name); - - std::cout << "Encrypted: " << enc_cc - << ' ' << luhn_check(enc_cc) << std::endl; - - u64bit dec_cc = decrypt_cc_number(enc_cc, key, acct_name); - - std::cout << "Decrypted: " << dec_cc - << ' ' << luhn_check(dec_cc) << std::endl; - - if(dec_cc != cc_number) - { - std::cout << "Something went wrong :( Bad CC checksum?" << std::endl; - return 2; - } - - return 0; - } - -REGISTER_APP(fpe); - -} - -#endif // BOTAN_HAS_FPE_FE1 && BOTAN_HAS_SHA1 |