• 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 org.junit.Assert.assertThrows;
21 
22 import com.google.crypto.tink.internal.KeyTester;
23 import com.google.crypto.tink.subtle.Base64;
24 import java.math.BigInteger;
25 import java.security.GeneralSecurityException;
26 import java.util.Optional;
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
29 import org.junit.runners.JUnit4;
30 
31 @RunWith(JUnit4.class)
32 public final class JwtRsaSsaPssPublicKeyTest {
33 
34   // Test vector from https://www.rfc-editor.org/rfc/rfc7517#appendix-C.1
35   static final BigInteger MODULUS =
36       new BigInteger(
37           1,
38           Base64.urlSafeDecode(
39               "t6Q8PWSi1dkJj9hTP8hNYFlvadM7DflW9mWepOJhJ66w7nyoK1gPNqFMSQRy"
40                   + "O125Gp-TEkodhWr0iujjHVx7BcV0llS4w5ACGgPrcAd6ZcSR0-Iqom-QFcNP"
41                   + "8Sjg086MwoqQU_LYywlAGZ21WSdS_PERyGFiNnj3QQlO8Yns5jCtLCRwLHL0"
42                   + "Pb1fEv45AuRIuUfVcPySBWYnDyGxvjYGDSM-AqWS9zIQ2ZilgT-GqUmipg0X"
43                   + "OC0Cc20rgLe2ymLHjpHciCKVAbY5-L32-lSeZO-Os6U15_aXrk9Gw8cPUaX1"
44                   + "_I8sLGuSiVdt3C_Fn2PZ3Z8i744FPFGGcG1qs2Wz-Q"));
45 
46   @Test
build_kidStrategyIgnored_hasExpectedValues()47   public void build_kidStrategyIgnored_hasExpectedValues() throws Exception {
48     JwtRsaSsaPssParameters parameters =
49         JwtRsaSsaPssParameters.builder()
50             .setModulusSizeBits(2048)
51             .setPublicExponent(JwtRsaSsaPssParameters.F4)
52             .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.IGNORED)
53             .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256)
54             .build();
55     JwtRsaSsaPssPublicKey key =
56         JwtRsaSsaPssPublicKey.builder().setParameters(parameters).setModulus(MODULUS).build();
57     assertThat(key.getParameters()).isEqualTo(parameters);
58     assertThat(key.getModulus()).isEqualTo(MODULUS);
59     assertThat(key.getKid()).isEqualTo(Optional.empty());
60     assertThat(key.getIdRequirementOrNull()).isNull();
61   }
62 
63   @Test
build_kidStrategyIgnored_setCustomKid_fails()64   public void build_kidStrategyIgnored_setCustomKid_fails() throws Exception {
65     JwtRsaSsaPssParameters parameters =
66         JwtRsaSsaPssParameters.builder()
67             .setModulusSizeBits(2048)
68             .setPublicExponent(JwtRsaSsaPssParameters.F4)
69             .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.IGNORED)
70             .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256)
71             .build();
72     JwtRsaSsaPssPublicKey.Builder builder =
73         JwtRsaSsaPssPublicKey.builder()
74             .setParameters(parameters)
75             .setModulus(MODULUS)
76             .setCustomKid("customKid23");
77     assertThrows(GeneralSecurityException.class, builder::build);
78   }
79 
80   @Test
build_kidStrategyIgnored_setIdRequirement_fails()81   public void build_kidStrategyIgnored_setIdRequirement_fails() throws Exception {
82     JwtRsaSsaPssParameters parameters =
83         JwtRsaSsaPssParameters.builder()
84             .setModulusSizeBits(2048)
85             .setPublicExponent(JwtRsaSsaPssParameters.F4)
86             .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.IGNORED)
87             .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256)
88             .build();
89     JwtRsaSsaPssPublicKey.Builder builder =
90         JwtRsaSsaPssPublicKey.builder()
91             .setParameters(parameters)
92             .setIdRequirement(123)
93             .setModulus(MODULUS);
94     assertThrows(GeneralSecurityException.class, builder::build);
95   }
96 
97   @Test
build_kidStrategyCustom_hasExpectedValues()98   public void build_kidStrategyCustom_hasExpectedValues() throws Exception {
99     JwtRsaSsaPssParameters parameters =
100         JwtRsaSsaPssParameters.builder()
101             .setModulusSizeBits(2048)
102             .setPublicExponent(JwtRsaSsaPssParameters.F4)
103             .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.CUSTOM)
104             .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256)
105             .build();
106     JwtRsaSsaPssPublicKey key =
107         JwtRsaSsaPssPublicKey.builder()
108             .setParameters(parameters)
109             .setModulus(MODULUS)
110             .setCustomKid("customKid777")
111             .build();
112     assertThat(key.getParameters()).isEqualTo(parameters);
113     assertThat(key.getModulus()).isEqualTo(MODULUS);
114     assertThat(key.getKid().get()).isEqualTo("customKid777");
115     assertThat(key.getIdRequirementOrNull()).isNull();
116   }
117 
118   @Test
build_kidStrategyCustom_setIdRequirement_fails()119   public void build_kidStrategyCustom_setIdRequirement_fails() throws Exception {
120     JwtRsaSsaPssParameters parameters =
121         JwtRsaSsaPssParameters.builder()
122             .setModulusSizeBits(2048)
123             .setPublicExponent(JwtRsaSsaPssParameters.F4)
124             .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.CUSTOM)
125             .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256)
126             .build();
127     JwtRsaSsaPssPublicKey.Builder builder =
128         JwtRsaSsaPssPublicKey.builder()
129             .setParameters(parameters)
130             .setIdRequirement(123)
131             .setCustomKid("customKid777")
132             .setModulus(MODULUS);
133     assertThrows(GeneralSecurityException.class, builder::build);
134   }
135 
136   @Test
buildKidStrategyCustom_missingCustomKid_fails()137   public void buildKidStrategyCustom_missingCustomKid_fails() throws Exception {
138     JwtRsaSsaPssParameters parameters =
139         JwtRsaSsaPssParameters.builder()
140             .setModulusSizeBits(2048)
141             .setPublicExponent(JwtRsaSsaPssParameters.F4)
142             .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.CUSTOM)
143             .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256)
144             .build();
145     JwtRsaSsaPssPublicKey.Builder builder =
146         JwtRsaSsaPssPublicKey.builder().setParameters(parameters).setModulus(MODULUS);
147     assertThrows(GeneralSecurityException.class, builder::build);
148   }
149 
150   @Test
build_kidStrategyBase64_getProperties_succeeds()151   public void build_kidStrategyBase64_getProperties_succeeds() throws Exception {
152     JwtRsaSsaPssParameters parameters =
153         JwtRsaSsaPssParameters.builder()
154             .setModulusSizeBits(2048)
155             .setPublicExponent(JwtRsaSsaPssParameters.F4)
156             .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.BASE64_ENCODED_KEY_ID)
157             .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256)
158             .build();
159     JwtRsaSsaPssPublicKey key =
160         JwtRsaSsaPssPublicKey.builder()
161             .setParameters(parameters)
162             .setModulus(MODULUS)
163             .setIdRequirement(0x1ac6a944)
164             .build();
165     assertThat(key.getParameters()).isEqualTo(parameters);
166     assertThat(key.getIdRequirementOrNull()).isEqualTo(0x1ac6a944);
167     // See JwtFormatTest.getKidFromTinkOutputPrefixType_success
168     assertThat(key.getKid()).isEqualTo(Optional.of("GsapRA"));
169   }
170 
171   @Test
build_kidStrategyBase64_noIdRequirement_throws()172   public void build_kidStrategyBase64_noIdRequirement_throws() throws Exception {
173     JwtRsaSsaPssParameters parameters =
174         JwtRsaSsaPssParameters.builder()
175             .setModulusSizeBits(2048)
176             .setPublicExponent(JwtRsaSsaPssParameters.F4)
177             .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.BASE64_ENCODED_KEY_ID)
178             .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256)
179             .build();
180     JwtRsaSsaPssPublicKey.Builder builder =
181         JwtRsaSsaPssPublicKey.builder().setParameters(parameters).setModulus(MODULUS);
182     assertThrows(GeneralSecurityException.class, builder::build);
183   }
184 
185   @Test
build_kidStrategyBase64_setCustomKid_throws()186   public void build_kidStrategyBase64_setCustomKid_throws() throws Exception {
187     JwtRsaSsaPssParameters parameters =
188         JwtRsaSsaPssParameters.builder()
189             .setModulusSizeBits(2048)
190             .setPublicExponent(JwtRsaSsaPssParameters.F4)
191             .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.BASE64_ENCODED_KEY_ID)
192             .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256)
193             .build();
194     JwtRsaSsaPssPublicKey.Builder builder =
195         JwtRsaSsaPssPublicKey.builder()
196             .setParameters(parameters)
197             .setIdRequirement(0x89abcdef)
198             .setCustomKid("customKid")
199             .setModulus(MODULUS);
200     assertThrows(GeneralSecurityException.class, builder::build);
201   }
202 
203   @Test
emptyBuild_fails()204   public void emptyBuild_fails() throws Exception {
205     assertThrows(GeneralSecurityException.class, () -> JwtRsaSsaPssPublicKey.builder().build());
206   }
207 
208   @Test
buildWithoutParameters_fails()209   public void buildWithoutParameters_fails() throws Exception {
210     assertThrows(
211         GeneralSecurityException.class,
212         () -> JwtRsaSsaPssPublicKey.builder().setModulus(MODULUS).build());
213   }
214 
215   @Test
build_withoutModulus_fails()216   public void build_withoutModulus_fails() throws Exception {
217     JwtRsaSsaPssParameters parameters =
218         JwtRsaSsaPssParameters.builder()
219             .setModulusSizeBits(2048)
220             .setPublicExponent(JwtRsaSsaPssParameters.F4)
221             .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.IGNORED)
222             .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256)
223             .build();
224     assertThrows(
225         GeneralSecurityException.class,
226         () -> JwtRsaSsaPssPublicKey.builder().setParameters(parameters).build());
227   }
228 
229   @Test
build_invalidModulusSize_fails()230   public void build_invalidModulusSize_fails() throws Exception {
231     JwtRsaSsaPssParameters parameters =
232         JwtRsaSsaPssParameters.builder()
233             .setModulusSizeBits(3456)
234             .setPublicExponent(JwtRsaSsaPssParameters.F4)
235             .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.IGNORED)
236             .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256)
237             .build();
238 
239     // Modulus between 2^3455 and 2^3456 are valid.
240     BigInteger tooSmall = BigInteger.valueOf(2).pow(3455).subtract(BigInteger.ONE);
241     BigInteger tooBig = BigInteger.valueOf(2).pow(3456).add(BigInteger.ONE);
242 
243     assertThrows(
244         GeneralSecurityException.class,
245         () ->
246             JwtRsaSsaPssPublicKey.builder().setParameters(parameters).setModulus(tooSmall).build());
247     assertThrows(
248         GeneralSecurityException.class,
249         () -> JwtRsaSsaPssPublicKey.builder().setParameters(parameters).setModulus(tooBig).build());
250   }
251 
252   @Test
testEqualities()253   public void testEqualities() throws Exception {
254     JwtRsaSsaPssParameters kidStrategyIgnoredParameters =
255         JwtRsaSsaPssParameters.builder()
256             .setModulusSizeBits(2048)
257             .setPublicExponent(JwtRsaSsaPssParameters.F4)
258             .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.IGNORED)
259             .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256)
260             .build();
261     JwtRsaSsaPssParameters kidStrategyIgnoredParametersCopy =
262         JwtRsaSsaPssParameters.builder()
263             .setModulusSizeBits(2048)
264             .setPublicExponent(JwtRsaSsaPssParameters.F4)
265             .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.IGNORED)
266             .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256)
267             .build();
268 
269     JwtRsaSsaPssParameters kidStrategyCustomParameters =
270         JwtRsaSsaPssParameters.builder()
271             .setModulusSizeBits(2048)
272             .setPublicExponent(JwtRsaSsaPssParameters.F4)
273             .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.CUSTOM)
274             .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256)
275             .build();
276 
277     JwtRsaSsaPssParameters kidStrategyBase64Parameters =
278         JwtRsaSsaPssParameters.builder()
279             .setModulusSizeBits(2048)
280             .setPublicExponent(JwtRsaSsaPssParameters.F4)
281             .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.BASE64_ENCODED_KEY_ID)
282             .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256)
283             .build();
284 
285     new KeyTester()
286         .addEqualityGroup(
287             "KID Ignored, R256",
288             JwtRsaSsaPssPublicKey.builder()
289                 .setParameters(kidStrategyIgnoredParameters)
290                 .setModulus(MODULUS)
291                 .build(),
292             // the same key built twice must be equal
293             JwtRsaSsaPssPublicKey.builder()
294                 .setParameters(kidStrategyIgnoredParameters)
295                 .setModulus(MODULUS)
296                 .build(),
297             // the same key built with a copy of parameters must be equal
298             JwtRsaSsaPssPublicKey.builder()
299                 .setParameters(kidStrategyIgnoredParametersCopy)
300                 .setModulus(MODULUS)
301                 .build())
302         // This group checks that keys with different key bytes are not equal
303         .addEqualityGroup(
304             "KID Ignored, different modulus",
305             JwtRsaSsaPssPublicKey.builder()
306                 .setParameters(kidStrategyIgnoredParameters)
307                 .setModulus(MODULUS.add(BigInteger.ONE))
308                 .build())
309         // These groups checks that keys with different customKid are not equal
310         .addEqualityGroup(
311             "KID Custom, customKid1",
312             JwtRsaSsaPssPublicKey.builder()
313                 .setParameters(kidStrategyCustomParameters)
314                 .setModulus(MODULUS)
315                 .setCustomKid("customKid1")
316                 .build())
317         .addEqualityGroup(
318             "KID Custom, customKid2",
319             JwtRsaSsaPssPublicKey.builder()
320                 .setParameters(kidStrategyCustomParameters)
321                 .setModulus(MODULUS)
322                 .setCustomKid("customKid2")
323                 .build())
324         // These groups checks that keys with different ID Requirements are not equal
325         .addEqualityGroup(
326             "Tink with key id 1907",
327             JwtRsaSsaPssPublicKey.builder()
328                 .setParameters(kidStrategyBase64Parameters)
329                 .setModulus(MODULUS)
330                 .setIdRequirement(1907)
331                 .build())
332         .addEqualityGroup(
333             "Tink with key id 1908",
334             JwtRsaSsaPssPublicKey.builder()
335                 .setParameters(kidStrategyBase64Parameters)
336                 .setModulus(MODULUS)
337                 .setIdRequirement(1908)
338                 .build())
339         .doTests();
340   }
341 }
342