@@ -31,6 +31,8 @@ static constexpr int EXIT_INCORRECT_PASSWORD = 2;
3131static std::string password;
3232static std::unique_ptr<DumpKeysRunner> dump_keys_runner;
3333static KeyStore keyStore;
34+ bool printHeader = false ;
35+ bool dumpEncryptionHeader = false ;
3436
3537// / The key lookup callback gets called from the FileReader whenever it
3638// / encounters an encrypted file. It'll keep the keys around in a key store
@@ -125,14 +127,44 @@ void readKeyStoreFromStdin() {
125127 }
126128}
127129
130+ void print_header (std::string_view filename,
131+ std::optional<EncryptedFileHeader> header) {
132+ if (!printHeader) {
133+ return ;
134+ }
135+ std::cout << " File: " << filename << std::endl;
136+ if (header) {
137+ try {
138+ fmt::println (" Encrypted:" );
139+ fmt::println (" Key ID: {}" , header->get_id ());
140+ fmt::println (" Key Derivation: {}" ,
141+ header->get_key_derivation ());
142+ if (header->get_key_derivation () ==
143+ KeyDerivationMethod::PasswordBased) {
144+ fmt::println (" PBKDF2 Iterations: {}" ,
145+ header->get_pbkdf_iterations ());
146+ }
147+ fmt::println (" Compression: {}" , header->get_compression ());
148+ } catch (const std::exception&) {
149+ // Ignore errors
150+ }
151+ } else {
152+ if (dumpEncryptionHeader) {
153+ std::cout << " Not an encrypted file or unable to read "
154+ " encryption header"
155+ << std::endl;
156+ }
157+ }
158+ std::cout << std::string (70 , ' =' ) << std::endl;
159+ }
160+
128161int main (int argc, char ** argv) {
129162 using cb::getopt::Argument;
130163 cb::getopt::CommandLineOptionsParser parser;
131164
132165 std::string dumpKeysExecutable = INSTALL_ROOT " /bin/dump-keys" ;
133166 std::string gosecrets =
134167 INSTALL_ROOT " /var/lib/couchbase/config/gosecrets.cfg" ;
135- bool printHeader = false ;
136168 bool withKeyStore = false ;
137169 bool stdinUsed = false ;
138170
@@ -191,10 +223,18 @@ int main(int argc, char** argv) {
191223 " The JSON containing the keystore to use (use '-' to read from "
192224 " standard input)" });
193225
194- parser.addOption ({[&printHeader ](auto value) { printHeader = true ; },
226+ parser.addOption ({[](auto value) { printHeader = true ; },
195227 " print-header" ,
196228 " Print a header with the file name before the content of "
197229 " the file" });
230+ parser.addOption (
231+ {[](auto value) {
232+ dumpEncryptionHeader = true ;
233+ printHeader = true ;
234+ },
235+ " dump-encryption-header" ,
236+ " Print the information from the encryption header if the file is "
237+ " encrypted" });
198238 parser.addOption ({[](auto ) {
199239 std::cout << " Couchbase Server " << PRODUCT_VERSION
200240 << std::endl;
@@ -215,13 +255,21 @@ int main(int argc, char** argv) {
215255 }
216256
217257 for (const auto & file : arguments) {
218- if (printHeader) {
219- std::cout << std::endl
220- << file << std::endl
221- << std::string (file.length (), ' =' ) << std::endl;
222- }
258+ bool header_printed = false ;
259+ auto do_print_header =
260+ [&header_printed](std::string_view filename,
261+ std::optional<EncryptedFileHeader> header) {
262+ if (!header_printed) {
263+ print_header (filename, header);
264+ header_printed = true ;
265+ }
266+ };
223267 try {
224268 auto reader = FileReader::create (file, key_lookup_callback);
269+ do_print_header (file,
270+ dumpEncryptionHeader
271+ ? reader->get_encryption_header ()
272+ : std::nullopt );
225273 reader->set_max_allowed_chunk_size (
226274 std::numeric_limits<uint32_t >::max ());
227275 std::vector<uint8_t > blob (8192 );
@@ -231,10 +279,12 @@ int main(int argc, char** argv) {
231279 std::cout.flush ();
232280 }
233281 } catch (const cb::crypto::dump_keys::IncorrectPasswordError& e) {
282+ do_print_header (file, {});
234283 std::cerr << e.what () << std::endl;
235284 std::exit (EXIT_INCORRECT_PASSWORD);
236285
237286 } catch (const std::exception& e) {
287+ do_print_header (file, {});
238288 std::cerr << " Fatal error: " << e.what () << std::endl;
239289 return EXIT_FAILURE;
240290 }
0 commit comments