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