1 // Copyright 2022 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ///////////////////////////////////////////////////////////////////////////////
16 // [START aead-example]
17 // A command-line utility for testing Tink AEAD.
18 #include <iostream>
19 #include <memory>
20 #include <ostream>
21 #include <string>
22
23 #include "absl/flags/flag.h"
24 #include "absl/flags/parse.h"
25 #include "absl/log/check.h"
26 #include "absl/strings/string_view.h"
27 #include "tink/aead.h"
28 #include "tink/aead/aead_config.h"
29 #include "util/util.h"
30 #include "tink/keyset_handle.h"
31 #include "tink/util/status.h"
32
33 ABSL_FLAG(std::string, keyset_filename, "", "Keyset file in JSON format");
34 ABSL_FLAG(std::string, mode, "", "Mode of operation {encrypt|decrypt}");
35 ABSL_FLAG(std::string, input_filename, "", "Filename to operate on");
36 ABSL_FLAG(std::string, output_filename, "", "Output file name");
37 ABSL_FLAG(std::string, associated_data, "",
38 "Associated data for AEAD (default: empty");
39
40 namespace {
41
42 using ::crypto::tink::Aead;
43 using ::crypto::tink::AeadConfig;
44 using ::crypto::tink::KeysetHandle;
45 using ::crypto::tink::util::Status;
46 using ::crypto::tink::util::StatusOr;
47
48 constexpr absl::string_view kEncrypt = "encrypt";
49 constexpr absl::string_view kDecrypt = "decrypt";
50
ValidateParams()51 void ValidateParams() {
52 // [START_EXCLUDE]
53 CHECK(absl::GetFlag(FLAGS_mode) == kEncrypt ||
54 absl::GetFlag(FLAGS_mode) == kDecrypt)
55 << "Invalid mode; must be `encrypt` or `decrypt`";
56 CHECK(!absl::GetFlag(FLAGS_keyset_filename).empty())
57 << "Keyset file must be specified";
58 CHECK(!absl::GetFlag(FLAGS_input_filename).empty())
59 << "Input file must be specified";
60 CHECK(!absl::GetFlag(FLAGS_output_filename).empty())
61 << "Output file must be specified";
62 // [END_EXCLUDE]
63 }
64
65 } // namespace
66
67 namespace tink_cc_examples {
68
69 // AEAD example CLI implementation.
AeadCli(absl::string_view mode,const std::string & keyset_filename,const std::string & input_filename,const std::string & output_filename,absl::string_view associated_data)70 Status AeadCli(absl::string_view mode, const std::string& keyset_filename,
71 const std::string& input_filename,
72 const std::string& output_filename,
73 absl::string_view associated_data) {
74 Status result = AeadConfig::Register();
75 if (!result.ok()) return result;
76
77 // Read the keyset from file.
78 StatusOr<std::unique_ptr<KeysetHandle>> keyset_handle =
79 ReadJsonCleartextKeyset(keyset_filename);
80 if (!keyset_handle.ok()) return keyset_handle.status();
81
82 // Get the primitive.
83 StatusOr<std::unique_ptr<Aead>> aead = (*keyset_handle)->GetPrimitive<Aead>();
84 if (!aead.ok()) return aead.status();
85
86 // Read the input.
87 StatusOr<std::string> input_file_content = ReadFile(input_filename);
88 if (!input_file_content.ok()) return input_file_content.status();
89
90 // Compute the output.
91 std::string output;
92 if (mode == kEncrypt) {
93 StatusOr<std::string> encrypt_result =
94 (*aead)->Encrypt(*input_file_content, associated_data);
95 if (!encrypt_result.ok()) return encrypt_result.status();
96 output = encrypt_result.value();
97 } else { // operation == kDecrypt.
98 StatusOr<std::string> decrypt_result =
99 (*aead)->Decrypt(*input_file_content, associated_data);
100 if (!decrypt_result.ok()) return decrypt_result.status();
101 output = decrypt_result.value();
102 }
103
104 // Write the output to the output file.
105 return WriteToFile(output, output_filename);
106 }
107
108 } // namespace tink_cc_examples
109
main(int argc,char ** argv)110 int main(int argc, char** argv) {
111 absl::ParseCommandLine(argc, argv);
112
113 ValidateParams();
114
115 std::string mode = absl::GetFlag(FLAGS_mode);
116 std::string keyset_filename = absl::GetFlag(FLAGS_keyset_filename);
117 std::string input_filename = absl::GetFlag(FLAGS_input_filename);
118 std::string output_filename = absl::GetFlag(FLAGS_output_filename);
119 std::string associated_data = absl::GetFlag(FLAGS_associated_data);
120
121 std::clog << "Using keyset from file " << keyset_filename << " to AEAD-"
122 << mode << " file " << input_filename << " with associated data '"
123 << associated_data << "'." << std::endl;
124 std::clog << "The resulting output will be written to " << output_filename
125 << std::endl;
126
127 CHECK_OK(tink_cc_examples::AeadCli(mode, keyset_filename, input_filename,
128 output_filename, associated_data));
129 return 0;
130 }
131 // [END aead-example]
132