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