xref: /aosp_15_r20/external/tink/cc/jwt/internal/jwt_ecdsa_sign_verify_key_manager_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2021 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 
17 #include <memory>
18 #include <string>
19 #include <utility>
20 #include <vector>
21 
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "absl/strings/str_split.h"
25 #include "tink/jwt/internal/json_util.h"
26 #include "tink/jwt/internal/jwt_ecdsa_sign_key_manager.h"
27 #include "tink/jwt/internal/jwt_ecdsa_verify_key_manager.h"
28 #include "tink/jwt/internal/jwt_format.h"
29 #include "tink/util/status.h"
30 #include "tink/util/statusor.h"
31 #include "tink/util/test_matchers.h"
32 
33 namespace crypto {
34 namespace tink {
35 namespace jwt_internal {
36 
37 using ::crypto::tink::test::IsOk;
38 using ::crypto::tink::test::IsOkAndHolds;
39 using ::crypto::tink::util::StatusOr;
40 using ::google::crypto::tink::JwtEcdsaAlgorithm;
41 using ::google::crypto::tink::JwtEcdsaKeyFormat;
42 using ::google::crypto::tink::JwtEcdsaPrivateKey;
43 using ::google::crypto::tink::JwtEcdsaPublicKey;
44 using ::google::crypto::tink::KeyData;
45 using ::testing::Eq;
46 using ::testing::Not;
47 
48 namespace {
49 
50 constexpr absl::string_view kTestKid = "kid-123";
51 
TEST(JwtEcdsaSignVerifyKeyManagerTest,BasicsSign)52 TEST(JwtEcdsaSignVerifyKeyManagerTest, BasicsSign) {
53   EXPECT_EQ(JwtEcdsaSignKeyManager().get_version(), 0);
54   EXPECT_EQ(JwtEcdsaSignKeyManager().get_key_type(),
55             "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey");
56   EXPECT_EQ(JwtEcdsaSignKeyManager().key_material_type(),
57             KeyData::ASYMMETRIC_PRIVATE);
58 }
59 
TEST(JwtEcdsaSignVerifyKeyManagerTest,BasicsVerify)60 TEST(JwtEcdsaSignVerifyKeyManagerTest, BasicsVerify) {
61   EXPECT_EQ(JwtEcdsaVerifyKeyManager().get_version(), 0);
62   EXPECT_EQ(JwtEcdsaVerifyKeyManager().get_key_type(),
63             "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey");
64   EXPECT_EQ(JwtEcdsaVerifyKeyManager().key_material_type(),
65             KeyData::ASYMMETRIC_PUBLIC);
66 }
67 
TEST(JwtEcdsaSignVerifyKeyManagerTest,ValidateEmptyPrivateKey)68 TEST(JwtEcdsaSignVerifyKeyManagerTest, ValidateEmptyPrivateKey) {
69   EXPECT_THAT(JwtEcdsaSignKeyManager().ValidateKey(JwtEcdsaPrivateKey()),
70               Not(IsOk()));
71 }
72 
TEST(JwtEcdsaSignVerifyKeyManagerTest,ValidateEmptyPublicKey)73 TEST(JwtEcdsaSignVerifyKeyManagerTest, ValidateEmptyPublicKey) {
74   EXPECT_THAT(JwtEcdsaVerifyKeyManager().ValidateKey(JwtEcdsaPublicKey()),
75               Not(IsOk()));
76 }
77 
TEST(JwtEcdsaSignVerifyKeyManagerTest,ValidateEmptyKeyFormat)78 TEST(JwtEcdsaSignVerifyKeyManagerTest, ValidateEmptyKeyFormat) {
79   EXPECT_THAT(JwtEcdsaSignKeyManager().ValidateKeyFormat(JwtEcdsaKeyFormat()),
80               Not(IsOk()));
81 }
82 
TEST(JwtEcdsaSignVerifyKeyManagerTest,ValidKeyFormatES256)83 TEST(JwtEcdsaSignVerifyKeyManagerTest, ValidKeyFormatES256) {
84   JwtEcdsaKeyFormat key_format;
85   key_format.set_algorithm(JwtEcdsaAlgorithm::ES256);
86   EXPECT_THAT(JwtEcdsaSignKeyManager().ValidateKeyFormat(key_format), IsOk());
87 }
88 
TEST(JwtEcdsaSignVerifyKeyManagerTest,ValidateKeyFormatES384)89 TEST(JwtEcdsaSignVerifyKeyManagerTest, ValidateKeyFormatES384) {
90   JwtEcdsaKeyFormat key_format;
91   key_format.set_algorithm(JwtEcdsaAlgorithm::ES384);
92   EXPECT_THAT(JwtEcdsaSignKeyManager().ValidateKeyFormat(key_format), IsOk());
93 }
94 
TEST(JwtEcdsaSignVerifyKeyManagerTest,ValidateKeyFormatES512)95 TEST(JwtEcdsaSignVerifyKeyManagerTest, ValidateKeyFormatES512) {
96   JwtEcdsaKeyFormat key_format;
97   key_format.set_algorithm(JwtEcdsaAlgorithm::ES512);
98   EXPECT_THAT(JwtEcdsaSignKeyManager().ValidateKeyFormat(key_format), IsOk());
99 }
100 
TEST(JwtEcdsaSignVerifyKeyManagerTest,CreatePrivateKeyAndValidate)101 TEST(JwtEcdsaSignVerifyKeyManagerTest, CreatePrivateKeyAndValidate) {
102   JwtEcdsaKeyFormat key_format;
103   key_format.set_algorithm(JwtEcdsaAlgorithm::ES256);
104   util::StatusOr<JwtEcdsaPrivateKey> key =
105       JwtEcdsaSignKeyManager().CreateKey(key_format);
106   ASSERT_THAT(key, IsOk());
107   EXPECT_EQ(key->version(), 0);
108   EXPECT_EQ(key->public_key().algorithm(), key_format.algorithm());
109   EXPECT_THAT(JwtEcdsaSignKeyManager().ValidateKey(*key), IsOk());
110 
111   // Change key to an invalid algorithm.
112   key->mutable_public_key()->set_algorithm(JwtEcdsaAlgorithm::ES_UNKNOWN);
113   EXPECT_FALSE(JwtEcdsaSignKeyManager().ValidateKey(*key).ok());
114 }
115 
TEST(JwtEcdsaSignVerifyKeyManagerTest,CreatePublicKeyAndValidate)116 TEST(JwtEcdsaSignVerifyKeyManagerTest, CreatePublicKeyAndValidate) {
117   JwtEcdsaKeyFormat key_format;
118   key_format.set_algorithm(JwtEcdsaAlgorithm::ES256);
119   util::StatusOr<JwtEcdsaPrivateKey> key =
120       JwtEcdsaSignKeyManager().CreateKey(key_format);
121   ASSERT_THAT(key, IsOk());
122   util::StatusOr<JwtEcdsaPublicKey> public_key =
123       JwtEcdsaSignKeyManager().GetPublicKey(*key);
124   EXPECT_THAT(JwtEcdsaVerifyKeyManager().ValidateKey(*public_key), IsOk());
125 
126   // Change key to an invalid algorithm.
127   public_key->set_algorithm(JwtEcdsaAlgorithm::ES_UNKNOWN);
128   EXPECT_FALSE(JwtEcdsaVerifyKeyManager().ValidateKey(*public_key).ok());
129 }
130 
TEST(JwtEcdsaSignVerifyKeyManagerTest,GetAndUsePrimitive)131 TEST(JwtEcdsaSignVerifyKeyManagerTest, GetAndUsePrimitive) {
132   JwtEcdsaKeyFormat key_format;
133   key_format.set_algorithm(JwtEcdsaAlgorithm::ES256);
134   util::StatusOr<JwtEcdsaPrivateKey> key =
135       JwtEcdsaSignKeyManager().CreateKey(key_format);
136   ASSERT_THAT(key, IsOk());
137 
138   util::StatusOr<std::unique_ptr<JwtPublicKeySignInternal>> sign =
139       JwtEcdsaSignKeyManager().GetPrimitive<JwtPublicKeySignInternal>(*key);
140   ASSERT_THAT(sign, IsOk());
141 
142   util::StatusOr<RawJwt> raw_jwt =
143       RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build();
144   ASSERT_THAT(raw_jwt, IsOk());
145 
146   util::StatusOr<std::string> compact =
147       (*sign)->SignAndEncodeWithKid(*raw_jwt, /*kid=*/absl::nullopt);
148   ASSERT_THAT(compact, IsOk());
149 
150   util::StatusOr<JwtValidator> validator = JwtValidatorBuilder()
151                                                .ExpectIssuer("issuer")
152                                                .AllowMissingExpiration()
153                                                .Build();
154   ASSERT_THAT(validator, IsOk());
155   util::StatusOr<std::unique_ptr<JwtPublicKeyVerifyInternal>> verify =
156       JwtEcdsaVerifyKeyManager().GetPrimitive<JwtPublicKeyVerifyInternal>(
157           key->public_key());
158   ASSERT_THAT(verify, IsOk());
159 
160   util::StatusOr<VerifiedJwt> verified_jwt = (*verify)->VerifyAndDecodeWithKid(
161       *compact, *validator, /*kid=*/absl::nullopt);
162   ASSERT_THAT(verified_jwt, IsOk());
163   util::StatusOr<std::string> issuer = verified_jwt->GetIssuer();
164   EXPECT_THAT(issuer, IsOkAndHolds("issuer"));
165 
166   EXPECT_THAT((*verify)
167                   ->VerifyAndDecodeWithKid(*compact, *validator, kTestKid)
168                   .status(),
169               Not(IsOk()));
170 
171   util::StatusOr<JwtValidator> validator2 =
172       JwtValidatorBuilder().ExpectIssuer("unknown").Build();
173   ASSERT_THAT(validator2, IsOk());
174   EXPECT_THAT(
175       (*verify)
176           ->VerifyAndDecodeWithKid(*compact, *validator2, /*kid=*/absl::nullopt)
177           .status(),
178       Not(IsOk()));
179 
180   // Token with kid header
181   util::StatusOr<std::string> token_with_kid =
182       (*sign)->SignAndEncodeWithKid(*raw_jwt, kTestKid);
183   ASSERT_THAT(compact, IsOk());
184   EXPECT_THAT((*verify)
185                   ->VerifyAndDecodeWithKid(*token_with_kid, *validator,
186                                            /*kid=*/absl::nullopt)
187                   .status(),
188               IsOk());
189   EXPECT_THAT(
190       (*verify)
191           ->VerifyAndDecodeWithKid(*token_with_kid, *validator, kTestKid)
192           .status(),
193       IsOk());
194   EXPECT_THAT(
195       (*verify)
196           ->VerifyAndDecodeWithKid(*token_with_kid, *validator, "other-kid")
197           .status(),
198       Not(IsOk()));
199 }
200 
TEST(JwtRsaSsaPkcs1SignVerifyKeyManagerTest,GetAndUsePrimitivesWithCustomKid)201 TEST(JwtRsaSsaPkcs1SignVerifyKeyManagerTest, GetAndUsePrimitivesWithCustomKid) {
202   JwtEcdsaKeyFormat key_format;
203   key_format.set_algorithm(JwtEcdsaAlgorithm::ES256);
204   util::StatusOr<JwtEcdsaPrivateKey> key =
205       JwtEcdsaSignKeyManager().CreateKey(key_format);
206   ASSERT_THAT(key, IsOk());
207   key->mutable_public_key()->mutable_custom_kid()->set_value(
208       "Lorem ipsum dolor sit amet, consectetur adipiscing elit");
209 
210   util::StatusOr<std::unique_ptr<JwtPublicKeySignInternal>> sign =
211       JwtEcdsaSignKeyManager().GetPrimitive<JwtPublicKeySignInternal>(*key);
212   ASSERT_THAT(sign, IsOk());
213 
214   util::StatusOr<RawJwt> raw_jwt =
215       RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build();
216   ASSERT_THAT(raw_jwt, IsOk());
217 
218   util::StatusOr<std::string> compact =
219       (*sign)->SignAndEncodeWithKid(*raw_jwt, /*kid=*/absl::nullopt);
220   ASSERT_THAT(compact, IsOk());
221 
222   // parse header and check "kid"
223   std::vector<absl::string_view> parts = absl::StrSplit(*compact, '.');
224   ASSERT_THAT(parts.size(), Eq(3));
225   std::string json_header;
226   ASSERT_TRUE(DecodeHeader(parts[0], &json_header));
227   util::StatusOr<google::protobuf::Struct> header =
228       JsonStringToProtoStruct(json_header);
229   ASSERT_THAT(header, IsOk());
230   auto it = header->fields().find("kid");
231   ASSERT_FALSE(it == header->fields().end());
232   EXPECT_THAT(it->second.string_value(),
233               Eq("Lorem ipsum dolor sit amet, consectetur adipiscing elit"));
234 
235   // validate token
236   util::StatusOr<JwtValidator> validator = JwtValidatorBuilder()
237                                                .ExpectIssuer("issuer")
238                                                .AllowMissingExpiration()
239                                                .Build();
240   ASSERT_THAT(validator, IsOk());
241   util::StatusOr<std::unique_ptr<JwtPublicKeyVerifyInternal>> verify =
242       JwtEcdsaVerifyKeyManager().GetPrimitive<JwtPublicKeyVerifyInternal>(
243           key->public_key());
244   ASSERT_THAT(verify, IsOk());
245 
246   util::StatusOr<VerifiedJwt> verified_jwt = (*verify)->VerifyAndDecodeWithKid(
247       *compact, *validator, /*kid=*/absl::nullopt);
248   ASSERT_THAT(verified_jwt, IsOk());
249   util::StatusOr<std::string> issuer = verified_jwt->GetIssuer();
250   ASSERT_THAT(issuer, IsOk());
251   EXPECT_THAT(*issuer, Eq("issuer"));
252 
253   // passing a kid when custom_kid is set should fail
254   EXPECT_THAT((*sign)->SignAndEncodeWithKid(*raw_jwt, kTestKid).status(),
255               Not(IsOk()));
256   EXPECT_THAT((*verify)
257                   ->VerifyAndDecodeWithKid(*compact, *validator, kTestKid)
258                   .status(),
259               Not(IsOk()));
260 
261   // Test that custom kid is verified: validation should fail with other kid.
262   key->mutable_public_key()->mutable_custom_kid()->set_value("other kid");
263   ASSERT_THAT(validator, IsOk());
264   util::StatusOr<std::unique_ptr<JwtPublicKeyVerifyInternal>> other_verify =
265       JwtEcdsaVerifyKeyManager().GetPrimitive<JwtPublicKeyVerifyInternal>(
266           key->public_key());
267   ASSERT_THAT(other_verify, IsOk());
268   EXPECT_THAT(
269       (*other_verify)
270           ->VerifyAndDecodeWithKid(*compact, *validator, /*kid=*/absl::nullopt)
271           .status(),
272       Not(IsOk()));
273 }
274 
TEST(JwtEcdsaSignVerifyKeyManagerTest,VerifyFailsWithDifferentKey)275 TEST(JwtEcdsaSignVerifyKeyManagerTest, VerifyFailsWithDifferentKey) {
276   JwtEcdsaKeyFormat key_format;
277   key_format.set_algorithm(JwtEcdsaAlgorithm::ES256);
278   util::StatusOr<JwtEcdsaPrivateKey> key1 =
279       JwtEcdsaSignKeyManager().CreateKey(key_format);
280   ASSERT_THAT(key1, IsOk());
281 
282   util::StatusOr<JwtEcdsaPrivateKey> key2 =
283       JwtEcdsaSignKeyManager().CreateKey(key_format);
284   ASSERT_THAT(key2, IsOk());
285 
286   util::StatusOr<std::unique_ptr<JwtPublicKeySignInternal>> sign1 =
287       JwtEcdsaSignKeyManager().GetPrimitive<JwtPublicKeySignInternal>(*key1);
288   ASSERT_THAT(sign1, IsOk());
289 
290   util::StatusOr<RawJwt> raw_jwt =
291       RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build();
292   ASSERT_THAT(raw_jwt, IsOk());
293 
294   util::StatusOr<std::string> compact =
295       (*sign1)->SignAndEncodeWithKid(*raw_jwt, /*kid=*/absl::nullopt);
296   ASSERT_THAT(compact, IsOk());
297 
298   util::StatusOr<JwtValidator> validator =
299       JwtValidatorBuilder().AllowMissingExpiration().Build();
300   util::StatusOr<std::unique_ptr<JwtPublicKeyVerifyInternal>> verify2 =
301       JwtEcdsaVerifyKeyManager().GetPrimitive<JwtPublicKeyVerifyInternal>(
302           key2->public_key());
303   EXPECT_THAT(verify2, IsOk());
304 
305   EXPECT_THAT(
306       (*verify2)
307           ->VerifyAndDecodeWithKid(*compact, *validator, /*kid=*/absl::nullopt)
308           .status(),
309       Not(IsOk()));
310 }
311 
312 }  // namespace
313 }  // namespace jwt_internal
314 }  // namespace tink
315 }  // namespace crypto
316