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

randombit / botan / 16055899095

03 Jul 2025 04:34PM UTC coverage: 90.571% (-0.003%) from 90.574%
16055899095

push

github

web-flow
Merge pull request #4931 from randombit/jack/moar-tidy

Address various warnings from clang-tidy

99050 of 109362 relevant lines covered (90.57%)

12478386.65 hits per line

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

94.2
/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
   #include <botan/symkey.h>
15

16
namespace Botan_CLI {
17

18
namespace {
19

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

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

33
      sum += digit;
272✔
34

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

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

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

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

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

58
   return 0;
59
}
60

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

64
   const Botan::BigInt c = Botan::FPE::fe1_encrypt(n, Botan::BigInt::from_u64(cc_rank(cc_number)), key, tweak);
1✔
65

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

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

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

80
   const Botan::BigInt c = Botan::FPE::fe1_decrypt(n, Botan::BigInt::from_u64(cc_rank(enc_cc)), key, tweak);
1✔
81

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

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

93
}  // namespace
94

95
class CC_Encrypt final : public Command {
96
   public:
97
      CC_Encrypt() : Command("cc_encrypt CC passphrase --tweak=") {}
4✔
98

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

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

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

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

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

117
         output() << encrypt_cc_number(cc_number, key, tweak) << "\n";
1✔
118
      }
3✔
119
};
120

121
BOTAN_REGISTER_COMMAND("cc_encrypt", CC_Encrypt);
2✔
122

123
class CC_Decrypt final : public Command {
124
   public:
125
      CC_Decrypt() : Command("cc_decrypt CC passphrase --tweak=") {}
4✔
126

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

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

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

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

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

145
         output() << decrypt_cc_number(cc_number, key, tweak) << "\n";
1✔
146
      }
3✔
147
};
148

149
BOTAN_REGISTER_COMMAND("cc_decrypt", CC_Decrypt);
2✔
150

151
}  // namespace Botan_CLI
152

153
#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

© 2026 Coveralls, Inc