• 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 JwtRsaSsaPkcs1PublicKeyTest {
33 
34   // Test vector from https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.2
35   static final BigInteger MODULUS =
36       new BigInteger(
37           1,
38           Base64.urlSafeDecode(
39               "ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx"
40                   + "HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs"
41                   + "D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH"
42                   + "SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV"
43                   + "MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8"
44                   + "NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ"));
45 
46   @Test
build_kidStrategyIgnored_hasExpectedValues()47   public void build_kidStrategyIgnored_hasExpectedValues() throws Exception {
48     JwtRsaSsaPkcs1Parameters parameters =
49         JwtRsaSsaPkcs1Parameters.builder()
50             .setModulusSizeBits(2048)
51             .setPublicExponent(JwtRsaSsaPkcs1Parameters.F4)
52             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.IGNORED)
53             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
54             .build();
55     JwtRsaSsaPkcs1PublicKey key =
56         JwtRsaSsaPkcs1PublicKey.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     JwtRsaSsaPkcs1Parameters parameters =
66         JwtRsaSsaPkcs1Parameters.builder()
67             .setModulusSizeBits(2048)
68             .setPublicExponent(JwtRsaSsaPkcs1Parameters.F4)
69             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.IGNORED)
70             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
71             .build();
72     JwtRsaSsaPkcs1PublicKey.Builder builder =
73         JwtRsaSsaPkcs1PublicKey.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     JwtRsaSsaPkcs1Parameters parameters =
83         JwtRsaSsaPkcs1Parameters.builder()
84             .setModulusSizeBits(2048)
85             .setPublicExponent(JwtRsaSsaPkcs1Parameters.F4)
86             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.IGNORED)
87             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
88             .build();
89     JwtRsaSsaPkcs1PublicKey.Builder builder =
90         JwtRsaSsaPkcs1PublicKey.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     JwtRsaSsaPkcs1Parameters parameters =
100         JwtRsaSsaPkcs1Parameters.builder()
101             .setModulusSizeBits(2048)
102             .setPublicExponent(JwtRsaSsaPkcs1Parameters.F4)
103             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.CUSTOM)
104             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
105             .build();
106     JwtRsaSsaPkcs1PublicKey key =
107         JwtRsaSsaPkcs1PublicKey.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     JwtRsaSsaPkcs1Parameters parameters =
121         JwtRsaSsaPkcs1Parameters.builder()
122             .setModulusSizeBits(2048)
123             .setPublicExponent(JwtRsaSsaPkcs1Parameters.F4)
124             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.CUSTOM)
125             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
126             .build();
127     JwtRsaSsaPkcs1PublicKey.Builder builder =
128         JwtRsaSsaPkcs1PublicKey.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     JwtRsaSsaPkcs1Parameters parameters =
139         JwtRsaSsaPkcs1Parameters.builder()
140             .setModulusSizeBits(2048)
141             .setPublicExponent(JwtRsaSsaPkcs1Parameters.F4)
142             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.CUSTOM)
143             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
144             .build();
145     JwtRsaSsaPkcs1PublicKey.Builder builder =
146         JwtRsaSsaPkcs1PublicKey.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     JwtRsaSsaPkcs1Parameters parameters =
153         JwtRsaSsaPkcs1Parameters.builder()
154             .setModulusSizeBits(2048)
155             .setPublicExponent(JwtRsaSsaPkcs1Parameters.F4)
156             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.BASE64_ENCODED_KEY_ID)
157             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
158             .build();
159     JwtRsaSsaPkcs1PublicKey key =
160         JwtRsaSsaPkcs1PublicKey.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     JwtRsaSsaPkcs1Parameters parameters =
174         JwtRsaSsaPkcs1Parameters.builder()
175             .setModulusSizeBits(2048)
176             .setPublicExponent(JwtRsaSsaPkcs1Parameters.F4)
177             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.BASE64_ENCODED_KEY_ID)
178             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
179             .build();
180     JwtRsaSsaPkcs1PublicKey.Builder builder =
181         JwtRsaSsaPkcs1PublicKey.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     JwtRsaSsaPkcs1Parameters parameters =
188         JwtRsaSsaPkcs1Parameters.builder()
189             .setModulusSizeBits(2048)
190             .setPublicExponent(JwtRsaSsaPkcs1Parameters.F4)
191             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.BASE64_ENCODED_KEY_ID)
192             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
193             .build();
194     JwtRsaSsaPkcs1PublicKey.Builder builder =
195         JwtRsaSsaPkcs1PublicKey.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, () -> JwtRsaSsaPkcs1PublicKey.builder().build());
206   }
207 
208   @Test
buildWithoutParameters_fails()209   public void buildWithoutParameters_fails() throws Exception {
210     assertThrows(
211         GeneralSecurityException.class,
212         () -> JwtRsaSsaPkcs1PublicKey.builder().setModulus(MODULUS).build());
213   }
214 
215   @Test
build_withoutModulus_fails()216   public void build_withoutModulus_fails() throws Exception {
217     JwtRsaSsaPkcs1Parameters parameters =
218         JwtRsaSsaPkcs1Parameters.builder()
219             .setModulusSizeBits(2048)
220             .setPublicExponent(JwtRsaSsaPkcs1Parameters.F4)
221             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.IGNORED)
222             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
223             .build();
224     assertThrows(
225         GeneralSecurityException.class,
226         () -> JwtRsaSsaPkcs1PublicKey.builder().setParameters(parameters).build());
227   }
228 
229   @Test
build_invalidModulusSize_fails()230   public void build_invalidModulusSize_fails() throws Exception {
231     JwtRsaSsaPkcs1Parameters parameters =
232         JwtRsaSsaPkcs1Parameters.builder()
233             .setModulusSizeBits(3456)
234             .setPublicExponent(JwtRsaSsaPkcs1Parameters.F4)
235             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.IGNORED)
236             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
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             JwtRsaSsaPkcs1PublicKey.builder()
247                 .setParameters(parameters)
248                 .setModulus(tooSmall)
249                 .build());
250     assertThrows(
251         GeneralSecurityException.class,
252         () ->
253             JwtRsaSsaPkcs1PublicKey.builder().setParameters(parameters).setModulus(tooBig).build());
254   }
255 
256   @Test
testEqualities()257   public void testEqualities() throws Exception {
258     JwtRsaSsaPkcs1Parameters kidStrategyIgnoredParameters =
259         JwtRsaSsaPkcs1Parameters.builder()
260             .setModulusSizeBits(2048)
261             .setPublicExponent(JwtRsaSsaPkcs1Parameters.F4)
262             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.IGNORED)
263             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
264             .build();
265     JwtRsaSsaPkcs1Parameters kidStrategyIgnoredParametersCopy =
266         JwtRsaSsaPkcs1Parameters.builder()
267             .setModulusSizeBits(2048)
268             .setPublicExponent(JwtRsaSsaPkcs1Parameters.F4)
269             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.IGNORED)
270             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
271             .build();
272 
273     JwtRsaSsaPkcs1Parameters kidStrategyCustomParameters =
274         JwtRsaSsaPkcs1Parameters.builder()
275             .setModulusSizeBits(2048)
276             .setPublicExponent(JwtRsaSsaPkcs1Parameters.F4)
277             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.CUSTOM)
278             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
279             .build();
280 
281     JwtRsaSsaPkcs1Parameters kidStrategyBase64Parameters =
282         JwtRsaSsaPkcs1Parameters.builder()
283             .setModulusSizeBits(2048)
284             .setPublicExponent(JwtRsaSsaPkcs1Parameters.F4)
285             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.BASE64_ENCODED_KEY_ID)
286             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
287             .build();
288 
289     new KeyTester()
290         .addEqualityGroup(
291             "KID Ignored, R256",
292             JwtRsaSsaPkcs1PublicKey.builder()
293                 .setParameters(kidStrategyIgnoredParameters)
294                 .setModulus(MODULUS)
295                 .build(),
296             // the same key built twice must be equal
297             JwtRsaSsaPkcs1PublicKey.builder()
298                 .setParameters(kidStrategyIgnoredParameters)
299                 .setModulus(MODULUS)
300                 .build(),
301             // the same key built with a copy of parameters must be equal
302             JwtRsaSsaPkcs1PublicKey.builder()
303                 .setParameters(kidStrategyIgnoredParametersCopy)
304                 .setModulus(MODULUS)
305                 .build())
306         // This group checks that keys with different key bytes are not equal
307         .addEqualityGroup(
308             "KID Ignored, different modulus",
309             JwtRsaSsaPkcs1PublicKey.builder()
310                 .setParameters(kidStrategyIgnoredParameters)
311                 .setModulus(MODULUS.add(BigInteger.ONE))
312                 .build())
313         // These groups checks that keys with different customKid are not equal
314         .addEqualityGroup(
315             "KID Custom, customKid1",
316             JwtRsaSsaPkcs1PublicKey.builder()
317                 .setParameters(kidStrategyCustomParameters)
318                 .setModulus(MODULUS)
319                 .setCustomKid("customKid1")
320                 .build())
321         .addEqualityGroup(
322             "KID Custom, customKid2",
323             JwtRsaSsaPkcs1PublicKey.builder()
324                 .setParameters(kidStrategyCustomParameters)
325                 .setModulus(MODULUS)
326                 .setCustomKid("customKid2")
327                 .build())
328         // These groups checks that keys with different ID Requirements are not equal
329         .addEqualityGroup(
330             "Tink with key id 1907",
331             JwtRsaSsaPkcs1PublicKey.builder()
332                 .setParameters(kidStrategyBase64Parameters)
333                 .setModulus(MODULUS)
334                 .setIdRequirement(1907)
335                 .build())
336         .addEqualityGroup(
337             "Tink with key id 1908",
338             JwtRsaSsaPkcs1PublicKey.builder()
339                 .setParameters(kidStrategyBase64Parameters)
340                 .setModulus(MODULUS)
341                 .setIdRequirement(1908)
342                 .build())
343         .doTests();
344   }
345 }
346