• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5230455705

10 Jun 2023 02:30PM UTC coverage: 91.715% (-0.03%) from 91.746%
5230455705

push

github

randombit
Merge GH #3584 Change clang-format AllowShortFunctionsOnASingleLine config from All to Inline

77182 of 84154 relevant lines covered (91.72%)

11975295.43 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.37
/src/cli/cc_enc.cpp
1
/*
2
* (C) 2014,2015 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "cli.h"
8
#include <botan/hex.h>
9

10
#if defined(BOTAN_HAS_FPE_FE1) && defined(BOTAN_HAS_PBKDF)
11

12
   #include <botan/fpe_fe1.h>
13
   #include <botan/pbkdf.h>
14

15
namespace Botan_CLI {
16

17
namespace {
18

19
uint8_t luhn_checksum(uint64_t cc_number) {
17✔
20
   uint8_t sum = 0;
17✔
21

22
   bool alt = false;
17✔
23
   while(cc_number) {
289✔
24
      uint8_t digit = cc_number % 10;
272✔
25
      if(alt) {
272✔
26
         digit *= 2;
136✔
27
         if(digit > 9) {
136✔
28
            digit -= 9;
60✔
29
         }
30
      }
31

32
      sum += digit;
272✔
33

34
      cc_number /= 10;
272✔
35
      alt = !alt;
272✔
36
   }
37

38
   return (sum % 10);
17✔
39
}
40

41
bool luhn_check(uint64_t cc_number) {
17✔
42
   return (luhn_checksum(cc_number) == 0);
17✔
43
}
44

45
uint64_t cc_rank(uint64_t cc_number) {
2✔
46
   // Remove Luhn checksum
47
   return cc_number / 10;
2✔
48
}
49

50
uint64_t cc_derank(uint64_t cc_number) {
2✔
51
   for(size_t i = 0; i != 10; ++i) {
17✔
52
      if(luhn_check(cc_number * 10 + i)) {
34✔
53
         return (cc_number * 10 + i);
2✔
54
      }
55
   }
56

57
   return 0;
58
}
59

60
uint64_t encrypt_cc_number(uint64_t cc_number, const Botan::SymmetricKey& key, const std::vector<uint8_t>& tweak) {
1✔
61
   const Botan::BigInt n = 1000000000000000;
1✔
62

63
   const uint64_t cc_ranked = cc_rank(cc_number);
1✔
64

65
   const Botan::BigInt c = Botan::FPE::fe1_encrypt(n, cc_ranked, key, tweak);
1✔
66

67
   if(c.bits() > 50) {
1✔
68
      throw Botan::Internal_Error("FPE produced a number too large");
×
69
   }
70

71
   uint64_t enc_cc = 0;
72
   for(size_t i = 0; i != 7; ++i) {
8✔
73
      enc_cc = (enc_cc << 8) | c.byte_at(6 - i);
7✔
74
   }
75
   return cc_derank(enc_cc);
1✔
76
}
2✔
77

78
uint64_t decrypt_cc_number(uint64_t enc_cc, const Botan::SymmetricKey& key, const std::vector<uint8_t>& tweak) {
1✔
79
   const Botan::BigInt n = 1000000000000000;
1✔
80

81
   const uint64_t cc_ranked = cc_rank(enc_cc);
1✔
82

83
   const Botan::BigInt c = Botan::FPE::fe1_decrypt(n, cc_ranked, key, tweak);
1✔
84

85
   if(c.bits() > 50) {
1✔
86
      throw CLI_Error("FPE produced a number too large");
×
87
   }
88

89
   uint64_t dec_cc = 0;
90
   for(size_t i = 0; i != 7; ++i) {
8✔
91
      dec_cc = (dec_cc << 8) | c.byte_at(6 - i);
7✔
92
   }
93
   return cc_derank(dec_cc);
1✔
94
}
2✔
95

96
}  // namespace
97

98
class CC_Encrypt final : public Command {
99
   public:
100
      CC_Encrypt() : Command("cc_encrypt CC passphrase --tweak=") {}
4✔
101

102
      std::string group() const override { return "misc"; }
1✔
103

104
      std::string description() const override {
1✔
105
         return "Encrypt the passed valid credit card number using FPE encryption";
1✔
106
      }
107

108
      void go() override {
1✔
109
         const uint64_t cc_number = std::stoull(get_arg("CC"));
3✔
110
         const std::vector<uint8_t> tweak = Botan::hex_decode(get_arg("tweak"));
2✔
111
         const std::string pass = get_arg("passphrase");
1✔
112

113
         auto pbkdf = Botan::PBKDF::create("PBKDF2(SHA-256)");
1✔
114
         if(!pbkdf) {
1✔
115
            throw CLI_Error_Unsupported("PBKDF", "PBKDF2(SHA-256)");
×
116
         }
117

118
         auto key = Botan::SymmetricKey(pbkdf->pbkdf_iterations(32, pass, tweak.data(), tweak.size(), 100000));
1✔
119

120
         output() << encrypt_cc_number(cc_number, key, tweak) << "\n";
1✔
121
      }
3✔
122
};
123

124
BOTAN_REGISTER_COMMAND("cc_encrypt", CC_Encrypt);
2✔
125

126
class CC_Decrypt final : public Command {
127
   public:
128
      CC_Decrypt() : Command("cc_decrypt CC passphrase --tweak=") {}
4✔
129

130
      std::string group() const override { return "misc"; }
1✔
131

132
      std::string description() const override {
1✔
133
         return "Decrypt the passed valid ciphertext credit card number using FPE decryption";
1✔
134
      }
135

136
      void go() override {
1✔
137
         const uint64_t cc_number = std::stoull(get_arg("CC"));
3✔
138
         const std::vector<uint8_t> tweak = Botan::hex_decode(get_arg("tweak"));
2✔
139
         const std::string pass = get_arg("passphrase");
1✔
140

141
         auto pbkdf = Botan::PBKDF::create("PBKDF2(SHA-256)");
1✔
142
         if(!pbkdf) {
1✔
143
            throw CLI_Error_Unsupported("PBKDF", "PBKDF2(SHA-256)");
×
144
         }
145

146
         auto key = Botan::SymmetricKey(pbkdf->pbkdf_iterations(32, pass, tweak.data(), tweak.size(), 100000));
1✔
147

148
         output() << decrypt_cc_number(cc_number, key, tweak) << "\n";
1✔
149
      }
3✔
150
};
151

152
BOTAN_REGISTER_COMMAND("cc_decrypt", CC_Decrypt);
2✔
153

154
}  // namespace Botan_CLI
155

156
#endif  // FPE && PBKDF
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc