xref: /aosp_15_r20/external/tink/cc/jwt/jwk_set_converter.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1*e7b1675dSTing-Kang Chang // Copyright 2021 Google LLC
2*e7b1675dSTing-Kang Chang //
3*e7b1675dSTing-Kang Chang // Licensed under the Apache License, Version 2.0 (the "License");
4*e7b1675dSTing-Kang Chang // you may not use this file except in compliance with the License.
5*e7b1675dSTing-Kang Chang // You may obtain a copy of the License at
6*e7b1675dSTing-Kang Chang //
7*e7b1675dSTing-Kang Chang //     http://www.apache.org/licenses/LICENSE-2.0
8*e7b1675dSTing-Kang Chang //
9*e7b1675dSTing-Kang Chang // Unless required by applicable law or agreed to in writing, software
10*e7b1675dSTing-Kang Chang // distributed under the License is distributed on an "AS IS" BASIS,
11*e7b1675dSTing-Kang Chang // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*e7b1675dSTing-Kang Chang // See the License for the specific language governing permissions and
13*e7b1675dSTing-Kang Chang // limitations under the License.
14*e7b1675dSTing-Kang Chang //
15*e7b1675dSTing-Kang Chang ///////////////////////////////////////////////////////////////////////////////
16*e7b1675dSTing-Kang Chang 
17*e7b1675dSTing-Kang Chang #include "tink/jwt/jwk_set_converter.h"
18*e7b1675dSTing-Kang Chang 
19*e7b1675dSTing-Kang Chang #include <memory>
20*e7b1675dSTing-Kang Chang #include <ostream>
21*e7b1675dSTing-Kang Chang #include <sstream>
22*e7b1675dSTing-Kang Chang #include <string>
23*e7b1675dSTing-Kang Chang 
24*e7b1675dSTing-Kang Chang #include "absl/strings/escaping.h"
25*e7b1675dSTing-Kang Chang #include "tink/binary_keyset_writer.h"
26*e7b1675dSTing-Kang Chang #include "tink/jwt/internal/json_util.h"
27*e7b1675dSTing-Kang Chang #include "tink/jwt/internal/jwt_format.h"
28*e7b1675dSTing-Kang Chang #include "tink/jwt/jwt_public_key_sign.h"
29*e7b1675dSTing-Kang Chang #include "tink/jwt/raw_jwt.h"
30*e7b1675dSTing-Kang Chang #include "tink/keyset_handle.h"
31*e7b1675dSTing-Kang Chang #include "tink/util/keyset_util.h"
32*e7b1675dSTing-Kang Chang #include "tink/util/statusor.h"
33*e7b1675dSTing-Kang Chang #include "proto/common.pb.h"
34*e7b1675dSTing-Kang Chang #include "proto/jwt_ecdsa.pb.h"
35*e7b1675dSTing-Kang Chang #include "proto/jwt_rsa_ssa_pkcs1.pb.h"
36*e7b1675dSTing-Kang Chang #include "proto/jwt_rsa_ssa_pss.pb.h"
37*e7b1675dSTing-Kang Chang #include "proto/tink.pb.h"
38*e7b1675dSTing-Kang Chang 
39*e7b1675dSTing-Kang Chang namespace crypto {
40*e7b1675dSTing-Kang Chang namespace tink {
41*e7b1675dSTing-Kang Chang 
42*e7b1675dSTing-Kang Chang using ::google::crypto::tink::JwtRsaSsaPkcs1Algorithm;
43*e7b1675dSTing-Kang Chang using ::google::crypto::tink::JwtRsaSsaPkcs1PublicKey;
44*e7b1675dSTing-Kang Chang using ::google::crypto::tink::JwtRsaSsaPssAlgorithm;
45*e7b1675dSTing-Kang Chang using ::google::crypto::tink::JwtRsaSsaPssPublicKey;
46*e7b1675dSTing-Kang Chang using ::google::crypto::tink::JwtEcdsaAlgorithm;
47*e7b1675dSTing-Kang Chang using ::google::crypto::tink::JwtEcdsaPublicKey;
48*e7b1675dSTing-Kang Chang using ::google::crypto::tink::KeyData;
49*e7b1675dSTing-Kang Chang using ::google::crypto::tink::Keyset;
50*e7b1675dSTing-Kang Chang using ::google::crypto::tink::Keyset_Key;
51*e7b1675dSTing-Kang Chang using ::google::crypto::tink::KeyStatusType;
52*e7b1675dSTing-Kang Chang using ::google::crypto::tink::OutputPrefixType;
53*e7b1675dSTing-Kang Chang using ::google::protobuf::ListValue;
54*e7b1675dSTing-Kang Chang using ::google::protobuf::Struct;
55*e7b1675dSTing-Kang Chang using ::google::protobuf::Value;
56*e7b1675dSTing-Kang Chang 
57*e7b1675dSTing-Kang Chang namespace {
58*e7b1675dSTing-Kang Chang 
HasItem(const Struct & key_struct,absl::string_view name)59*e7b1675dSTing-Kang Chang bool HasItem(const Struct& key_struct, absl::string_view name) {
60*e7b1675dSTing-Kang Chang   return key_struct.fields().find(std::string(name)) !=
61*e7b1675dSTing-Kang Chang          key_struct.fields().end();
62*e7b1675dSTing-Kang Chang }
63*e7b1675dSTing-Kang Chang 
GetStringItem(const Struct & key_struct,absl::string_view name)64*e7b1675dSTing-Kang Chang util::StatusOr<std::string> GetStringItem(const Struct& key_struct,
65*e7b1675dSTing-Kang Chang                                           absl::string_view name) {
66*e7b1675dSTing-Kang Chang   auto it = key_struct.fields().find(std::string(name));
67*e7b1675dSTing-Kang Chang   if (it == key_struct.fields().end()) {
68*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument, "not found");
69*e7b1675dSTing-Kang Chang   }
70*e7b1675dSTing-Kang Chang   if (it->second.kind_case() != Value::kStringValue) {
71*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument, "is not a string");
72*e7b1675dSTing-Kang Chang   }
73*e7b1675dSTing-Kang Chang   return it->second.string_value();
74*e7b1675dSTing-Kang Chang }
75*e7b1675dSTing-Kang Chang 
ExpectStringItem(const Struct & key_struct,absl::string_view name,absl::string_view value)76*e7b1675dSTing-Kang Chang util::Status ExpectStringItem(const Struct& key_struct, absl::string_view name,
77*e7b1675dSTing-Kang Chang                               absl::string_view value) {
78*e7b1675dSTing-Kang Chang   util::StatusOr<std::string> item = GetStringItem(key_struct, name);
79*e7b1675dSTing-Kang Chang   if (!item.ok()) {
80*e7b1675dSTing-Kang Chang     return item.status();
81*e7b1675dSTing-Kang Chang   }
82*e7b1675dSTing-Kang Chang   if (*item != value) {
83*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument, "unexpected value");
84*e7b1675dSTing-Kang Chang   }
85*e7b1675dSTing-Kang Chang   return util::OkStatus();
86*e7b1675dSTing-Kang Chang }
87*e7b1675dSTing-Kang Chang 
ValidateUseIsSig(const Struct & key_struct)88*e7b1675dSTing-Kang Chang util::Status ValidateUseIsSig(const Struct& key_struct) {
89*e7b1675dSTing-Kang Chang   if (!HasItem(key_struct, "use")) {
90*e7b1675dSTing-Kang Chang     return util::OkStatus();
91*e7b1675dSTing-Kang Chang   }
92*e7b1675dSTing-Kang Chang   return ExpectStringItem(key_struct, "use", "sig");
93*e7b1675dSTing-Kang Chang }
94*e7b1675dSTing-Kang Chang 
ValidateKeyOpsIsVerify(const Struct & key_struct)95*e7b1675dSTing-Kang Chang util::Status ValidateKeyOpsIsVerify(const Struct& key_struct) {
96*e7b1675dSTing-Kang Chang   if (!HasItem(key_struct, "key_ops")) {
97*e7b1675dSTing-Kang Chang     return util::OkStatus();
98*e7b1675dSTing-Kang Chang   }
99*e7b1675dSTing-Kang Chang   auto it = key_struct.fields().find("key_ops");
100*e7b1675dSTing-Kang Chang   if (it == key_struct.fields().end()) {
101*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
102*e7b1675dSTing-Kang Chang                         "key_ops not found");
103*e7b1675dSTing-Kang Chang   }
104*e7b1675dSTing-Kang Chang   if (it->second.kind_case() != Value::kListValue) {
105*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
106*e7b1675dSTing-Kang Chang                         "key_ops is not a list");
107*e7b1675dSTing-Kang Chang   }
108*e7b1675dSTing-Kang Chang   const ListValue& key_ops_list = it->second.list_value();
109*e7b1675dSTing-Kang Chang   if (key_ops_list.values_size() != 1) {
110*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
111*e7b1675dSTing-Kang Chang                         "key_ops size is not 1");
112*e7b1675dSTing-Kang Chang   }
113*e7b1675dSTing-Kang Chang   const Value & value = key_ops_list.values().Get(0);
114*e7b1675dSTing-Kang Chang   if (value.kind_case() != Value::kStringValue) {
115*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
116*e7b1675dSTing-Kang Chang                         "key_ops item is not a string");
117*e7b1675dSTing-Kang Chang   }
118*e7b1675dSTing-Kang Chang   if (value.string_value() != "verify") {
119*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
120*e7b1675dSTing-Kang Chang                         "key_ops is not equal to [\"verify\"]");
121*e7b1675dSTing-Kang Chang   }
122*e7b1675dSTing-Kang Chang   return util::OkStatus();
123*e7b1675dSTing-Kang Chang }
124*e7b1675dSTing-Kang Chang 
RsPublicKeyDataFromKeyStruct(const Struct & key_struct)125*e7b1675dSTing-Kang Chang util::StatusOr<KeyData> RsPublicKeyDataFromKeyStruct(const Struct& key_struct) {
126*e7b1675dSTing-Kang Chang   JwtRsaSsaPkcs1PublicKey public_key_proto;
127*e7b1675dSTing-Kang Chang   public_key_proto.set_version(0);
128*e7b1675dSTing-Kang Chang 
129*e7b1675dSTing-Kang Chang   util::StatusOr<std::string> alg = GetStringItem(key_struct, "alg");
130*e7b1675dSTing-Kang Chang   if (!alg.ok()) {
131*e7b1675dSTing-Kang Chang     return alg.status();
132*e7b1675dSTing-Kang Chang   }
133*e7b1675dSTing-Kang Chang   if (*alg == "RS256") {
134*e7b1675dSTing-Kang Chang     public_key_proto.set_algorithm(JwtRsaSsaPkcs1Algorithm::RS256);
135*e7b1675dSTing-Kang Chang   } else if (*alg == "RS384") {
136*e7b1675dSTing-Kang Chang     public_key_proto.set_algorithm(JwtRsaSsaPkcs1Algorithm::RS384);
137*e7b1675dSTing-Kang Chang   } else if (*alg == "RS512") {
138*e7b1675dSTing-Kang Chang     public_key_proto.set_algorithm(JwtRsaSsaPkcs1Algorithm::RS512);
139*e7b1675dSTing-Kang Chang   } else {
140*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument, "invalid alg");
141*e7b1675dSTing-Kang Chang   }
142*e7b1675dSTing-Kang Chang 
143*e7b1675dSTing-Kang Chang   if (HasItem(key_struct, "p") || HasItem(key_struct, "q") ||
144*e7b1675dSTing-Kang Chang       HasItem(key_struct, "dq") || HasItem(key_struct, "dp") ||
145*e7b1675dSTing-Kang Chang       HasItem(key_struct, "d") || HasItem(key_struct, "qi")) {
146*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
147*e7b1675dSTing-Kang Chang                         "private keys cannot be converted");
148*e7b1675dSTing-Kang Chang   }
149*e7b1675dSTing-Kang Chang   util::Status status_kty = ExpectStringItem(key_struct, "kty", "RSA");
150*e7b1675dSTing-Kang Chang   if (!status_kty.ok()) {
151*e7b1675dSTing-Kang Chang     return status_kty;
152*e7b1675dSTing-Kang Chang   }
153*e7b1675dSTing-Kang Chang   util::Status status_use = ValidateUseIsSig(key_struct);
154*e7b1675dSTing-Kang Chang   if (!status_use.ok()) {
155*e7b1675dSTing-Kang Chang     return status_use;
156*e7b1675dSTing-Kang Chang   }
157*e7b1675dSTing-Kang Chang   util::Status status_key_ops = ValidateKeyOpsIsVerify(key_struct);
158*e7b1675dSTing-Kang Chang   if (!status_key_ops.ok()) {
159*e7b1675dSTing-Kang Chang     return status_key_ops;
160*e7b1675dSTing-Kang Chang   }
161*e7b1675dSTing-Kang Chang 
162*e7b1675dSTing-Kang Chang   util::StatusOr<std::string> e = GetStringItem(key_struct, "e");
163*e7b1675dSTing-Kang Chang   if (!e.ok()) {
164*e7b1675dSTing-Kang Chang     return e.status();
165*e7b1675dSTing-Kang Chang   }
166*e7b1675dSTing-Kang Chang   std::string decoded_e;
167*e7b1675dSTing-Kang Chang   if (!absl::WebSafeBase64Unescape(*e, &decoded_e)) {
168*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
169*e7b1675dSTing-Kang Chang                         "failed to decode e");
170*e7b1675dSTing-Kang Chang   }
171*e7b1675dSTing-Kang Chang   public_key_proto.set_e(decoded_e);
172*e7b1675dSTing-Kang Chang 
173*e7b1675dSTing-Kang Chang   util::StatusOr<std::string> n = GetStringItem(key_struct, "n");
174*e7b1675dSTing-Kang Chang   if (!n.ok()) {
175*e7b1675dSTing-Kang Chang     return n.status();
176*e7b1675dSTing-Kang Chang   }
177*e7b1675dSTing-Kang Chang   std::string decoded_n;
178*e7b1675dSTing-Kang Chang   if (!absl::WebSafeBase64Unescape(*n, &decoded_n)) {
179*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
180*e7b1675dSTing-Kang Chang                         "failed to decode n");
181*e7b1675dSTing-Kang Chang   }
182*e7b1675dSTing-Kang Chang   public_key_proto.set_n(decoded_n);
183*e7b1675dSTing-Kang Chang 
184*e7b1675dSTing-Kang Chang   if (HasItem(key_struct, "kid")) {
185*e7b1675dSTing-Kang Chang     util::StatusOr<std::string> kid = GetStringItem(key_struct, "kid");
186*e7b1675dSTing-Kang Chang     if (!kid.ok()) {
187*e7b1675dSTing-Kang Chang       return kid.status();
188*e7b1675dSTing-Kang Chang     }
189*e7b1675dSTing-Kang Chang     public_key_proto.mutable_custom_kid()->set_value(*kid);
190*e7b1675dSTing-Kang Chang   }
191*e7b1675dSTing-Kang Chang   KeyData key_data_proto;
192*e7b1675dSTing-Kang Chang   key_data_proto.set_type_url(
193*e7b1675dSTing-Kang Chang       "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey");
194*e7b1675dSTing-Kang Chang   key_data_proto.set_value(public_key_proto.SerializeAsString());
195*e7b1675dSTing-Kang Chang   key_data_proto.set_key_material_type(KeyData::ASYMMETRIC_PUBLIC);
196*e7b1675dSTing-Kang Chang   return key_data_proto;
197*e7b1675dSTing-Kang Chang }
198*e7b1675dSTing-Kang Chang 
PsPublicKeyDataFromKeyStruct(const Struct & key_struct)199*e7b1675dSTing-Kang Chang util::StatusOr<KeyData> PsPublicKeyDataFromKeyStruct(const Struct& key_struct) {
200*e7b1675dSTing-Kang Chang   JwtRsaSsaPssPublicKey public_key_proto;
201*e7b1675dSTing-Kang Chang   public_key_proto.set_version(0);
202*e7b1675dSTing-Kang Chang 
203*e7b1675dSTing-Kang Chang   util::StatusOr<std::string> alg = GetStringItem(key_struct, "alg");
204*e7b1675dSTing-Kang Chang   if (!alg.ok()) {
205*e7b1675dSTing-Kang Chang     return alg.status();
206*e7b1675dSTing-Kang Chang   }
207*e7b1675dSTing-Kang Chang   if (*alg == "PS256") {
208*e7b1675dSTing-Kang Chang     public_key_proto.set_algorithm(JwtRsaSsaPssAlgorithm::PS256);
209*e7b1675dSTing-Kang Chang   } else if (*alg == "PS384") {
210*e7b1675dSTing-Kang Chang     public_key_proto.set_algorithm(JwtRsaSsaPssAlgorithm::PS384);
211*e7b1675dSTing-Kang Chang   } else if (*alg == "PS512") {
212*e7b1675dSTing-Kang Chang     public_key_proto.set_algorithm(JwtRsaSsaPssAlgorithm::PS512);
213*e7b1675dSTing-Kang Chang   } else {
214*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument, "invalid alg");
215*e7b1675dSTing-Kang Chang   }
216*e7b1675dSTing-Kang Chang 
217*e7b1675dSTing-Kang Chang   if (HasItem(key_struct, "p") || HasItem(key_struct, "q") ||
218*e7b1675dSTing-Kang Chang       HasItem(key_struct, "dq") || HasItem(key_struct, "dp") ||
219*e7b1675dSTing-Kang Chang       HasItem(key_struct, "d") || HasItem(key_struct, "qi")) {
220*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
221*e7b1675dSTing-Kang Chang                         "private keys cannot be converted");
222*e7b1675dSTing-Kang Chang   }
223*e7b1675dSTing-Kang Chang   util::Status status_kty = ExpectStringItem(key_struct, "kty", "RSA");
224*e7b1675dSTing-Kang Chang   if (!status_kty.ok()) {
225*e7b1675dSTing-Kang Chang     return status_kty;
226*e7b1675dSTing-Kang Chang   }
227*e7b1675dSTing-Kang Chang   util::Status status_use = ValidateUseIsSig(key_struct);
228*e7b1675dSTing-Kang Chang   if (!status_use.ok()) {
229*e7b1675dSTing-Kang Chang     return status_use;
230*e7b1675dSTing-Kang Chang   }
231*e7b1675dSTing-Kang Chang   util::Status status_key_ops = ValidateKeyOpsIsVerify(key_struct);
232*e7b1675dSTing-Kang Chang   if (!status_key_ops.ok()) {
233*e7b1675dSTing-Kang Chang     return status_key_ops;
234*e7b1675dSTing-Kang Chang   }
235*e7b1675dSTing-Kang Chang 
236*e7b1675dSTing-Kang Chang   util::StatusOr<std::string> e = GetStringItem(key_struct, "e");
237*e7b1675dSTing-Kang Chang   if (!e.ok()) {
238*e7b1675dSTing-Kang Chang     return e.status();
239*e7b1675dSTing-Kang Chang   }
240*e7b1675dSTing-Kang Chang   std::string decoded_e;
241*e7b1675dSTing-Kang Chang   if (!absl::WebSafeBase64Unescape(*e, &decoded_e)) {
242*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
243*e7b1675dSTing-Kang Chang                         "failed to decode e");
244*e7b1675dSTing-Kang Chang   }
245*e7b1675dSTing-Kang Chang   public_key_proto.set_e(decoded_e);
246*e7b1675dSTing-Kang Chang 
247*e7b1675dSTing-Kang Chang   util::StatusOr<std::string> n = GetStringItem(key_struct, "n");
248*e7b1675dSTing-Kang Chang   if (!n.ok()) {
249*e7b1675dSTing-Kang Chang     return n.status();
250*e7b1675dSTing-Kang Chang   }
251*e7b1675dSTing-Kang Chang   std::string decoded_n;
252*e7b1675dSTing-Kang Chang   if (!absl::WebSafeBase64Unescape(*n, &decoded_n)) {
253*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
254*e7b1675dSTing-Kang Chang                         "failed to decode n");
255*e7b1675dSTing-Kang Chang   }
256*e7b1675dSTing-Kang Chang   public_key_proto.set_n(decoded_n);
257*e7b1675dSTing-Kang Chang 
258*e7b1675dSTing-Kang Chang   if (HasItem(key_struct, "kid")) {
259*e7b1675dSTing-Kang Chang     util::StatusOr<std::string> kid = GetStringItem(key_struct, "kid");
260*e7b1675dSTing-Kang Chang     if (!kid.ok()) {
261*e7b1675dSTing-Kang Chang       return kid.status();
262*e7b1675dSTing-Kang Chang     }
263*e7b1675dSTing-Kang Chang     public_key_proto.mutable_custom_kid()->set_value(*kid);
264*e7b1675dSTing-Kang Chang   }
265*e7b1675dSTing-Kang Chang   KeyData key_data_proto;
266*e7b1675dSTing-Kang Chang   key_data_proto.set_type_url(
267*e7b1675dSTing-Kang Chang       "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey");
268*e7b1675dSTing-Kang Chang   key_data_proto.set_value(public_key_proto.SerializeAsString());
269*e7b1675dSTing-Kang Chang   key_data_proto.set_key_material_type(KeyData::ASYMMETRIC_PUBLIC);
270*e7b1675dSTing-Kang Chang   return key_data_proto;
271*e7b1675dSTing-Kang Chang }
272*e7b1675dSTing-Kang Chang 
EsPublicKeyDataFromKeyStruct(const Struct & key_struct)273*e7b1675dSTing-Kang Chang util::StatusOr<KeyData> EsPublicKeyDataFromKeyStruct(const Struct& key_struct) {
274*e7b1675dSTing-Kang Chang   JwtEcdsaPublicKey public_key_proto;
275*e7b1675dSTing-Kang Chang   public_key_proto.set_version(0);
276*e7b1675dSTing-Kang Chang 
277*e7b1675dSTing-Kang Chang   util::StatusOr<std::string> alg = GetStringItem(key_struct, "alg");
278*e7b1675dSTing-Kang Chang   if (!alg.ok()) {
279*e7b1675dSTing-Kang Chang     return alg.status();
280*e7b1675dSTing-Kang Chang   }
281*e7b1675dSTing-Kang Chang   util::StatusOr<std::string> curve = GetStringItem(key_struct, "crv");
282*e7b1675dSTing-Kang Chang   if (!curve.ok()) {
283*e7b1675dSTing-Kang Chang     return curve.status();
284*e7b1675dSTing-Kang Chang   }
285*e7b1675dSTing-Kang Chang   if (*alg == "ES256") {
286*e7b1675dSTing-Kang Chang     if (*curve != "P-256") {
287*e7b1675dSTing-Kang Chang       return util::Status(absl::StatusCode::kInvalidArgument,
288*e7b1675dSTing-Kang Chang                           "crv is not equal to P-256");
289*e7b1675dSTing-Kang Chang     }
290*e7b1675dSTing-Kang Chang     public_key_proto.set_algorithm(JwtEcdsaAlgorithm::ES256);
291*e7b1675dSTing-Kang Chang   } else if (*alg == "ES384") {
292*e7b1675dSTing-Kang Chang     if (*curve != "P-384") {
293*e7b1675dSTing-Kang Chang       return util::Status(absl::StatusCode::kInvalidArgument,
294*e7b1675dSTing-Kang Chang                           "crv is not equal to P-384");
295*e7b1675dSTing-Kang Chang     }
296*e7b1675dSTing-Kang Chang     public_key_proto.set_algorithm(JwtEcdsaAlgorithm::ES384);
297*e7b1675dSTing-Kang Chang   } else if (*alg == "ES512") {
298*e7b1675dSTing-Kang Chang     if (*curve != "P-521") {
299*e7b1675dSTing-Kang Chang       return util::Status(absl::StatusCode::kInvalidArgument,
300*e7b1675dSTing-Kang Chang                           "crv is not equal to P-521");
301*e7b1675dSTing-Kang Chang     }
302*e7b1675dSTing-Kang Chang     public_key_proto.set_algorithm(JwtEcdsaAlgorithm::ES512);
303*e7b1675dSTing-Kang Chang   } else {
304*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument, "invalid alg");
305*e7b1675dSTing-Kang Chang   }
306*e7b1675dSTing-Kang Chang 
307*e7b1675dSTing-Kang Chang   if (HasItem(key_struct, "d")) {
308*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
309*e7b1675dSTing-Kang Chang                         "private keys cannot be converted");
310*e7b1675dSTing-Kang Chang   }
311*e7b1675dSTing-Kang Chang   util::Status status_kty = ExpectStringItem(key_struct, "kty", "EC");
312*e7b1675dSTing-Kang Chang   if (!status_kty.ok()) {
313*e7b1675dSTing-Kang Chang     return status_kty;
314*e7b1675dSTing-Kang Chang   }
315*e7b1675dSTing-Kang Chang   util::Status status_use = ValidateUseIsSig(key_struct);
316*e7b1675dSTing-Kang Chang   if (!status_use.ok()) {
317*e7b1675dSTing-Kang Chang     return status_use;
318*e7b1675dSTing-Kang Chang   }
319*e7b1675dSTing-Kang Chang   util::Status status_key_ops = ValidateKeyOpsIsVerify(key_struct);
320*e7b1675dSTing-Kang Chang   if (!status_key_ops.ok()) {
321*e7b1675dSTing-Kang Chang     return status_key_ops;
322*e7b1675dSTing-Kang Chang   }
323*e7b1675dSTing-Kang Chang 
324*e7b1675dSTing-Kang Chang   util::StatusOr<std::string> x = GetStringItem(key_struct, "x");
325*e7b1675dSTing-Kang Chang   if (!x.ok()) {
326*e7b1675dSTing-Kang Chang     return x.status();
327*e7b1675dSTing-Kang Chang   }
328*e7b1675dSTing-Kang Chang   std::string decoded_x;
329*e7b1675dSTing-Kang Chang   if (!absl::WebSafeBase64Unescape(*x, &decoded_x)) {
330*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
331*e7b1675dSTing-Kang Chang                         "failed to decode x");
332*e7b1675dSTing-Kang Chang   }
333*e7b1675dSTing-Kang Chang   public_key_proto.set_x(decoded_x);
334*e7b1675dSTing-Kang Chang 
335*e7b1675dSTing-Kang Chang   util::StatusOr<std::string> y = GetStringItem(key_struct, "y");
336*e7b1675dSTing-Kang Chang   if (!y.ok()) {
337*e7b1675dSTing-Kang Chang     return y.status();
338*e7b1675dSTing-Kang Chang   }
339*e7b1675dSTing-Kang Chang   std::string decoded_y;
340*e7b1675dSTing-Kang Chang   if (!absl::WebSafeBase64Unescape(*y, &decoded_y)) {
341*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
342*e7b1675dSTing-Kang Chang                         "failed to decode y");
343*e7b1675dSTing-Kang Chang   }
344*e7b1675dSTing-Kang Chang   public_key_proto.set_y(decoded_y);
345*e7b1675dSTing-Kang Chang 
346*e7b1675dSTing-Kang Chang   if (HasItem(key_struct, "kid")) {
347*e7b1675dSTing-Kang Chang     util::StatusOr<std::string> kid = GetStringItem(key_struct, "kid");
348*e7b1675dSTing-Kang Chang     if (!kid.ok()) {
349*e7b1675dSTing-Kang Chang       return kid.status();
350*e7b1675dSTing-Kang Chang     }
351*e7b1675dSTing-Kang Chang     public_key_proto.mutable_custom_kid()->set_value(*kid);
352*e7b1675dSTing-Kang Chang   }
353*e7b1675dSTing-Kang Chang   KeyData key_data_proto;
354*e7b1675dSTing-Kang Chang   key_data_proto.set_type_url(
355*e7b1675dSTing-Kang Chang       "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey");
356*e7b1675dSTing-Kang Chang   key_data_proto.set_value(public_key_proto.SerializeAsString());
357*e7b1675dSTing-Kang Chang   key_data_proto.set_key_material_type(KeyData::ASYMMETRIC_PUBLIC);
358*e7b1675dSTing-Kang Chang   return key_data_proto;
359*e7b1675dSTing-Kang Chang }
360*e7b1675dSTing-Kang Chang 
361*e7b1675dSTing-Kang Chang }  // namespace
362*e7b1675dSTing-Kang Chang 
JwkSetToPublicKeysetHandle(absl::string_view jwk_set)363*e7b1675dSTing-Kang Chang util::StatusOr<std::unique_ptr<KeysetHandle>> JwkSetToPublicKeysetHandle(
364*e7b1675dSTing-Kang Chang     absl::string_view jwk_set) {
365*e7b1675dSTing-Kang Chang   util::StatusOr<Struct> jwk_set_struct =
366*e7b1675dSTing-Kang Chang       jwt_internal::JsonStringToProtoStruct(jwk_set);
367*e7b1675dSTing-Kang Chang   if (!jwk_set_struct.ok()) {
368*e7b1675dSTing-Kang Chang     return jwk_set_struct.status();
369*e7b1675dSTing-Kang Chang   }
370*e7b1675dSTing-Kang Chang   auto it = jwk_set_struct->fields().find("keys");
371*e7b1675dSTing-Kang Chang   if (it == jwk_set_struct->fields().end()) {
372*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument, "keys not found");
373*e7b1675dSTing-Kang Chang   }
374*e7b1675dSTing-Kang Chang   if (it->second.kind_case() != Value::kListValue) {
375*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
376*e7b1675dSTing-Kang Chang                         "keys is not a list");
377*e7b1675dSTing-Kang Chang   }
378*e7b1675dSTing-Kang Chang   if (it->second.list_value().values_size() <= 0) {
379*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
380*e7b1675dSTing-Kang Chang                         "keys list is empty");
381*e7b1675dSTing-Kang Chang   }
382*e7b1675dSTing-Kang Chang   uint32_t last_key_id = 0;
383*e7b1675dSTing-Kang Chang   Keyset keyset;
384*e7b1675dSTing-Kang Chang   for (const Value& value : it->second.list_value().values()) {
385*e7b1675dSTing-Kang Chang     if (value.kind_case() != Value::kStructValue) {
386*e7b1675dSTing-Kang Chang       return util::Status(absl::StatusCode::kInvalidArgument,
387*e7b1675dSTing-Kang Chang                           "key is not a JSON object");
388*e7b1675dSTing-Kang Chang     }
389*e7b1675dSTing-Kang Chang     const Struct& key_struct = value.struct_value();
390*e7b1675dSTing-Kang Chang 
391*e7b1675dSTing-Kang Chang     util::StatusOr<std::string> alg = GetStringItem(key_struct, "alg");
392*e7b1675dSTing-Kang Chang     if (!alg.ok()) {
393*e7b1675dSTing-Kang Chang       return alg.status();
394*e7b1675dSTing-Kang Chang     }
395*e7b1675dSTing-Kang Chang     absl::string_view alg_prefix = absl::string_view(*alg).substr(0, 2);
396*e7b1675dSTing-Kang Chang 
397*e7b1675dSTing-Kang Chang     // Add to keyset
398*e7b1675dSTing-Kang Chang     Keyset_Key* key = keyset.add_key();
399*e7b1675dSTing-Kang Chang     uint32_t key_id = GenerateUnusedKeyId(keyset);
400*e7b1675dSTing-Kang Chang     key->set_key_id(key_id);
401*e7b1675dSTing-Kang Chang     key->set_status(KeyStatusType::ENABLED);
402*e7b1675dSTing-Kang Chang     key->set_output_prefix_type(OutputPrefixType::RAW);
403*e7b1675dSTing-Kang Chang 
404*e7b1675dSTing-Kang Chang     if (alg_prefix == "RS") {
405*e7b1675dSTing-Kang Chang       util::StatusOr<KeyData> key_data =
406*e7b1675dSTing-Kang Chang           RsPublicKeyDataFromKeyStruct(key_struct);
407*e7b1675dSTing-Kang Chang       if (!key_data.ok()) {
408*e7b1675dSTing-Kang Chang         return key_data.status();
409*e7b1675dSTing-Kang Chang       }
410*e7b1675dSTing-Kang Chang       *key->mutable_key_data() = *key_data;
411*e7b1675dSTing-Kang Chang     } else if (alg_prefix == "PS") {
412*e7b1675dSTing-Kang Chang       util::StatusOr<KeyData> key_data =
413*e7b1675dSTing-Kang Chang           PsPublicKeyDataFromKeyStruct(key_struct);
414*e7b1675dSTing-Kang Chang       if (!key_data.ok()) {
415*e7b1675dSTing-Kang Chang         return key_data.status();
416*e7b1675dSTing-Kang Chang       }
417*e7b1675dSTing-Kang Chang       *key->mutable_key_data() = *key_data;
418*e7b1675dSTing-Kang Chang     } else if (alg_prefix == "ES") {
419*e7b1675dSTing-Kang Chang       util::StatusOr<KeyData> key_data =
420*e7b1675dSTing-Kang Chang           EsPublicKeyDataFromKeyStruct(key_struct);
421*e7b1675dSTing-Kang Chang       if (!key_data.ok()) {
422*e7b1675dSTing-Kang Chang         return key_data.status();
423*e7b1675dSTing-Kang Chang       }
424*e7b1675dSTing-Kang Chang       *key->mutable_key_data() = *key_data;
425*e7b1675dSTing-Kang Chang     } else {
426*e7b1675dSTing-Kang Chang       return util::Status(absl::StatusCode::kInvalidArgument,
427*e7b1675dSTing-Kang Chang                           "invalid alg prefix");
428*e7b1675dSTing-Kang Chang     }
429*e7b1675dSTing-Kang Chang     last_key_id = key_id;
430*e7b1675dSTing-Kang Chang   }
431*e7b1675dSTing-Kang Chang   keyset.set_primary_key_id(last_key_id);
432*e7b1675dSTing-Kang Chang   return KeysetHandle::ReadNoSecret(keyset.SerializeAsString());
433*e7b1675dSTing-Kang Chang }
434*e7b1675dSTing-Kang Chang 
AddStringEntry(Struct * key,absl::string_view name,absl::string_view value)435*e7b1675dSTing-Kang Chang void AddStringEntry(Struct* key, absl::string_view name,
436*e7b1675dSTing-Kang Chang                     absl::string_view value) {
437*e7b1675dSTing-Kang Chang   auto val = key->mutable_fields()->insert({std::string(name), Value()});
438*e7b1675dSTing-Kang Chang   val.first->second.set_string_value(std::string(value));
439*e7b1675dSTing-Kang Chang }
440*e7b1675dSTing-Kang Chang 
AddKeyOpsVerifyEntry(Struct * key)441*e7b1675dSTing-Kang Chang void AddKeyOpsVerifyEntry(Struct* key) {
442*e7b1675dSTing-Kang Chang   auto key_ops = key->mutable_fields()->insert({"key_ops", Value()});
443*e7b1675dSTing-Kang Chang   key_ops.first->second.mutable_list_value()->add_values()->set_string_value(
444*e7b1675dSTing-Kang Chang       "verify");
445*e7b1675dSTing-Kang Chang }
446*e7b1675dSTing-Kang Chang 
447*e7b1675dSTing-Kang Chang 
EsPublicKeyToKeyStruct(const Keyset_Key & key)448*e7b1675dSTing-Kang Chang util::StatusOr<Struct> EsPublicKeyToKeyStruct(const Keyset_Key& key) {
449*e7b1675dSTing-Kang Chang   JwtEcdsaPublicKey public_key;
450*e7b1675dSTing-Kang Chang   if (!public_key.ParseFromString(key.key_data().value())) {
451*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
452*e7b1675dSTing-Kang Chang                         "parse JwtEcdsaPublicKey failed");
453*e7b1675dSTing-Kang Chang   }
454*e7b1675dSTing-Kang Chang 
455*e7b1675dSTing-Kang Chang   Struct output_key;
456*e7b1675dSTing-Kang Chang 
457*e7b1675dSTing-Kang Chang   switch (public_key.algorithm()) {
458*e7b1675dSTing-Kang Chang     case JwtEcdsaAlgorithm::ES256:
459*e7b1675dSTing-Kang Chang       AddStringEntry(&output_key, "crv", "P-256");
460*e7b1675dSTing-Kang Chang       AddStringEntry(&output_key, "alg", "ES256");
461*e7b1675dSTing-Kang Chang       break;
462*e7b1675dSTing-Kang Chang     case JwtEcdsaAlgorithm::ES384:
463*e7b1675dSTing-Kang Chang       AddStringEntry(&output_key, "crv", "P-384");
464*e7b1675dSTing-Kang Chang       AddStringEntry(&output_key, "alg", "ES384");
465*e7b1675dSTing-Kang Chang       break;
466*e7b1675dSTing-Kang Chang     case JwtEcdsaAlgorithm::ES512:
467*e7b1675dSTing-Kang Chang       AddStringEntry(&output_key, "crv", "P-521");
468*e7b1675dSTing-Kang Chang       AddStringEntry(&output_key, "alg", "ES512");
469*e7b1675dSTing-Kang Chang       break;
470*e7b1675dSTing-Kang Chang     default:
471*e7b1675dSTing-Kang Chang       return util::Status(absl::StatusCode::kInvalidArgument,
472*e7b1675dSTing-Kang Chang                           "unknown JwtEcdsaAlgorithm");
473*e7b1675dSTing-Kang Chang   }
474*e7b1675dSTing-Kang Chang 
475*e7b1675dSTing-Kang Chang   AddStringEntry(&output_key, "kty", "EC");
476*e7b1675dSTing-Kang Chang   AddStringEntry(&output_key, "x", absl::WebSafeBase64Escape(public_key.x()));
477*e7b1675dSTing-Kang Chang   AddStringEntry(&output_key, "y", absl::WebSafeBase64Escape(public_key.y()));
478*e7b1675dSTing-Kang Chang   AddStringEntry(&output_key, "use", "sig");
479*e7b1675dSTing-Kang Chang   AddKeyOpsVerifyEntry(&output_key);
480*e7b1675dSTing-Kang Chang 
481*e7b1675dSTing-Kang Chang   absl::optional<std::string> kid =
482*e7b1675dSTing-Kang Chang       jwt_internal::GetKid(key.key_id(), key.output_prefix_type());
483*e7b1675dSTing-Kang Chang   if (kid.has_value()) {
484*e7b1675dSTing-Kang Chang     AddStringEntry(&output_key, "kid", kid.value());
485*e7b1675dSTing-Kang Chang   } else if (public_key.has_custom_kid()) {
486*e7b1675dSTing-Kang Chang     AddStringEntry(&output_key, "kid", public_key.custom_kid().value());
487*e7b1675dSTing-Kang Chang   }
488*e7b1675dSTing-Kang Chang   return output_key;
489*e7b1675dSTing-Kang Chang }
490*e7b1675dSTing-Kang Chang 
RsPublicKeyToKeyStruct(const Keyset_Key & key)491*e7b1675dSTing-Kang Chang util::StatusOr<Struct> RsPublicKeyToKeyStruct(const Keyset_Key& key) {
492*e7b1675dSTing-Kang Chang   JwtRsaSsaPkcs1PublicKey public_key;
493*e7b1675dSTing-Kang Chang   if (!public_key.ParseFromString(key.key_data().value())) {
494*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
495*e7b1675dSTing-Kang Chang                         "parse JwtRsaSsaPkcs1PublicKey failed");
496*e7b1675dSTing-Kang Chang   }
497*e7b1675dSTing-Kang Chang 
498*e7b1675dSTing-Kang Chang   Struct output_key;
499*e7b1675dSTing-Kang Chang 
500*e7b1675dSTing-Kang Chang   switch (public_key.algorithm()) {
501*e7b1675dSTing-Kang Chang     case JwtRsaSsaPkcs1Algorithm::RS256:
502*e7b1675dSTing-Kang Chang       AddStringEntry(&output_key, "alg", "RS256");
503*e7b1675dSTing-Kang Chang       break;
504*e7b1675dSTing-Kang Chang     case JwtRsaSsaPkcs1Algorithm::RS384:
505*e7b1675dSTing-Kang Chang       AddStringEntry(&output_key, "alg", "RS384");
506*e7b1675dSTing-Kang Chang       break;
507*e7b1675dSTing-Kang Chang     case JwtRsaSsaPkcs1Algorithm::RS512:
508*e7b1675dSTing-Kang Chang       AddStringEntry(&output_key, "alg", "RS512");
509*e7b1675dSTing-Kang Chang       break;
510*e7b1675dSTing-Kang Chang     default:
511*e7b1675dSTing-Kang Chang       return util::Status(absl::StatusCode::kInvalidArgument,
512*e7b1675dSTing-Kang Chang                           "unknown JwtRsaSsaPkcs1Algorithm");
513*e7b1675dSTing-Kang Chang   }
514*e7b1675dSTing-Kang Chang 
515*e7b1675dSTing-Kang Chang   AddStringEntry(&output_key, "kty", "RSA");
516*e7b1675dSTing-Kang Chang   AddStringEntry(&output_key, "e", absl::WebSafeBase64Escape(public_key.e()));
517*e7b1675dSTing-Kang Chang   AddStringEntry(&output_key, "n", absl::WebSafeBase64Escape(public_key.n()));
518*e7b1675dSTing-Kang Chang   AddStringEntry(&output_key, "use", "sig");
519*e7b1675dSTing-Kang Chang   AddKeyOpsVerifyEntry(&output_key);
520*e7b1675dSTing-Kang Chang 
521*e7b1675dSTing-Kang Chang   absl::optional<std::string> kid =
522*e7b1675dSTing-Kang Chang       jwt_internal::GetKid(key.key_id(), key.output_prefix_type());
523*e7b1675dSTing-Kang Chang   if (kid.has_value()) {
524*e7b1675dSTing-Kang Chang     AddStringEntry(&output_key, "kid", kid.value());
525*e7b1675dSTing-Kang Chang   } else if (public_key.has_custom_kid()) {
526*e7b1675dSTing-Kang Chang     AddStringEntry(&output_key, "kid", public_key.custom_kid().value());
527*e7b1675dSTing-Kang Chang   }
528*e7b1675dSTing-Kang Chang   return output_key;
529*e7b1675dSTing-Kang Chang }
530*e7b1675dSTing-Kang Chang 
PsPublicKeyToKeyStruct(const Keyset_Key & key)531*e7b1675dSTing-Kang Chang util::StatusOr<Struct> PsPublicKeyToKeyStruct(const Keyset_Key& key) {
532*e7b1675dSTing-Kang Chang   JwtRsaSsaPssPublicKey public_key;
533*e7b1675dSTing-Kang Chang   if (!public_key.ParseFromString(key.key_data().value())) {
534*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
535*e7b1675dSTing-Kang Chang                         "parse JwtRsaSsaPkcs1PublicKey failed");
536*e7b1675dSTing-Kang Chang   }
537*e7b1675dSTing-Kang Chang 
538*e7b1675dSTing-Kang Chang   Struct output_key;
539*e7b1675dSTing-Kang Chang 
540*e7b1675dSTing-Kang Chang   switch (public_key.algorithm()) {
541*e7b1675dSTing-Kang Chang     case JwtRsaSsaPssAlgorithm::PS256:
542*e7b1675dSTing-Kang Chang       AddStringEntry(&output_key, "alg", "PS256");
543*e7b1675dSTing-Kang Chang       break;
544*e7b1675dSTing-Kang Chang     case JwtRsaSsaPssAlgorithm::PS384:
545*e7b1675dSTing-Kang Chang       AddStringEntry(&output_key, "alg", "PS384");
546*e7b1675dSTing-Kang Chang       break;
547*e7b1675dSTing-Kang Chang     case JwtRsaSsaPssAlgorithm::PS512:
548*e7b1675dSTing-Kang Chang       AddStringEntry(&output_key, "alg", "PS512");
549*e7b1675dSTing-Kang Chang       break;
550*e7b1675dSTing-Kang Chang     default:
551*e7b1675dSTing-Kang Chang       return util::Status(absl::StatusCode::kInvalidArgument,
552*e7b1675dSTing-Kang Chang                           "unknown JwtRsaSsaPkcs1Algorithm");
553*e7b1675dSTing-Kang Chang   }
554*e7b1675dSTing-Kang Chang 
555*e7b1675dSTing-Kang Chang   AddStringEntry(&output_key, "kty", "RSA");
556*e7b1675dSTing-Kang Chang   AddStringEntry(&output_key, "e", absl::WebSafeBase64Escape(public_key.e()));
557*e7b1675dSTing-Kang Chang   AddStringEntry(&output_key, "n", absl::WebSafeBase64Escape(public_key.n()));
558*e7b1675dSTing-Kang Chang   AddStringEntry(&output_key, "use", "sig");
559*e7b1675dSTing-Kang Chang   AddKeyOpsVerifyEntry(&output_key);
560*e7b1675dSTing-Kang Chang 
561*e7b1675dSTing-Kang Chang   absl::optional<std::string> kid =
562*e7b1675dSTing-Kang Chang       jwt_internal::GetKid(key.key_id(), key.output_prefix_type());
563*e7b1675dSTing-Kang Chang   if (kid.has_value()) {
564*e7b1675dSTing-Kang Chang     AddStringEntry(&output_key, "kid", kid.value());
565*e7b1675dSTing-Kang Chang   } else if (public_key.has_custom_kid()) {
566*e7b1675dSTing-Kang Chang     AddStringEntry(&output_key, "kid", public_key.custom_kid().value());
567*e7b1675dSTing-Kang Chang   }
568*e7b1675dSTing-Kang Chang   return output_key;
569*e7b1675dSTing-Kang Chang }
570*e7b1675dSTing-Kang Chang 
JwkSetFromPublicKeysetHandle(const KeysetHandle & keyset_handle)571*e7b1675dSTing-Kang Chang util::StatusOr<std::string> JwkSetFromPublicKeysetHandle(
572*e7b1675dSTing-Kang Chang     const KeysetHandle& keyset_handle) {
573*e7b1675dSTing-Kang Chang   std::stringbuf keyset_buf;
574*e7b1675dSTing-Kang Chang   util::StatusOr<std::unique_ptr<BinaryKeysetWriter>> writer =
575*e7b1675dSTing-Kang Chang       BinaryKeysetWriter::New(absl::make_unique<std::ostream>(&keyset_buf));
576*e7b1675dSTing-Kang Chang   if (!writer.ok()) {
577*e7b1675dSTing-Kang Chang     return writer.status();
578*e7b1675dSTing-Kang Chang   }
579*e7b1675dSTing-Kang Chang   util::Status status = keyset_handle.WriteNoSecret((*writer).get());
580*e7b1675dSTing-Kang Chang   if (!status.ok()) {
581*e7b1675dSTing-Kang Chang     return status;
582*e7b1675dSTing-Kang Chang   }
583*e7b1675dSTing-Kang Chang   Keyset keyset;
584*e7b1675dSTing-Kang Chang   if (!keyset.ParseFromString(keyset_buf.str())) {
585*e7b1675dSTing-Kang Chang     return util::Status(absl::StatusCode::kInvalidArgument,
586*e7b1675dSTing-Kang Chang                         "parse Keyset failed");
587*e7b1675dSTing-Kang Chang   }
588*e7b1675dSTing-Kang Chang 
589*e7b1675dSTing-Kang Chang   Struct output;
590*e7b1675dSTing-Kang Chang   auto insertion_result = output.mutable_fields()->insert({"keys", Value()});
591*e7b1675dSTing-Kang Chang   ListValue* keys_list = insertion_result.first->second.mutable_list_value();
592*e7b1675dSTing-Kang Chang 
593*e7b1675dSTing-Kang Chang   for (const Keyset::Key& key : keyset.key()) {
594*e7b1675dSTing-Kang Chang     if (key.status() != KeyStatusType::ENABLED) {
595*e7b1675dSTing-Kang Chang       continue;
596*e7b1675dSTing-Kang Chang     }
597*e7b1675dSTing-Kang Chang     if ((key.output_prefix_type() != OutputPrefixType::RAW) &&
598*e7b1675dSTing-Kang Chang         (key.output_prefix_type() != OutputPrefixType::TINK)) {
599*e7b1675dSTing-Kang Chang       return util::Status(absl::StatusCode::kInvalidArgument,
600*e7b1675dSTing-Kang Chang                           "Unknown output prefix type");
601*e7b1675dSTing-Kang Chang     }
602*e7b1675dSTing-Kang Chang 
603*e7b1675dSTing-Kang Chang     if (key.key_data().key_material_type() != KeyData::ASYMMETRIC_PUBLIC) {
604*e7b1675dSTing-Kang Chang       return util::Status(absl::StatusCode::kInvalidArgument,
605*e7b1675dSTing-Kang Chang                           "Only asymmetric public keys are supported");
606*e7b1675dSTing-Kang Chang     }
607*e7b1675dSTing-Kang Chang     if (key.key_data().type_url() ==
608*e7b1675dSTing-Kang Chang         "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey") {
609*e7b1675dSTing-Kang Chang       util::StatusOr<Struct> output_key = EsPublicKeyToKeyStruct(key);
610*e7b1675dSTing-Kang Chang       if (!output_key.ok()) {
611*e7b1675dSTing-Kang Chang         return output_key.status();
612*e7b1675dSTing-Kang Chang       }
613*e7b1675dSTing-Kang Chang       *keys_list->add_values()->mutable_struct_value() = *output_key;
614*e7b1675dSTing-Kang Chang     } else if (key.key_data().type_url() ==
615*e7b1675dSTing-Kang Chang                "type.googleapis.com/"
616*e7b1675dSTing-Kang Chang                "google.crypto.tink.JwtRsaSsaPkcs1PublicKey") {
617*e7b1675dSTing-Kang Chang       util::StatusOr<Struct> output_key = RsPublicKeyToKeyStruct(key);
618*e7b1675dSTing-Kang Chang       if (!output_key.ok()) {
619*e7b1675dSTing-Kang Chang         return output_key.status();
620*e7b1675dSTing-Kang Chang       }
621*e7b1675dSTing-Kang Chang       *keys_list->add_values()->mutable_struct_value() = *output_key;
622*e7b1675dSTing-Kang Chang     } else if (key.key_data().type_url() ==
623*e7b1675dSTing-Kang Chang                "type.googleapis.com/"
624*e7b1675dSTing-Kang Chang                "google.crypto.tink.JwtRsaSsaPssPublicKey") {
625*e7b1675dSTing-Kang Chang       util::StatusOr<Struct> output_key = PsPublicKeyToKeyStruct(key);
626*e7b1675dSTing-Kang Chang       if (!output_key.ok()) {
627*e7b1675dSTing-Kang Chang         return output_key.status();
628*e7b1675dSTing-Kang Chang       }
629*e7b1675dSTing-Kang Chang       *keys_list->add_values()->mutable_struct_value() = *output_key;
630*e7b1675dSTing-Kang Chang     } else {
631*e7b1675dSTing-Kang Chang       return util::Status(absl::StatusCode::kInvalidArgument,
632*e7b1675dSTing-Kang Chang                           "Unknown key type url");
633*e7b1675dSTing-Kang Chang     }
634*e7b1675dSTing-Kang Chang   }
635*e7b1675dSTing-Kang Chang   return jwt_internal::ProtoStructToJsonString(output);
636*e7b1675dSTing-Kang Chang }
637*e7b1675dSTing-Kang Chang 
638*e7b1675dSTing-Kang Chang }  // namespace tink
639*e7b1675dSTing-Kang Chang }  // namespace crypto
640