xref: /aosp_15_r20/external/tink/cc/examples/digital_signatures/digital_signatures_cli.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2020 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 digital-signature-example]
17 // A utility for signing and verifying files using digital signatures.
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 "util/util.h"
27 #include "tink/keyset_handle.h"
28 #include "tink/public_key_sign.h"
29 #include "tink/public_key_verify.h"
30 #include "tink/signature/signature_config.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 (sign|verify)");
35 ABSL_FLAG(std::string, input_filename, "", "Filename to operate on");
36 ABSL_FLAG(std::string, signature_filename, "", "Path to the signature file");
37 
38 namespace {
39 
40 using ::crypto::tink::KeysetHandle;
41 using ::crypto::tink::PublicKeySign;
42 using ::crypto::tink::PublicKeyVerify;
43 using ::crypto::tink::util::Status;
44 using ::crypto::tink::util::StatusOr;
45 
46 constexpr absl::string_view kSign = "sign";
47 constexpr absl::string_view kVerify = "verify";
48 
ValidateParams()49 void ValidateParams() {
50   // [START_EXCLUDE]
51   CHECK(absl::GetFlag(FLAGS_mode) == kSign ||
52         absl::GetFlag(FLAGS_mode) == kVerify)
53       << "Invalid mode; must be `" << kSign << "` or `" << kVerify << "`"
54       << std::endl;
55   CHECK(!absl::GetFlag(FLAGS_keyset_filename).empty())
56       << "Keyset file must be specified";
57   CHECK(!absl::GetFlag(FLAGS_input_filename).empty())
58       << "Input file must be specified";
59   CHECK(!absl::GetFlag(FLAGS_signature_filename).empty())
60       << "Signature file must be specified";
61   // [END_EXCLUDE]
62 }
63 
64 }  // namespace
65 
66 namespace tink_cc_examples {
67 
68 // Digital signature example CLI implementation.
DigitalSignatureCli(absl::string_view mode,const std::string & keyset_filename,const std::string & input_filename,const std::string & signature_filename)69 Status DigitalSignatureCli(absl::string_view mode,
70                            const std::string& keyset_filename,
71                            const std::string& input_filename,
72                            const std::string& signature_filename) {
73   Status result = crypto::tink::SignatureConfig::Register();
74   if (!result.ok()) return result;
75 
76   // Read the keyset from file.
77   StatusOr<std::unique_ptr<KeysetHandle>> keyset_handle =
78       ReadJsonCleartextKeyset(keyset_filename);
79   if (!keyset_handle.ok()) return keyset_handle.status();
80 
81   // Read the input.
82   StatusOr<std::string> input_file_content = ReadFile(input_filename);
83   if (!input_file_content.ok()) return input_file_content.status();
84 
85   if (mode == kSign) {
86     StatusOr<std::unique_ptr<PublicKeySign>> public_key_sign =
87         (*keyset_handle)->GetPrimitive<PublicKeySign>();
88     if (!public_key_sign.ok()) return public_key_sign.status();
89 
90     StatusOr<std::string> signature =
91         (*public_key_sign)->Sign(*input_file_content);
92     if (!signature.ok()) return signature.status();
93 
94     return WriteToFile(*signature, signature_filename);
95   } else {  // mode == kVerify
96     StatusOr<std::unique_ptr<PublicKeyVerify>> public_key_verify =
97         (*keyset_handle)->GetPrimitive<PublicKeyVerify>();
98     if (!public_key_verify.ok()) return public_key_verify.status();
99 
100     // Read the signature.
101     StatusOr<std::string> signature_file_content = ReadFile(signature_filename);
102     if (!signature_file_content.ok()) return signature_file_content.status();
103 
104     return (*public_key_verify)
105         ->Verify(*signature_file_content, *input_file_content);
106   }
107 }
108 
109 }  // namespace tink_cc_examples
110 
main(int argc,char ** argv)111 int main(int argc, char** argv) {
112   absl::ParseCommandLine(argc, argv);
113 
114   ValidateParams();
115 
116   std::string mode = absl::GetFlag(FLAGS_mode);
117   std::string keyset_filename = absl::GetFlag(FLAGS_keyset_filename);
118   std::string input_filename = absl::GetFlag(FLAGS_input_filename);
119   std::string signature_filename = absl::GetFlag(FLAGS_signature_filename);
120 
121   std::clog << "Using keyset in " << keyset_filename << " to " << mode;
122   if (mode == kSign) {
123     std::clog << " file " << input_filename
124               << "; the resulting signature is written to "
125               << signature_filename << std::endl;
126   } else {  // mode == kVerify
127     std::clog << " the signature in " << signature_filename
128               << " over the content of " << input_filename << std::endl;
129   }
130 
131   CHECK_OK(tink_cc_examples::DigitalSignatureCli(
132       mode, keyset_filename, input_filename, signature_filename));
133   return 0;
134 }
135 // [END digital-signature-example]
136