• 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.InsecureSecretKeyAccess;
23 import com.google.crypto.tink.aead.ChaCha20Poly1305Key;
24 import com.google.crypto.tink.internal.KeyTester;
25 import com.google.crypto.tink.subtle.Base64;
26 import com.google.crypto.tink.util.SecretBigInteger;
27 import com.google.crypto.tink.util.SecretBytes;
28 import java.math.BigInteger;
29 import java.security.GeneralSecurityException;
30 import java.util.Optional;
31 import org.junit.Test;
32 import org.junit.runner.RunWith;
33 import org.junit.runners.JUnit4;
34 
35 @RunWith(JUnit4.class)
36 public final class JwtRsaSsaPkcs1PrivateKeyTest {
37 
38   // Test vector from https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.2
39   static final BigInteger EXPONENT = new BigInteger(1, Base64.urlSafeDecode("AQAB"));
40   static final BigInteger MODULUS =
41       new BigInteger(
42           1,
43           Base64.urlSafeDecode(
44               "ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx"
45                   + "HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs"
46                   + "D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH"
47                   + "SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV"
48                   + "MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8"
49                   + "NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ"));
50   static final BigInteger P =
51       new BigInteger(
52           1,
53           Base64.urlSafeDecode(
54               "4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdi"
55                   + "YrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPG"
56                   + "BY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc"));
57   static final BigInteger Q =
58       new BigInteger(
59           1,
60           Base64.urlSafeDecode(
61               "uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxa"
62                   + "ewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA"
63                   + "-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc"));
64   static final BigInteger D =
65       new BigInteger(
66           1,
67           Base64.urlSafeDecode(
68               "Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97I"
69                   + "jlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0"
70                   + "BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn"
71                   + "439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYT"
72                   + "CBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLh"
73                   + "BOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ"));
74   static final BigInteger DP =
75       new BigInteger(
76           1,
77           Base64.urlSafeDecode(
78               "BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3Q"
79                   + "CLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb"
80                   + "34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0"));
81   static final BigInteger DQ =
82       new BigInteger(
83           1,
84           Base64.urlSafeDecode(
85               "h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa"
86                   + "7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-ky"
87                   + "NlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU"));
88   static final BigInteger Q_INV =
89       new BigInteger(
90           1,
91           Base64.urlSafeDecode(
92               "IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2o"
93                   + "y26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLU"
94                   + "W0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U"));
95 
96   @Test
build_kidStrategyIgnored_hasExpectedValues()97   public void build_kidStrategyIgnored_hasExpectedValues() throws Exception {
98     JwtRsaSsaPkcs1Parameters parameters =
99         JwtRsaSsaPkcs1Parameters.builder()
100             .setModulusSizeBits(2048)
101             .setPublicExponent(JwtRsaSsaPkcs1Parameters.F4)
102             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.IGNORED)
103             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
104             .build();
105     JwtRsaSsaPkcs1PublicKey publicKey =
106         JwtRsaSsaPkcs1PublicKey.builder().setParameters(parameters).setModulus(MODULUS).build();
107     JwtRsaSsaPkcs1PrivateKey privateKey =
108         JwtRsaSsaPkcs1PrivateKey.builder()
109             .setPublicKey(publicKey)
110             .setPrimes(
111                 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()),
112                 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()))
113             .setPrivateExponent(SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get()))
114             .setPrimeExponents(
115                 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()),
116                 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()))
117             .setCrtCoefficient(
118                 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get()))
119             .build();
120     assertThat(privateKey.getParameters()).isEqualTo(parameters);
121     assertThat(privateKey.getPublicKey()).isEqualTo(publicKey);
122     assertThat(privateKey.getPrimeP().getBigInteger(InsecureSecretKeyAccess.get())).isEqualTo(P);
123     assertThat(privateKey.getPrimeQ().getBigInteger(InsecureSecretKeyAccess.get())).isEqualTo(Q);
124     assertThat(privateKey.getPrimeExponentP().getBigInteger(InsecureSecretKeyAccess.get()))
125         .isEqualTo(DP);
126     assertThat(privateKey.getPrimeExponentQ().getBigInteger(InsecureSecretKeyAccess.get()))
127         .isEqualTo(DQ);
128     assertThat(privateKey.getCrtCoefficient().getBigInteger(InsecureSecretKeyAccess.get()))
129         .isEqualTo(Q_INV);
130     assertThat(privateKey.getPrivateExponent().getBigInteger(InsecureSecretKeyAccess.get()))
131         .isEqualTo(D);
132 
133     assertThat(privateKey.getKid()).isEqualTo(Optional.empty());
134     assertThat(privateKey.getIdRequirementOrNull()).isNull();
135   }
136 
137   @Test
build_kidStrategyCustom_hasExpectedValues()138   public void build_kidStrategyCustom_hasExpectedValues() throws Exception {
139     JwtRsaSsaPkcs1Parameters parameters =
140         JwtRsaSsaPkcs1Parameters.builder()
141             .setModulusSizeBits(2048)
142             .setPublicExponent(JwtRsaSsaPkcs1Parameters.F4)
143             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.CUSTOM)
144             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
145             .build();
146     JwtRsaSsaPkcs1PublicKey publicKey =
147         JwtRsaSsaPkcs1PublicKey.builder()
148             .setParameters(parameters)
149             .setModulus(MODULUS)
150             .setCustomKid("customKid777")
151             .build();
152     JwtRsaSsaPkcs1PrivateKey privateKey =
153         JwtRsaSsaPkcs1PrivateKey.builder()
154             .setPublicKey(publicKey)
155             .setPrimes(
156                 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()),
157                 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()))
158             .setPrivateExponent(SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get()))
159             .setPrimeExponents(
160                 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()),
161                 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()))
162             .setCrtCoefficient(
163                 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get()))
164             .build();
165     assertThat(privateKey.getParameters()).isEqualTo(parameters);
166     assertThat(privateKey.getPublicKey()).isEqualTo(publicKey);
167 
168     assertThat(privateKey.getKid().get()).isEqualTo("customKid777");
169     assertThat(privateKey.getIdRequirementOrNull()).isNull();
170   }
171 
172   @Test
build_kidStrategyBase64_hasExpectedValues()173   public void build_kidStrategyBase64_hasExpectedValues() throws Exception {
174     JwtRsaSsaPkcs1Parameters parameters =
175         JwtRsaSsaPkcs1Parameters.builder()
176             .setModulusSizeBits(2048)
177             .setPublicExponent(JwtRsaSsaPkcs1Parameters.F4)
178             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.BASE64_ENCODED_KEY_ID)
179             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
180             .build();
181     JwtRsaSsaPkcs1PublicKey publicKey =
182         JwtRsaSsaPkcs1PublicKey.builder()
183             .setParameters(parameters)
184             .setModulus(MODULUS)
185             .setIdRequirement(0x1ac6a944)
186             .build();
187     JwtRsaSsaPkcs1PrivateKey privateKey =
188         JwtRsaSsaPkcs1PrivateKey.builder()
189             .setPublicKey(publicKey)
190             .setPrimes(
191                 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()),
192                 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()))
193             .setPrivateExponent(SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get()))
194             .setPrimeExponents(
195                 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()),
196                 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()))
197             .setCrtCoefficient(
198                 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get()))
199             .build();
200     assertThat(privateKey.getParameters()).isEqualTo(parameters);
201     assertThat(privateKey.getPublicKey()).isEqualTo(publicKey);
202 
203     assertThat(privateKey.getKid().get()).isEqualTo("GsapRA");
204     assertThat(privateKey.getIdRequirementOrNull()).isEqualTo(0x1ac6a944);
205   }
206 
207   @Test
notAllValuesSet_throws()208   public void notAllValuesSet_throws() throws Exception {
209     JwtRsaSsaPkcs1Parameters parameters =
210         JwtRsaSsaPkcs1Parameters.builder()
211             .setModulusSizeBits(2048)
212             .setPublicExponent(EXPONENT)
213             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.IGNORED)
214             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
215             .build();
216     JwtRsaSsaPkcs1PublicKey publicKey =
217         JwtRsaSsaPkcs1PublicKey.builder().setParameters(parameters).setModulus(MODULUS).build();
218 
219     // no public key
220     assertThrows(
221         GeneralSecurityException.class,
222         () ->
223             JwtRsaSsaPkcs1PrivateKey.builder()
224                 .setPrimes(
225                     SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()),
226                     SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()))
227                 .setPrivateExponent(
228                     SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get()))
229                 .setPrimeExponents(
230                     SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()),
231                     SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()))
232                 .setCrtCoefficient(
233                     SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get()))
234                 .build());
235 
236     // no prime factors
237     assertThrows(
238         GeneralSecurityException.class,
239         () ->
240             JwtRsaSsaPkcs1PrivateKey.builder()
241                 .setPublicKey(publicKey)
242                 .setPrivateExponent(
243                     SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get()))
244                 .setPrimeExponents(
245                     SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()),
246                     SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()))
247                 .setCrtCoefficient(
248                     SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get()))
249                 .build());
250 
251     // no private exponent
252     assertThrows(
253         GeneralSecurityException.class,
254         () ->
255             JwtRsaSsaPkcs1PrivateKey.builder()
256                 .setPublicKey(publicKey)
257                 .setPrimes(
258                     SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()),
259                     SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()))
260                 .setPrimeExponents(
261                     SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()),
262                     SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()))
263                 .setCrtCoefficient(
264                     SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get()))
265                 .build());
266 
267     // no factors crt exponents
268     assertThrows(
269         GeneralSecurityException.class,
270         () ->
271             JwtRsaSsaPkcs1PrivateKey.builder()
272                 .setPublicKey(publicKey)
273                 .setPrimes(
274                     SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()),
275                     SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()))
276                 .setPrivateExponent(
277                     SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get()))
278                 .setCrtCoefficient(
279                     SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get()))
280                 .build());
281 
282     // no crt coefficient
283     assertThrows(
284         GeneralSecurityException.class,
285         () ->
286             JwtRsaSsaPkcs1PrivateKey.builder()
287                 .setPublicKey(publicKey)
288                 .setPrimes(
289                     SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()),
290                     SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()))
291                 .setPrivateExponent(
292                     SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get()))
293                 .setPrimeExponents(
294                     SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()),
295                     SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()))
296                 .build());
297   }
298 
299   @Test
emptyBuild_fails()300   public void emptyBuild_fails() throws Exception {
301     assertThrows(GeneralSecurityException.class, () -> JwtRsaSsaPkcs1PrivateKey.builder().build());
302   }
303 
304   @Test
build_validatesValues()305   public void build_validatesValues() throws Exception {
306     JwtRsaSsaPkcs1Parameters parameters =
307         JwtRsaSsaPkcs1Parameters.builder()
308             .setModulusSizeBits(2048)
309             .setPublicExponent(EXPONENT)
310             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.IGNORED)
311             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
312             .build();
313     // Check that build fails if any value is increased by 1.
314     assertThrows(
315         GeneralSecurityException.class,
316         () ->
317             JwtRsaSsaPkcs1PrivateKey.builder()
318                 .setPublicKey(
319                     JwtRsaSsaPkcs1PublicKey.builder()
320                         .setParameters(parameters)
321                         .setModulus(MODULUS.add(BigInteger.ONE)) // modulus is one off
322                         .build())
323                 .setPrimes(
324                     SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()),
325                     SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()))
326                 .setPrimeExponents(
327                     SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()),
328                     SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()))
329                 .setCrtCoefficient(
330                     SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get()))
331                 .build());
332     assertThrows(
333         GeneralSecurityException.class,
334         () ->
335             JwtRsaSsaPkcs1PrivateKey.builder()
336                 .setPublicKey(
337                     JwtRsaSsaPkcs1PublicKey.builder()
338                         .setParameters(parameters)
339                         .setModulus(MODULUS)
340                         .build())
341                 .setPrimes(
342                     SecretBigInteger.fromBigInteger(
343                         P.add(BigInteger.ONE), InsecureSecretKeyAccess.get()),
344                     SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()))
345                 .setPrimeExponents(
346                     SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()),
347                     SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()))
348                 .setCrtCoefficient(
349                     SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get()))
350                 .build());
351     assertThrows(
352         GeneralSecurityException.class,
353         () ->
354             JwtRsaSsaPkcs1PrivateKey.builder()
355                 .setPublicKey(
356                     JwtRsaSsaPkcs1PublicKey.builder()
357                         .setParameters(parameters)
358                         .setModulus(MODULUS)
359                         .build())
360                 .setPrimes(
361                     SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()),
362                     SecretBigInteger.fromBigInteger(
363                         Q.add(BigInteger.ONE), InsecureSecretKeyAccess.get()))
364                 .setPrimeExponents(
365                     SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()),
366                     SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()))
367                 .setCrtCoefficient(
368                     SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get()))
369                 .build());
370     assertThrows(
371         GeneralSecurityException.class,
372         () ->
373             JwtRsaSsaPkcs1PrivateKey.builder()
374                 .setPublicKey(
375                     JwtRsaSsaPkcs1PublicKey.builder()
376                         .setParameters(parameters)
377                         .setModulus(MODULUS)
378                         .build())
379                 .setPrimes(
380                     SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()),
381                     SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()))
382                 .setPrimeExponents(
383                     SecretBigInteger.fromBigInteger(
384                         DP.add(BigInteger.ONE), InsecureSecretKeyAccess.get()),
385                     SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()))
386                 .setCrtCoefficient(
387                     SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get()))
388                 .build());
389     assertThrows(
390         GeneralSecurityException.class,
391         () ->
392             JwtRsaSsaPkcs1PrivateKey.builder()
393                 .setPublicKey(
394                     JwtRsaSsaPkcs1PublicKey.builder()
395                         .setParameters(parameters)
396                         .setModulus(MODULUS)
397                         .build())
398                 .setPrimes(
399                     SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()),
400                     SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()))
401                 .setPrimeExponents(
402                     SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()),
403                     SecretBigInteger.fromBigInteger(
404                         DQ.add(BigInteger.ONE), InsecureSecretKeyAccess.get()))
405                 .setCrtCoefficient(
406                     SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get()))
407                 .build());
408     assertThrows(
409         GeneralSecurityException.class,
410         () ->
411             JwtRsaSsaPkcs1PrivateKey.builder()
412                 .setPublicKey(
413                     JwtRsaSsaPkcs1PublicKey.builder()
414                         .setParameters(parameters)
415                         .setModulus(MODULUS)
416                         .build())
417                 .setPrimes(
418                     SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()),
419                     SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()))
420                 .setPrimeExponents(
421                     SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()),
422                     SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()))
423                 .setCrtCoefficient(
424                     SecretBigInteger.fromBigInteger(
425                         Q_INV.add(BigInteger.ONE), InsecureSecretKeyAccess.get()))
426                 .build());
427   }
428 
429   @Test
testEqualities()430   public void testEqualities() throws Exception {
431     JwtRsaSsaPkcs1Parameters parameters =
432         JwtRsaSsaPkcs1Parameters.builder()
433             .setModulusSizeBits(2048)
434             .setPublicExponent(EXPONENT)
435             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.IGNORED)
436             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
437             .build();
438     JwtRsaSsaPkcs1PublicKey kidStrategyIgnoredPublicKey =
439         JwtRsaSsaPkcs1PublicKey.builder().setParameters(parameters).setModulus(MODULUS).build();
440 
441     JwtRsaSsaPkcs1PublicKey kidStrategyBase64PublicKey =
442         JwtRsaSsaPkcs1PublicKey.builder()
443             .setParameters(
444                 JwtRsaSsaPkcs1Parameters.builder()
445                     .setModulusSizeBits(2048)
446                     .setPublicExponent(EXPONENT)
447                     .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.BASE64_ENCODED_KEY_ID)
448                     .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
449                     .build())
450             .setModulus(MODULUS)
451             .setIdRequirement(1907)
452             .build();
453 
454     JwtRsaSsaPkcs1PublicKey kidStrategyIgnoredPublicKeyRS512 =
455         JwtRsaSsaPkcs1PublicKey.builder()
456             .setParameters(
457                 JwtRsaSsaPkcs1Parameters.builder()
458                     .setModulusSizeBits(2048)
459                     .setPublicExponent(EXPONENT)
460                     .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.IGNORED)
461                     .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS512)
462                     .build())
463             .setModulus(MODULUS)
464             .build();
465 
466     JwtRsaSsaPkcs1Parameters parametersCustomKid =
467         JwtRsaSsaPkcs1Parameters.builder()
468             .setModulusSizeBits(2048)
469             .setPublicExponent(EXPONENT)
470             .setKidStrategy(JwtRsaSsaPkcs1Parameters.KidStrategy.CUSTOM)
471             .setAlgorithm(JwtRsaSsaPkcs1Parameters.Algorithm.RS256)
472             .build();
473     JwtRsaSsaPkcs1PublicKey publicKeyCustomKid1 =
474         JwtRsaSsaPkcs1PublicKey.builder()
475             .setParameters(parametersCustomKid)
476             .setModulus(MODULUS)
477             .setCustomKid("CustomKID1")
478             .build();
479     JwtRsaSsaPkcs1PublicKey publicKeyCustomKid2 =
480         JwtRsaSsaPkcs1PublicKey.builder()
481             .setParameters(parametersCustomKid)
482             .setModulus(MODULUS)
483             .setCustomKid("CustomKID2")
484             .build();
485 
486     new KeyTester()
487         .addEqualityGroup(
488             "kidStrategyIgnored",
489             JwtRsaSsaPkcs1PrivateKey.builder()
490                 .setPublicKey(kidStrategyIgnoredPublicKey)
491                 .setPrimes(
492                     SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()),
493                     SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()))
494                 .setPrivateExponent(
495                     SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get()))
496                 .setPrimeExponents(
497                     SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()),
498                     SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()))
499                 .setCrtCoefficient(
500                     SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get()))
501                 .build(),
502             // the same key built twice must be equal
503             JwtRsaSsaPkcs1PrivateKey.builder()
504                 .setPublicKey(kidStrategyIgnoredPublicKey)
505                 .setPrimes(
506                     SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()),
507                     SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()))
508                 .setPrivateExponent(
509                     SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get()))
510                 .setPrimeExponents(
511                     SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()),
512                     SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()))
513                 .setCrtCoefficient(
514                     SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get()))
515                 .build())
516         // This group checks that a private key where p and q are swapped is considered different
517         .addEqualityGroup(
518             "p and q swapped",
519             JwtRsaSsaPkcs1PrivateKey.builder()
520                 .setPublicKey(kidStrategyIgnoredPublicKey)
521                 .setPrimes(
522                     SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()),
523                     SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()))
524                 .setPrivateExponent(
525                     SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get()))
526                 .setPrimeExponents(
527                     SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()),
528                     SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()))
529                 .setCrtCoefficient(
530                     SecretBigInteger.fromBigInteger(P.modInverse(Q), InsecureSecretKeyAccess.get()))
531                 .build())
532         // This group checks that keys with different parameters are not equal
533         .addEqualityGroup(
534             "KID ignored, RRS512",
535             JwtRsaSsaPkcs1PrivateKey.builder()
536                 .setPublicKey(kidStrategyIgnoredPublicKeyRS512)
537                 .setPrimes(
538                     SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()),
539                     SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()))
540                 .setPrivateExponent(
541                     SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get()))
542                 .setPrimeExponents(
543                     SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()),
544                     SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()))
545                 .setCrtCoefficient(
546                     SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get()))
547                 .build())
548         .addEqualityGroup(
549             "KID Base 64",
550             JwtRsaSsaPkcs1PrivateKey.builder()
551                 .setPublicKey(kidStrategyBase64PublicKey)
552                 .setPrimes(
553                     SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()),
554                     SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()))
555                 .setPrivateExponent(
556                     SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get()))
557                 .setPrimeExponents(
558                     SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()),
559                     SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()))
560                 .setCrtCoefficient(
561                     SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get()))
562                 .build())
563         .addEqualityGroup(
564             "CustomKID1",
565             JwtRsaSsaPkcs1PrivateKey.builder()
566                 .setPublicKey(publicKeyCustomKid1)
567                 .setPrimes(
568                     SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()),
569                     SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()))
570                 .setPrivateExponent(
571                     SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get()))
572                 .setPrimeExponents(
573                     SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()),
574                     SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()))
575                 .setCrtCoefficient(
576                     SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get()))
577                 .build())
578         .addEqualityGroup(
579             "CustomKID2",
580             JwtRsaSsaPkcs1PrivateKey.builder()
581                 .setPublicKey(publicKeyCustomKid2)
582                 .setPrimes(
583                     SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()),
584                     SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()))
585                 .setPrivateExponent(
586                     SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get()))
587                 .setPrimeExponents(
588                     SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()),
589                     SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()))
590                 .setCrtCoefficient(
591                     SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get()))
592                 .build())
593         .addEqualityGroup(
594             "different key class", ChaCha20Poly1305Key.create(SecretBytes.randomBytes(32)))
595         .doTests();
596   }
597 }
598