• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 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 package com.google.crypto.tink.jwt;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static com.google.crypto.tink.internal.testing.Asserts.assertEqualWhenValueParsed;
21 import static org.junit.Assert.assertThrows;
22 
23 import com.google.crypto.tink.InsecureSecretKeyAccess;
24 import com.google.crypto.tink.Key;
25 import com.google.crypto.tink.Parameters;
26 import com.google.crypto.tink.internal.MutableSerializationRegistry;
27 import com.google.crypto.tink.internal.ProtoKeySerialization;
28 import com.google.crypto.tink.internal.ProtoParametersSerialization;
29 import com.google.crypto.tink.proto.JwtHmacAlgorithm;
30 import com.google.crypto.tink.proto.JwtHmacKey.CustomKid;
31 import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
32 import com.google.crypto.tink.proto.OutputPrefixType;
33 import com.google.crypto.tink.util.SecretBytes;
34 import com.google.protobuf.ByteString;
35 import java.security.GeneralSecurityException;
36 import org.junit.BeforeClass;
37 import org.junit.Test;
38 import org.junit.experimental.theories.Theories;
39 import org.junit.runner.RunWith;
40 
41 /** Test for JwtHmacProtoSerialization. */
42 @RunWith(Theories.class)
43 public final class JwtHmacProtoSerializationTest {
44   private static final String TYPE_URL = "type.googleapis.com/google.crypto.tink.JwtHmacKey";
45 
46   private static final SecretBytes KEY_BYTES_42 = SecretBytes.randomBytes(42);
47   private static final ByteString KEY_BYTES_42_AS_BYTE_STRING =
48       ByteString.copyFrom(KEY_BYTES_42.toByteArray(InsecureSecretKeyAccess.get()));
49 
50   private static final MutableSerializationRegistry registry = new MutableSerializationRegistry();
51 
52   @BeforeClass
setUp()53   public static void setUp() throws Exception {
54     JwtHmacProtoSerialization.register(registry);
55   }
56 
57   // PARAMETERS PARSING ========================================================= PARAMETERS PARSING
58   @Test
serializeParseParameters_kidStrategyIsIgnored_works()59   public void serializeParseParameters_kidStrategyIsIgnored_works() throws Exception {
60     JwtHmacParameters parameters =
61         JwtHmacParameters.builder()
62             .setKeySizeBytes(19)
63             .setAlgorithm(JwtHmacParameters.Algorithm.HS256)
64             .setKidStrategy(JwtHmacParameters.KidStrategy.IGNORED)
65             .build();
66     ProtoParametersSerialization serialization =
67         ProtoParametersSerialization.create(
68             TYPE_URL,
69             OutputPrefixType.RAW,
70             com.google.crypto.tink.proto.JwtHmacKeyFormat.newBuilder()
71                 .setVersion(0)
72                 .setAlgorithm(JwtHmacAlgorithm.HS256)
73                 .setKeySize(19)
74                 .build());
75 
76     ProtoParametersSerialization serialized =
77         registry.serializeParameters(parameters, ProtoParametersSerialization.class);
78     assertEqualWhenValueParsed(
79         com.google.crypto.tink.proto.JwtHmacKeyFormat.parser(), serialized, serialization);
80 
81     Parameters parsed = registry.parseParameters(serialization);
82     assertThat(parsed).isEqualTo(parameters);
83   }
84 
85   @Test
serializeParseParameters_kidStrategyIsIgnored_differentKeySize_works()86   public void serializeParseParameters_kidStrategyIsIgnored_differentKeySize_works()
87       throws Exception {
88     JwtHmacParameters parameters =
89         JwtHmacParameters.builder()
90             .setKeySizeBytes(21)
91             .setAlgorithm(JwtHmacParameters.Algorithm.HS256)
92             .setKidStrategy(JwtHmacParameters.KidStrategy.IGNORED)
93             .build();
94     ProtoParametersSerialization serialization =
95         ProtoParametersSerialization.create(
96             TYPE_URL,
97             OutputPrefixType.RAW,
98             com.google.crypto.tink.proto.JwtHmacKeyFormat.newBuilder()
99                 .setVersion(0)
100                 .setAlgorithm(JwtHmacAlgorithm.HS256)
101                 .setKeySize(21)
102                 .build());
103 
104     ProtoParametersSerialization serialized =
105         registry.serializeParameters(parameters, ProtoParametersSerialization.class);
106     assertEqualWhenValueParsed(
107         com.google.crypto.tink.proto.JwtHmacKeyFormat.parser(), serialized, serialization);
108 
109     Parameters parsed = registry.parseParameters(serialization);
110     assertThat(parsed).isEqualTo(parameters);
111   }
112 
113   @Test
serializeParseParameters_kidStrategyIsIgnored_differentAlgorithm_works()114   public void serializeParseParameters_kidStrategyIsIgnored_differentAlgorithm_works()
115       throws Exception {
116     JwtHmacParameters parameters =
117         JwtHmacParameters.builder()
118             .setKeySizeBytes(19)
119             .setAlgorithm(JwtHmacParameters.Algorithm.HS512)
120             .setKidStrategy(JwtHmacParameters.KidStrategy.IGNORED)
121             .build();
122     ProtoParametersSerialization serialization =
123         ProtoParametersSerialization.create(
124             TYPE_URL,
125             OutputPrefixType.RAW,
126             com.google.crypto.tink.proto.JwtHmacKeyFormat.newBuilder()
127                 .setVersion(0)
128                 .setAlgorithm(JwtHmacAlgorithm.HS512)
129                 .setKeySize(19)
130                 .build());
131 
132     ProtoParametersSerialization serialized =
133         registry.serializeParameters(parameters, ProtoParametersSerialization.class);
134     assertEqualWhenValueParsed(
135         com.google.crypto.tink.proto.JwtHmacKeyFormat.parser(), serialized, serialization);
136 
137     Parameters parsed = registry.parseParameters(serialization);
138     assertThat(parsed).isEqualTo(parameters);
139   }
140 
141   @Test
serializeParseParameters_kidStrategyBase64_works()142   public void serializeParseParameters_kidStrategyBase64_works() throws Exception {
143     JwtHmacParameters parameters =
144         JwtHmacParameters.builder()
145             .setKeySizeBytes(19)
146             .setAlgorithm(JwtHmacParameters.Algorithm.HS256)
147             .setKidStrategy(JwtHmacParameters.KidStrategy.BASE64_ENCODED_KEY_ID)
148             .build();
149     ProtoParametersSerialization serialization =
150         ProtoParametersSerialization.create(
151             TYPE_URL,
152             OutputPrefixType.TINK,
153             com.google.crypto.tink.proto.JwtHmacKeyFormat.newBuilder()
154                 .setVersion(0)
155                 .setAlgorithm(JwtHmacAlgorithm.HS256)
156                 .setKeySize(19)
157                 .build());
158 
159     ProtoParametersSerialization serialized =
160         registry.serializeParameters(parameters, ProtoParametersSerialization.class);
161     assertEqualWhenValueParsed(
162         com.google.crypto.tink.proto.JwtHmacKeyFormat.parser(), serialized, serialization);
163 
164     Parameters parsed = registry.parseParameters(serialization);
165     assertThat(parsed).isEqualTo(parameters);
166   }
167 
168   // INVALID PARAMETERS SERIALIZATIONS =========================== INVALID PARAMETERS SERIALIZATIONS
169   @Test
serializeParameters_kidStrategyCustom_cannotBeSerialized_throws()170   public void serializeParameters_kidStrategyCustom_cannotBeSerialized_throws() throws Exception {
171     JwtHmacParameters parameters =
172         JwtHmacParameters.builder()
173             .setKeySizeBytes(19)
174             .setAlgorithm(JwtHmacParameters.Algorithm.HS256)
175             .setKidStrategy(JwtHmacParameters.KidStrategy.CUSTOM)
176             .build();
177     assertThrows(
178         GeneralSecurityException.class,
179         () -> registry.serializeParameters(parameters, ProtoParametersSerialization.class));
180   }
181 
182   @Test
parseParameters_crunchy_cannotBeParsed_throws()183   public void parseParameters_crunchy_cannotBeParsed_throws() throws Exception {
184     ProtoParametersSerialization serialization =
185         ProtoParametersSerialization.create(
186             TYPE_URL,
187             OutputPrefixType.CRUNCHY,
188             com.google.crypto.tink.proto.JwtHmacKeyFormat.newBuilder()
189                 .setVersion(0)
190                 .setAlgorithm(JwtHmacAlgorithm.HS256)
191                 .setKeySize(19)
192                 .build());
193     assertThrows(GeneralSecurityException.class, () -> registry.parseParameters(serialization));
194   }
195 
196   // KEYS PARSING ===================================================================== KEYS PARSING
197   @Test
serializeParseKey_kidStrategyIsIgnored_works()198   public void serializeParseKey_kidStrategyIsIgnored_works() throws Exception {
199     JwtHmacParameters parameters =
200         JwtHmacParameters.builder()
201             .setKeySizeBytes(42)
202             .setAlgorithm(JwtHmacParameters.Algorithm.HS256)
203             .setKidStrategy(JwtHmacParameters.KidStrategy.IGNORED)
204             .build();
205     JwtHmacKey key =
206         JwtHmacKey.builder().setParameters(parameters).setKeyBytes(KEY_BYTES_42).build();
207 
208     com.google.crypto.tink.proto.JwtHmacKey protoKey =
209         com.google.crypto.tink.proto.JwtHmacKey.newBuilder()
210             .setVersion(0)
211             .setAlgorithm(JwtHmacAlgorithm.HS256)
212             .setKeyValue(KEY_BYTES_42_AS_BYTE_STRING)
213             .build();
214     ProtoKeySerialization serialization =
215         ProtoKeySerialization.create(
216             "type.googleapis.com/google.crypto.tink.JwtHmacKey",
217             protoKey.toByteString(),
218             KeyMaterialType.SYMMETRIC,
219             OutputPrefixType.RAW,
220             /* idRequirement= */ null);
221 
222     ProtoKeySerialization serialized =
223         registry.serializeKey(key, ProtoKeySerialization.class, InsecureSecretKeyAccess.get());
224     assertEqualWhenValueParsed(
225         com.google.crypto.tink.proto.JwtHmacKey.parser(), serialized, serialization);
226 
227     Key parsed = registry.parseKey(serialization, InsecureSecretKeyAccess.get());
228     assertThat(parsed.equalsKey(key)).isTrue();
229   }
230 
231   @Test
serializeParseKey_kidStrategyIsIgnored_differentAlgorithm_works()232   public void serializeParseKey_kidStrategyIsIgnored_differentAlgorithm_works() throws Exception {
233     JwtHmacParameters parameters =
234         JwtHmacParameters.builder()
235             .setKeySizeBytes(42)
236             .setAlgorithm(JwtHmacParameters.Algorithm.HS384)
237             .setKidStrategy(JwtHmacParameters.KidStrategy.IGNORED)
238             .build();
239     JwtHmacKey key =
240         JwtHmacKey.builder().setParameters(parameters).setKeyBytes(KEY_BYTES_42).build();
241 
242     com.google.crypto.tink.proto.JwtHmacKey protoKey =
243         com.google.crypto.tink.proto.JwtHmacKey.newBuilder()
244             .setVersion(0)
245             .setAlgorithm(JwtHmacAlgorithm.HS384)
246             .setKeyValue(KEY_BYTES_42_AS_BYTE_STRING)
247             .build();
248     ProtoKeySerialization serialization =
249         ProtoKeySerialization.create(
250             "type.googleapis.com/google.crypto.tink.JwtHmacKey",
251             protoKey.toByteString(),
252             KeyMaterialType.SYMMETRIC,
253             OutputPrefixType.RAW,
254             /* idRequirement= */ null);
255 
256     ProtoKeySerialization serialized =
257         registry.serializeKey(key, ProtoKeySerialization.class, InsecureSecretKeyAccess.get());
258     assertEqualWhenValueParsed(
259         com.google.crypto.tink.proto.JwtHmacKey.parser(), serialized, serialization);
260 
261     Key parsed = registry.parseKey(serialization, InsecureSecretKeyAccess.get());
262     assertThat(parsed.equalsKey(key)).isTrue();
263   }
264 
265   @Test
serializeParseKey_kidStrategyIsCustom_works()266   public void serializeParseKey_kidStrategyIsCustom_works() throws Exception {
267     JwtHmacParameters parameters =
268         JwtHmacParameters.builder()
269             .setKeySizeBytes(42)
270             .setAlgorithm(JwtHmacParameters.Algorithm.HS512)
271             .setKidStrategy(JwtHmacParameters.KidStrategy.CUSTOM)
272             .build();
273     JwtHmacKey key =
274         JwtHmacKey.builder()
275             .setParameters(parameters)
276             .setKeyBytes(KEY_BYTES_42)
277             .setCustomKid("customKidForThisTest")
278             .build();
279 
280     com.google.crypto.tink.proto.JwtHmacKey protoKey =
281         com.google.crypto.tink.proto.JwtHmacKey.newBuilder()
282             .setVersion(0)
283             .setAlgorithm(JwtHmacAlgorithm.HS512)
284             .setKeyValue(KEY_BYTES_42_AS_BYTE_STRING)
285             .setCustomKid(CustomKid.newBuilder().setValue("customKidForThisTest"))
286             .build();
287     ProtoKeySerialization serialization =
288         ProtoKeySerialization.create(
289             "type.googleapis.com/google.crypto.tink.JwtHmacKey",
290             protoKey.toByteString(),
291             KeyMaterialType.SYMMETRIC,
292             OutputPrefixType.RAW,
293             /* idRequirement= */ null);
294 
295     ProtoKeySerialization serialized =
296         registry.serializeKey(key, ProtoKeySerialization.class, InsecureSecretKeyAccess.get());
297     assertEqualWhenValueParsed(
298         com.google.crypto.tink.proto.JwtHmacKey.parser(), serialized, serialization);
299 
300     Key parsed = registry.parseKey(serialization, InsecureSecretKeyAccess.get());
301     assertThat(parsed.equalsKey(key)).isTrue();
302   }
303 
304   @Test
serializeParseKey_kidStrategyIsCustom_differentAlgorithm_works()305   public void serializeParseKey_kidStrategyIsCustom_differentAlgorithm_works() throws Exception {
306     JwtHmacParameters parameters =
307         JwtHmacParameters.builder()
308             .setKeySizeBytes(42)
309             .setAlgorithm(JwtHmacParameters.Algorithm.HS384)
310             .setKidStrategy(JwtHmacParameters.KidStrategy.CUSTOM)
311             .build();
312     JwtHmacKey key =
313         JwtHmacKey.builder()
314             .setParameters(parameters)
315             .setKeyBytes(KEY_BYTES_42)
316             .setCustomKid("customKidForThisTest")
317             .build();
318 
319     com.google.crypto.tink.proto.JwtHmacKey protoKey =
320         com.google.crypto.tink.proto.JwtHmacKey.newBuilder()
321             .setVersion(0)
322             .setAlgorithm(JwtHmacAlgorithm.HS384)
323             .setKeyValue(KEY_BYTES_42_AS_BYTE_STRING)
324             .setCustomKid(CustomKid.newBuilder().setValue("customKidForThisTest"))
325             .build();
326     ProtoKeySerialization serialization =
327         ProtoKeySerialization.create(
328             "type.googleapis.com/google.crypto.tink.JwtHmacKey",
329             protoKey.toByteString(),
330             KeyMaterialType.SYMMETRIC,
331             OutputPrefixType.RAW,
332             /* idRequirement= */ null);
333 
334     ProtoKeySerialization serialized =
335         registry.serializeKey(key, ProtoKeySerialization.class, InsecureSecretKeyAccess.get());
336     assertEqualWhenValueParsed(
337         com.google.crypto.tink.proto.JwtHmacKey.parser(), serialized, serialization);
338 
339     Key parsed = registry.parseKey(serialization, InsecureSecretKeyAccess.get());
340     assertThat(parsed.equalsKey(key)).isTrue();
341   }
342 
343   @Test
serializeParseKey_kidStrategyIsBase64_works()344   public void serializeParseKey_kidStrategyIsBase64_works() throws Exception {
345     JwtHmacParameters parameters =
346         JwtHmacParameters.builder()
347             .setKeySizeBytes(42)
348             .setAlgorithm(JwtHmacParameters.Algorithm.HS384)
349             .setKidStrategy(JwtHmacParameters.KidStrategy.BASE64_ENCODED_KEY_ID)
350             .build();
351     JwtHmacKey key =
352         JwtHmacKey.builder()
353             .setParameters(parameters)
354             .setKeyBytes(KEY_BYTES_42)
355             .setIdRequirement(10203)
356             .build();
357 
358     com.google.crypto.tink.proto.JwtHmacKey protoKey =
359         com.google.crypto.tink.proto.JwtHmacKey.newBuilder()
360             .setVersion(0)
361             .setAlgorithm(JwtHmacAlgorithm.HS384)
362             .setKeyValue(KEY_BYTES_42_AS_BYTE_STRING)
363             .build();
364     ProtoKeySerialization serialization =
365         ProtoKeySerialization.create(
366             "type.googleapis.com/google.crypto.tink.JwtHmacKey",
367             protoKey.toByteString(),
368             KeyMaterialType.SYMMETRIC,
369             OutputPrefixType.TINK,
370             /* idRequirement= */ 10203);
371 
372     ProtoKeySerialization serialized =
373         registry.serializeKey(key, ProtoKeySerialization.class, InsecureSecretKeyAccess.get());
374     assertEqualWhenValueParsed(
375         com.google.crypto.tink.proto.JwtHmacKey.parser(), serialized, serialization);
376 
377     Key parsed = registry.parseKey(serialization, InsecureSecretKeyAccess.get());
378     assertThat(parsed.equalsKey(key)).isTrue();
379   }
380 
381   // INVALID KEYS SERIALIZATIONS ======================================= INVALID KEYS SERIALIZATIONS
382   @Test
serializeKey_wrongVersion_throws()383   public void serializeKey_wrongVersion_throws() throws Exception {
384     com.google.crypto.tink.proto.JwtHmacKey protoKey =
385         com.google.crypto.tink.proto.JwtHmacKey.newBuilder()
386             .setVersion(1)
387             .setAlgorithm(JwtHmacAlgorithm.HS384)
388             .setKeyValue(KEY_BYTES_42_AS_BYTE_STRING)
389             .build();
390     ProtoKeySerialization serialization =
391         ProtoKeySerialization.create(
392             "type.googleapis.com/google.crypto.tink.JwtHmacKey",
393             protoKey.toByteString(),
394             KeyMaterialType.SYMMETRIC,
395             OutputPrefixType.TINK,
396             /* idRequirement= */ 10203);
397 
398     assertThrows(
399         GeneralSecurityException.class,
400         () -> registry.parseKey(serialization, InsecureSecretKeyAccess.get()));
401   }
402 
403   @Test
serializeKey_unknownAlgorithm_throws()404   public void serializeKey_unknownAlgorithm_throws() throws Exception {
405     com.google.crypto.tink.proto.JwtHmacKey protoKey =
406         com.google.crypto.tink.proto.JwtHmacKey.newBuilder()
407             .setVersion(0)
408             .setAlgorithm(JwtHmacAlgorithm.HS_UNKNOWN)
409             .setKeyValue(KEY_BYTES_42_AS_BYTE_STRING)
410             .build();
411     ProtoKeySerialization serialization =
412         ProtoKeySerialization.create(
413             "type.googleapis.com/google.crypto.tink.JwtHmacKey",
414             protoKey.toByteString(),
415             KeyMaterialType.SYMMETRIC,
416             OutputPrefixType.TINK,
417             /* idRequirement= */ 10203);
418 
419     assertThrows(
420         GeneralSecurityException.class,
421         () -> registry.parseKey(serialization, InsecureSecretKeyAccess.get()));
422   }
423 
424   @Test
serializeKey_tinkKeyWithCustomSet_throws()425   public void serializeKey_tinkKeyWithCustomSet_throws() throws Exception {
426     com.google.crypto.tink.proto.JwtHmacKey protoKey =
427         com.google.crypto.tink.proto.JwtHmacKey.newBuilder()
428             .setVersion(0)
429             .setAlgorithm(JwtHmacAlgorithm.HS256)
430             .setKeyValue(KEY_BYTES_42_AS_BYTE_STRING)
431             .setCustomKid(CustomKid.newBuilder().setValue("customKidForThisTest"))
432             .build();
433     ProtoKeySerialization serialization =
434         ProtoKeySerialization.create(
435             "type.googleapis.com/google.crypto.tink.JwtHmacKey",
436             protoKey.toByteString(),
437             KeyMaterialType.SYMMETRIC,
438             OutputPrefixType.TINK,
439             /* idRequirement= */ 10203);
440 
441     assertThrows(
442         GeneralSecurityException.class,
443         () -> registry.parseKey(serialization, InsecureSecretKeyAccess.get()));
444   }
445 }
446