// Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////////// // [START mac-example] // A command-line utility for showcasing using the Tink MAC primitive. #include #include #include #include #include #include #include #include "absl/flags/flag.h" #include "absl/flags/parse.h" #include "absl/log/check.h" #include "absl/strings/string_view.h" #include "util/util.h" #include "tink/keyset_handle.h" #include "tink/mac.h" #include "tink/mac/mac_config.h" #include "tink/util/status.h" ABSL_FLAG(std::string, keyset_filename, "", "Keyset file in JSON format"); ABSL_FLAG(std::string, mode, "", "Mode of operation {compute|verify}"); ABSL_FLAG(std::string, data_filename, "", "Data file name"); ABSL_FLAG(std::string, tag_filename, "", "Authentication tag file name"); namespace { using ::crypto::tink::KeysetHandle; using ::crypto::tink::Mac; using ::crypto::tink::MacConfig; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; constexpr absl::string_view kCompute = "compute"; constexpr absl::string_view kVerify = "verify"; void ValidateParams() { // [START_EXCLUDE] CHECK(absl::GetFlag(FLAGS_mode) == kCompute || absl::GetFlag(FLAGS_mode) == kVerify) << "Invalid mode; must be `" << kCompute << "` or `" << kVerify << "`"; CHECK(!absl::GetFlag(FLAGS_keyset_filename).empty()) << "Keyset file must be specified"; CHECK(!absl::GetFlag(FLAGS_data_filename).empty()) << "Data file must be specified"; CHECK(!absl::GetFlag(FLAGS_tag_filename).empty()) << "Tag file must be specified"; // [END_EXCLUDE] } } // namespace namespace tink_cc_examples { // MAC example CLI implementation. Status MacCli(absl::string_view mode, const std::string keyset_filename, const std::string& data_filename, const std::string& tag_filename) { Status result = MacConfig::Register(); if (!result.ok()) return result; // Read the keyset from file. StatusOr> keyset_handle = ReadJsonCleartextKeyset(keyset_filename); if (!keyset_handle.ok()) return keyset_handle.status(); // Get the primitive. StatusOr> mac_primitive = (*keyset_handle)->GetPrimitive(); if (!mac_primitive.ok()) return mac_primitive.status(); // Read the input. StatusOr data_file_content = ReadFile(data_filename); if (!data_file_content.ok()) return data_file_content.status(); std::string output; if (mode == kCompute) { // Compute authentication tag. StatusOr compute_result = (*mac_primitive)->ComputeMac(*data_file_content); if (!compute_result.ok()) return compute_result.status(); // Write out the authentication tag to tag file. return WriteToFile(*compute_result, tag_filename); } else { // operation == kVerify. // Read the authentication tag from tag file. StatusOr tag_result = ReadFile(tag_filename); if (!tag_result.ok()) { std::cerr << tag_result.status().message() << std::endl; exit(1); } // Verify authentication tag. Status verify_result = (*mac_primitive)->VerifyMac(*tag_result, *data_file_content); if (verify_result.ok()) std::clog << "Verification succeeded!" << std::endl; return verify_result; } } } // namespace tink_cc_examples int main(int argc, char** argv) { absl::ParseCommandLine(argc, argv); ValidateParams(); std::string mode = absl::GetFlag(FLAGS_mode); std::string keyset_filename = absl::GetFlag(FLAGS_keyset_filename); std::string data_filename = absl::GetFlag(FLAGS_data_filename); std::string tag_filename = absl::GetFlag(FLAGS_tag_filename); std::clog << "Using keyset from file '" << keyset_filename << "' to " << mode << " authentication tag from file '" << tag_filename << "' for data file '" << data_filename << "'." << std::endl; std::clog << "The tag will be " << ((mode == kCompute) ? "written to" : "read from") << " file '" << tag_filename << "'." << std::endl; CHECK_OK(tink_cc_examples::MacCli(mode, keyset_filename, data_filename, tag_filename)); return 0; } // [END mac-example]