X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=inline;f=tools%2Fdcpdecryptmxf.cc;h=1cdb58ec0b0441aa2f42a37eb145357195d1f73d;hb=2cb2078282c8b799d7a0d0016e1518f1a4b55af1;hp=b5cf6b9be43659983a0c2eafc97276b93aaeeac3;hpb=045402635eb36956b9361c3dfde15d5954645c18;p=libdcp.git diff --git a/tools/dcpdecryptmxf.cc b/tools/dcpdecryptmxf.cc index b5cf6b9b..1cdb58ec 100644 --- a/tools/dcpdecryptmxf.cc +++ b/tools/dcpdecryptmxf.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 Carl Hetherington + Copyright (C) 2016-2021 Carl Hetherington This file is part of libdcp. @@ -31,66 +31,106 @@ files in the program, then also delete it here. */ -#include "encrypted_kdm.h" -#include "decrypted_kdm.h" -#include "crypto_context.h" -#include "key.h" -#include "util.h" + #include "atmos_asset.h" -#include "atmos_frame.h" #include "atmos_asset_reader.h" #include "atmos_asset_writer.h" +#include "atmos_frame.h" +#include "crypto_context.h" +#include "decrypted_kdm.h" +#include "encrypted_kdm.h" #include "exceptions.h" +#include "key.h" +#include "mono_picture_asset.h" +#include "mono_picture_asset_writer.h" +#include "util.h" +#include "version.h" #include -#include #include +#include #include -using std::string; + using std::cerr; using std::cout; +using std::shared_ptr; +using std::string; using boost::optional; -using boost::shared_ptr; + static void help (string n) { - cerr << "Syntax: " << n << " [OPTION] ]\n" - << " -v, --version show libdcp version\n" + cerr << "Re-write a MXF (decrypting it if required)\n" + << "Syntax: " << n << " [OPTION] ]\n" + << " --version show libdcp version\n" + << " -v, --verbose be verbose\n" << " -h, --help show this help\n" << " -o, --output output filename\n" << " -k, --kdm KDM file\n" - << " -p, --private-key private key file\n"; + << " -p, --private-key private key file\n" + << " -t, --type MXF type: picture or atmos\n" + << " -i, --ignore-hmac don't raise an error if HMACs don't agree\n"; } +template +void copy (T const& in, shared_ptr writer, bool ignore_hmac) +{ + auto reader = in.start_read(); + reader->set_check_hmac (!ignore_hmac); + for (int64_t i = 0; i < in.intrinsic_duration(); ++i) { + auto frame = reader->get_frame (i); + writer->write (frame->data(), frame->size()); + } + writer->finalize(); +}; + + int main (int argc, char* argv[]) { + dcp::init (); + + bool verbose = false; optional output_file; optional kdm_file; optional private_key_file; + bool ignore_hmac = false; + + enum class Type { + PICTURE, + ATMOS, + }; + + optional type; int option_index = 0; while (true) { struct option long_options[] = { - { "version", no_argument, 0, 'v' }, + { "version", no_argument, 0, 'A' }, + { "verbose", no_argument, 0, 'v' }, { "help", no_argument, 0, 'h' }, { "output", required_argument, 0, 'o'}, { "kdm", required_argument, 0, 'k'}, { "private-key", required_argument, 0, 'p'}, + { "type", required_argument, 0, 't' }, + { "ignore-hmac", no_argument, 0, 'i' }, { 0, 0, 0, 0 } }; - int c = getopt_long (argc, argv, "vho:k:p:", long_options, &option_index); + int c = getopt_long (argc, argv, "Avho:k:p:t:i", long_options, &option_index); if (c == -1) { break; } switch (c) { - case 'v': - cout << "libdcp version " << LIBDCP_VERSION << "\n"; + case 'A': + cout << "libdcp version " << dcp::version << "\n"; exit (EXIT_SUCCESS); + case 'v': + verbose = true; + break; case 'h': help (argv[0]); exit (EXIT_SUCCESS); @@ -103,6 +143,19 @@ main (int argc, char* argv[]) case 'p': private_key_file = optarg; break; + case 't': + if (strcmp(optarg, "picture") == 0) { + type = Type::PICTURE; + } else if (strcmp(optarg, "atmos") == 0) { + type = Type::ATMOS; + } else { + cerr << "Unknown MXF type " << optarg << "\n"; + exit (EXIT_FAILURE); + } + break; + case 'i': + ignore_hmac = true; + break; } } @@ -128,29 +181,62 @@ main (int argc, char* argv[]) exit (EXIT_FAILURE); } + if (!type) { + cerr << "You must specify -t or --type\n"; + exit (EXIT_FAILURE); + } + dcp::EncryptedKDM encrypted_kdm (dcp::file_to_string (kdm_file.get ())); dcp::DecryptedKDM decrypted_kdm (encrypted_kdm, dcp::file_to_string (private_key_file.get())); - /* XXX: only works for Atmos! */ + auto add_key = [verbose](dcp::MXF& mxf, dcp::DecryptedKDM const& kdm) { + auto key_id = mxf.key_id(); + if (key_id) { + if (verbose) { + cout << "Asset is encrypted.\n"; + } + auto keys = kdm.keys(); + auto key = std::find_if (keys.begin(), keys.end(), [key_id](dcp::DecryptedKDMKey const& k) { return k.id() == *key_id; }); + if (key == keys.end()) { + cout << "No key found in KDM.\n"; + exit(EXIT_FAILURE); + } + if (verbose) { + cout << "Key found in KDM.\n"; + } + mxf.set_key (key->key()); + } + }; try { - dcp::AtmosAsset in (input_file); - shared_ptr reader = in.start_read (); - dcp::AtmosAsset out ( - in.edit_rate(), - in.first_frame(), - in.max_channel_count(), - in.max_object_count(), - in.atmos_id(), - in.atmos_version() - ); - shared_ptr writer = out.start_write (output_file.get()); - for (int64_t i = 0; i < in.intrinsic_duration(); ++i) { - shared_ptr f = reader->get_frame (i); - writer->write (f->data(), f->size()); + switch (*type) { + case Type::ATMOS: + { + dcp::AtmosAsset in (input_file); + add_key (in, decrypted_kdm); + dcp::AtmosAsset out ( + in.edit_rate(), + in.first_frame(), + in.max_channel_count(), + in.max_object_count(), + in.atmos_version() + ); + auto writer = out.start_write(output_file.get()); + copy (in, writer, ignore_hmac); + break; + } + case Type::PICTURE: + { + dcp::MonoPictureAsset in (input_file); + add_key (in, decrypted_kdm); + dcp::MonoPictureAsset out (in.edit_rate(), dcp::Standard::SMPTE); + auto writer = out.start_write(output_file.get(), dcp::PictureAsset::Behaviour::MAKE_NEW); + copy (in, writer, ignore_hmac); + break; + } } - } catch (dcp::DCPReadError& e) { - cerr << "Unknown MXF format.\n"; + } catch (dcp::ReadError& e) { + cerr << "Read error: " << e.what() << "\n"; return EXIT_FAILURE; }