diff options
author | ioannanedelcu <ioannanedelcu@google.com> | 2023-08-09 09:01:26 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-08-09 09:02:27 -0700 |
commit | 8bcfd2de3868aac08778909291c24fd5a38953e7 (patch) | |
tree | 501f17c48b7707fed63243395f7e20c21f21ea95 | |
parent | a368136edb61cd4dd441b0dd0b9b4914c8f435d5 (diff) | |
download | tink-8bcfd2de3868aac08778909291c24fd5a38953e7.tar.gz |
Add JwtRsaSsaPss Public Key in Java.
PiperOrigin-RevId: 555178900
5 files changed, 587 insertions, 0 deletions
diff --git a/java_src/BUILD.bazel b/java_src/BUILD.bazel index 460c11ca3..52925ba81 100644 --- a/java_src/BUILD.bazel +++ b/java_src/BUILD.bazel @@ -247,6 +247,7 @@ gen_maven_jar_rules( "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pkcs1_sign_key_manager", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pkcs1_verify_key_manager", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_parameters", + "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_public_key", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_sign_key_manager", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_verify_key_manager", "//src/main/java/com/google/crypto/tink/jwt:jwt_signature_config", @@ -682,6 +683,7 @@ gen_maven_jar_rules( "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pkcs1_sign_key_manager-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pkcs1_verify_key_manager-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_parameters-android", + "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_public_key-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_sign_key_manager-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_verify_key_manager-android", "//src/main/java/com/google/crypto/tink/jwt:jwt_signature_config-android", diff --git a/java_src/src/main/java/com/google/crypto/tink/jwt/BUILD.bazel b/java_src/src/main/java/com/google/crypto/tink/jwt/BUILD.bazel index ad3bc2af0..e080b98ef 100644 --- a/java_src/src/main/java/com/google/crypto/tink/jwt/BUILD.bazel +++ b/java_src/src/main/java/com/google/crypto/tink/jwt/BUILD.bazel @@ -1277,3 +1277,31 @@ java_library( "@maven//:com_google_errorprone_error_prone_annotations", ], ) + +java_library( + name = "jwt_rsa_ssa_pss_public_key", + srcs = ["JwtRsaSsaPssPublicKey.java"], + deps = [ + ":jwt_rsa_ssa_pss_parameters", + ":jwt_signature_public_key", + "//src/main/java/com/google/crypto/tink:accesses_partial_key", + "//src/main/java/com/google/crypto/tink:key", + "//src/main/java/com/google/crypto/tink/subtle:base64", + "@maven//:com_google_code_findbugs_jsr305", + "@maven//:com_google_errorprone_error_prone_annotations", + ], +) + +android_library( + name = "jwt_rsa_ssa_pss_public_key-android", + srcs = ["JwtRsaSsaPssPublicKey.java"], + deps = [ + ":jwt_rsa_ssa_pss_parameters-android", + ":jwt_signature_public_key-android", + "//src/main/java/com/google/crypto/tink:accesses_partial_key-android", + "//src/main/java/com/google/crypto/tink:key-android", + "//src/main/java/com/google/crypto/tink/subtle:base64-android", + "@maven//:com_google_code_findbugs_jsr305", + "@maven//:com_google_errorprone_error_prone_annotations", + ], +) diff --git a/java_src/src/main/java/com/google/crypto/tink/jwt/JwtRsaSsaPssPublicKey.java b/java_src/src/main/java/com/google/crypto/tink/jwt/JwtRsaSsaPssPublicKey.java new file mode 100644 index 000000000..ebc0ff72d --- /dev/null +++ b/java_src/src/main/java/com/google/crypto/tink/jwt/JwtRsaSsaPssPublicKey.java @@ -0,0 +1,202 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +package com.google.crypto.tink.jwt; + +import com.google.crypto.tink.AccessesPartialKey; +import com.google.crypto.tink.Key; +import com.google.crypto.tink.subtle.Base64; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.RestrictedApi; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.security.GeneralSecurityException; +import java.util.Optional; +import javax.annotation.Nullable; + +/** + * Represents a public key for the JWT RSA SSA PSS signature primitive. + * + * <p>Standard: https://datatracker.ietf.org/doc/html/rfc7518 + */ +public final class JwtRsaSsaPssPublicKey extends JwtSignaturePublicKey { + private final JwtRsaSsaPssParameters parameters; + private final BigInteger modulus; + private final Optional<Integer> idRequirement; + private final Optional<String> kid; + + /** Builder for JwtRsaSsaPssPublicKey. */ + public static class Builder { + private Optional<JwtRsaSsaPssParameters> parameters = Optional.empty(); + private Optional<BigInteger> modulus = Optional.empty(); + private Optional<Integer> idRequirement = Optional.empty(); + private Optional<String> customKid = Optional.empty(); + + private Builder() {} + + @CanIgnoreReturnValue + public Builder setParameters(JwtRsaSsaPssParameters parameters) { + this.parameters = Optional.of(parameters); + return this; + } + + @CanIgnoreReturnValue + public Builder setModulus(BigInteger modulus) { + this.modulus = Optional.of(modulus); + return this; + } + + @CanIgnoreReturnValue + public Builder setIdRequirement(Integer idRequirement) { + this.idRequirement = Optional.of(idRequirement); + return this; + } + + @CanIgnoreReturnValue + public Builder setCustomKid(String customKid) { + this.customKid = Optional.of(customKid); + return this; + } + + private Optional<String> computeKid() throws GeneralSecurityException { + if (parameters + .get() + .getKidStrategy() + .equals(JwtRsaSsaPssParameters.KidStrategy.BASE64_ENCODED_KEY_ID)) { + if (customKid.isPresent()) { + throw new GeneralSecurityException( + "customKid must not be set for KidStrategy BASE64_ENCODED_KEY_ID"); + } + byte[] bigEndianKeyId = ByteBuffer.allocate(4).putInt(idRequirement.get()).array(); + return Optional.of(Base64.urlSafeEncode(bigEndianKeyId)); + } + if (parameters.get().getKidStrategy().equals(JwtRsaSsaPssParameters.KidStrategy.CUSTOM)) { + if (!customKid.isPresent()) { + throw new GeneralSecurityException("customKid needs to be set for KidStrategy CUSTOM"); + } + return customKid; + } + if (parameters.get().getKidStrategy().equals(JwtRsaSsaPssParameters.KidStrategy.IGNORED)) { + if (customKid.isPresent()) { + throw new GeneralSecurityException("customKid must not be set for KidStrategy IGNORED"); + } + return Optional.empty(); + } + throw new IllegalStateException("Unknown kid strategy"); + } + + public JwtRsaSsaPssPublicKey build() throws GeneralSecurityException { + if (!parameters.isPresent()) { + throw new GeneralSecurityException("Cannot build without parameters"); + } + + if (!modulus.isPresent()) { + throw new GeneralSecurityException("Cannot build without modulus"); + } + int modulusSize = modulus.get().bitLength(); + int paramModulusSize = parameters.get().getModulusSizeBits(); + // https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf, B.3 requires p and q + // to be chosen such that 2^(paramModulusSize-1) < modulus < 2^paramModulusSize. + if (modulusSize != paramModulusSize) { + throw new GeneralSecurityException( + "Got modulus size " + + modulusSize + + ", but parameters requires modulus size " + + paramModulusSize); + } + + if (parameters.get().hasIdRequirement() && !idRequirement.isPresent()) { + throw new GeneralSecurityException( + "Cannot create key without ID requirement with parameters with ID requirement"); + } + + if (!parameters.get().hasIdRequirement() && idRequirement.isPresent()) { + throw new GeneralSecurityException( + "Cannot create key with ID requirement with parameters without ID requirement"); + } + + return new JwtRsaSsaPssPublicKey( + parameters.get(), modulus.get(), idRequirement, computeKid()); + } + } + + private JwtRsaSsaPssPublicKey( + JwtRsaSsaPssParameters parameters, + BigInteger modulus, + Optional<Integer> idRequirement, + Optional<String> kid) { + this.parameters = parameters; + this.modulus = modulus; + this.idRequirement = idRequirement; + this.kid = kid; + } + + @RestrictedApi( + explanation = "Accessing parts of keys can produce unexpected incompatibilities, annotate the function with @AccessesPartialKey", + link = "https://developers.google.com/tink/design/access_control#accessing_partial_keys", + allowedOnPath = ".*Test\\.java", + allowlistAnnotations = {AccessesPartialKey.class}) + public static Builder builder() { + return new Builder(); + } + + /** Returns the underlying key bytes. */ + @RestrictedApi( + explanation = "Accessing parts of keys can produce unexpected incompatibilities, annotate the function with @AccessesPartialKey", + link = "https://developers.google.com/tink/design/access_control#accessing_partial_keys", + allowedOnPath = ".*Test\\.java", + allowlistAnnotations = {AccessesPartialKey.class}) + public BigInteger getModulus() { + return modulus; + } + + /** + * Returns the "kid" to be used for this key. + * + * <p>If present, this kid will be written into the {@code kid} header during {{@code + * PublicKeySign#signAndEncode}. If absent, no kid will be written. + * + * <p>If present, and the {@code kid} header is present, the contents of the {@code kid} header + * needs to match the return value of this function. + */ + @Override + public Optional<String> getKid() { + return kid; + } + + @Override + public JwtRsaSsaPssParameters getParameters() { + return parameters; + } + + @Override + @Nullable + public Integer getIdRequirementOrNull() { + return idRequirement.orElse(null); + } + + @Override + public boolean equalsKey(Key o) { + if (!(o instanceof JwtRsaSsaPssPublicKey)) { + return false; + } + JwtRsaSsaPssPublicKey that = (JwtRsaSsaPssPublicKey) o; + return that.parameters.equals(parameters) + && that.modulus.equals(modulus) + && that.kid.equals(kid) + && that.idRequirement.equals(idRequirement); + } +} diff --git a/java_src/src/test/java/com/google/crypto/tink/jwt/BUILD.bazel b/java_src/src/test/java/com/google/crypto/tink/jwt/BUILD.bazel index 79dfa7f97..d2556645f 100644 --- a/java_src/src/test/java/com/google/crypto/tink/jwt/BUILD.bazel +++ b/java_src/src/test/java/com/google/crypto/tink/jwt/BUILD.bazel @@ -585,3 +585,17 @@ java_test( "@maven//:junit_junit", ], ) + +java_test( + name = "JwtRsaSsaPssPublicKeyTest", + size = "small", + srcs = ["JwtRsaSsaPssPublicKeyTest.java"], + deps = [ + "//src/main/java/com/google/crypto/tink/internal:key_tester", + "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_parameters", + "//src/main/java/com/google/crypto/tink/jwt:jwt_rsa_ssa_pss_public_key", + "//src/main/java/com/google/crypto/tink/subtle:base64", + "@maven//:com_google_truth_truth", + "@maven//:junit_junit", + ], +) diff --git a/java_src/src/test/java/com/google/crypto/tink/jwt/JwtRsaSsaPssPublicKeyTest.java b/java_src/src/test/java/com/google/crypto/tink/jwt/JwtRsaSsaPssPublicKeyTest.java new file mode 100644 index 000000000..36ad7351a --- /dev/null +++ b/java_src/src/test/java/com/google/crypto/tink/jwt/JwtRsaSsaPssPublicKeyTest.java @@ -0,0 +1,341 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +package com.google.crypto.tink.jwt; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; + +import com.google.crypto.tink.internal.KeyTester; +import com.google.crypto.tink.subtle.Base64; +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.util.Optional; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public final class JwtRsaSsaPssPublicKeyTest { + + // Test vector from https://www.rfc-editor.org/rfc/rfc7517#appendix-C.1 + static final BigInteger MODULUS = + new BigInteger( + 1, + Base64.urlSafeDecode( + "t6Q8PWSi1dkJj9hTP8hNYFlvadM7DflW9mWepOJhJ66w7nyoK1gPNqFMSQRy" + + "O125Gp-TEkodhWr0iujjHVx7BcV0llS4w5ACGgPrcAd6ZcSR0-Iqom-QFcNP" + + "8Sjg086MwoqQU_LYywlAGZ21WSdS_PERyGFiNnj3QQlO8Yns5jCtLCRwLHL0" + + "Pb1fEv45AuRIuUfVcPySBWYnDyGxvjYGDSM-AqWS9zIQ2ZilgT-GqUmipg0X" + + "OC0Cc20rgLe2ymLHjpHciCKVAbY5-L32-lSeZO-Os6U15_aXrk9Gw8cPUaX1" + + "_I8sLGuSiVdt3C_Fn2PZ3Z8i744FPFGGcG1qs2Wz-Q")); + + @Test + public void build_kidStrategyIgnored_hasExpectedValues() throws Exception { + JwtRsaSsaPssParameters parameters = + JwtRsaSsaPssParameters.builder() + .setModulusSizeBits(2048) + .setPublicExponent(JwtRsaSsaPssParameters.F4) + .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.IGNORED) + .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256) + .build(); + JwtRsaSsaPssPublicKey key = + JwtRsaSsaPssPublicKey.builder().setParameters(parameters).setModulus(MODULUS).build(); + assertThat(key.getParameters()).isEqualTo(parameters); + assertThat(key.getModulus()).isEqualTo(MODULUS); + assertThat(key.getKid()).isEqualTo(Optional.empty()); + assertThat(key.getIdRequirementOrNull()).isNull(); + } + + @Test + public void build_kidStrategyIgnored_setCustomKid_fails() throws Exception { + JwtRsaSsaPssParameters parameters = + JwtRsaSsaPssParameters.builder() + .setModulusSizeBits(2048) + .setPublicExponent(JwtRsaSsaPssParameters.F4) + .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.IGNORED) + .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256) + .build(); + JwtRsaSsaPssPublicKey.Builder builder = + JwtRsaSsaPssPublicKey.builder() + .setParameters(parameters) + .setModulus(MODULUS) + .setCustomKid("customKid23"); + assertThrows(GeneralSecurityException.class, builder::build); + } + + @Test + public void build_kidStrategyIgnored_setIdRequirement_fails() throws Exception { + JwtRsaSsaPssParameters parameters = + JwtRsaSsaPssParameters.builder() + .setModulusSizeBits(2048) + .setPublicExponent(JwtRsaSsaPssParameters.F4) + .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.IGNORED) + .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256) + .build(); + JwtRsaSsaPssPublicKey.Builder builder = + JwtRsaSsaPssPublicKey.builder() + .setParameters(parameters) + .setIdRequirement(123) + .setModulus(MODULUS); + assertThrows(GeneralSecurityException.class, builder::build); + } + + @Test + public void build_kidStrategyCustom_hasExpectedValues() throws Exception { + JwtRsaSsaPssParameters parameters = + JwtRsaSsaPssParameters.builder() + .setModulusSizeBits(2048) + .setPublicExponent(JwtRsaSsaPssParameters.F4) + .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.CUSTOM) + .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256) + .build(); + JwtRsaSsaPssPublicKey key = + JwtRsaSsaPssPublicKey.builder() + .setParameters(parameters) + .setModulus(MODULUS) + .setCustomKid("customKid777") + .build(); + assertThat(key.getParameters()).isEqualTo(parameters); + assertThat(key.getModulus()).isEqualTo(MODULUS); + assertThat(key.getKid().get()).isEqualTo("customKid777"); + assertThat(key.getIdRequirementOrNull()).isNull(); + } + + @Test + public void build_kidStrategyCustom_setIdRequirement_fails() throws Exception { + JwtRsaSsaPssParameters parameters = + JwtRsaSsaPssParameters.builder() + .setModulusSizeBits(2048) + .setPublicExponent(JwtRsaSsaPssParameters.F4) + .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.CUSTOM) + .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256) + .build(); + JwtRsaSsaPssPublicKey.Builder builder = + JwtRsaSsaPssPublicKey.builder() + .setParameters(parameters) + .setIdRequirement(123) + .setCustomKid("customKid777") + .setModulus(MODULUS); + assertThrows(GeneralSecurityException.class, builder::build); + } + + @Test + public void buildKidStrategyCustom_missingCustomKid_fails() throws Exception { + JwtRsaSsaPssParameters parameters = + JwtRsaSsaPssParameters.builder() + .setModulusSizeBits(2048) + .setPublicExponent(JwtRsaSsaPssParameters.F4) + .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.CUSTOM) + .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256) + .build(); + JwtRsaSsaPssPublicKey.Builder builder = + JwtRsaSsaPssPublicKey.builder().setParameters(parameters).setModulus(MODULUS); + assertThrows(GeneralSecurityException.class, builder::build); + } + + @Test + public void build_kidStrategyBase64_getProperties_succeeds() throws Exception { + JwtRsaSsaPssParameters parameters = + JwtRsaSsaPssParameters.builder() + .setModulusSizeBits(2048) + .setPublicExponent(JwtRsaSsaPssParameters.F4) + .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.BASE64_ENCODED_KEY_ID) + .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256) + .build(); + JwtRsaSsaPssPublicKey key = + JwtRsaSsaPssPublicKey.builder() + .setParameters(parameters) + .setModulus(MODULUS) + .setIdRequirement(0x1ac6a944) + .build(); + assertThat(key.getParameters()).isEqualTo(parameters); + assertThat(key.getIdRequirementOrNull()).isEqualTo(0x1ac6a944); + // See JwtFormatTest.getKidFromTinkOutputPrefixType_success + assertThat(key.getKid()).isEqualTo(Optional.of("GsapRA")); + } + + @Test + public void build_kidStrategyBase64_noIdRequirement_throws() throws Exception { + JwtRsaSsaPssParameters parameters = + JwtRsaSsaPssParameters.builder() + .setModulusSizeBits(2048) + .setPublicExponent(JwtRsaSsaPssParameters.F4) + .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.BASE64_ENCODED_KEY_ID) + .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256) + .build(); + JwtRsaSsaPssPublicKey.Builder builder = + JwtRsaSsaPssPublicKey.builder().setParameters(parameters).setModulus(MODULUS); + assertThrows(GeneralSecurityException.class, builder::build); + } + + @Test + public void build_kidStrategyBase64_setCustomKid_throws() throws Exception { + JwtRsaSsaPssParameters parameters = + JwtRsaSsaPssParameters.builder() + .setModulusSizeBits(2048) + .setPublicExponent(JwtRsaSsaPssParameters.F4) + .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.BASE64_ENCODED_KEY_ID) + .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256) + .build(); + JwtRsaSsaPssPublicKey.Builder builder = + JwtRsaSsaPssPublicKey.builder() + .setParameters(parameters) + .setIdRequirement(0x89abcdef) + .setCustomKid("customKid") + .setModulus(MODULUS); + assertThrows(GeneralSecurityException.class, builder::build); + } + + @Test + public void emptyBuild_fails() throws Exception { + assertThrows(GeneralSecurityException.class, () -> JwtRsaSsaPssPublicKey.builder().build()); + } + + @Test + public void buildWithoutParameters_fails() throws Exception { + assertThrows( + GeneralSecurityException.class, + () -> JwtRsaSsaPssPublicKey.builder().setModulus(MODULUS).build()); + } + + @Test + public void build_withoutModulus_fails() throws Exception { + JwtRsaSsaPssParameters parameters = + JwtRsaSsaPssParameters.builder() + .setModulusSizeBits(2048) + .setPublicExponent(JwtRsaSsaPssParameters.F4) + .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.IGNORED) + .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256) + .build(); + assertThrows( + GeneralSecurityException.class, + () -> JwtRsaSsaPssPublicKey.builder().setParameters(parameters).build()); + } + + @Test + public void build_invalidModulusSize_fails() throws Exception { + JwtRsaSsaPssParameters parameters = + JwtRsaSsaPssParameters.builder() + .setModulusSizeBits(3456) + .setPublicExponent(JwtRsaSsaPssParameters.F4) + .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.IGNORED) + .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256) + .build(); + + // Modulus between 2^3455 and 2^3456 are valid. + BigInteger tooSmall = BigInteger.valueOf(2).pow(3455).subtract(BigInteger.ONE); + BigInteger tooBig = BigInteger.valueOf(2).pow(3456).add(BigInteger.ONE); + + assertThrows( + GeneralSecurityException.class, + () -> + JwtRsaSsaPssPublicKey.builder().setParameters(parameters).setModulus(tooSmall).build()); + assertThrows( + GeneralSecurityException.class, + () -> JwtRsaSsaPssPublicKey.builder().setParameters(parameters).setModulus(tooBig).build()); + } + + @Test + public void testEqualities() throws Exception { + JwtRsaSsaPssParameters kidStrategyIgnoredParameters = + JwtRsaSsaPssParameters.builder() + .setModulusSizeBits(2048) + .setPublicExponent(JwtRsaSsaPssParameters.F4) + .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.IGNORED) + .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256) + .build(); + JwtRsaSsaPssParameters kidStrategyIgnoredParametersCopy = + JwtRsaSsaPssParameters.builder() + .setModulusSizeBits(2048) + .setPublicExponent(JwtRsaSsaPssParameters.F4) + .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.IGNORED) + .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256) + .build(); + + JwtRsaSsaPssParameters kidStrategyCustomParameters = + JwtRsaSsaPssParameters.builder() + .setModulusSizeBits(2048) + .setPublicExponent(JwtRsaSsaPssParameters.F4) + .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.CUSTOM) + .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256) + .build(); + + JwtRsaSsaPssParameters kidStrategyBase64Parameters = + JwtRsaSsaPssParameters.builder() + .setModulusSizeBits(2048) + .setPublicExponent(JwtRsaSsaPssParameters.F4) + .setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.BASE64_ENCODED_KEY_ID) + .setAlgorithm(JwtRsaSsaPssParameters.Algorithm.PS256) + .build(); + + new KeyTester() + .addEqualityGroup( + "KID Ignored, R256", + JwtRsaSsaPssPublicKey.builder() + .setParameters(kidStrategyIgnoredParameters) + .setModulus(MODULUS) + .build(), + // the same key built twice must be equal + JwtRsaSsaPssPublicKey.builder() + .setParameters(kidStrategyIgnoredParameters) + .setModulus(MODULUS) + .build(), + // the same key built with a copy of parameters must be equal + JwtRsaSsaPssPublicKey.builder() + .setParameters(kidStrategyIgnoredParametersCopy) + .setModulus(MODULUS) + .build()) + // This group checks that keys with different key bytes are not equal + .addEqualityGroup( + "KID Ignored, different modulus", + JwtRsaSsaPssPublicKey.builder() + .setParameters(kidStrategyIgnoredParameters) + .setModulus(MODULUS.add(BigInteger.ONE)) + .build()) + // These groups checks that keys with different customKid are not equal + .addEqualityGroup( + "KID Custom, customKid1", + JwtRsaSsaPssPublicKey.builder() + .setParameters(kidStrategyCustomParameters) + .setModulus(MODULUS) + .setCustomKid("customKid1") + .build()) + .addEqualityGroup( + "KID Custom, customKid2", + JwtRsaSsaPssPublicKey.builder() + .setParameters(kidStrategyCustomParameters) + .setModulus(MODULUS) + .setCustomKid("customKid2") + .build()) + // These groups checks that keys with different ID Requirements are not equal + .addEqualityGroup( + "Tink with key id 1907", + JwtRsaSsaPssPublicKey.builder() + .setParameters(kidStrategyBase64Parameters) + .setModulus(MODULUS) + .setIdRequirement(1907) + .build()) + .addEqualityGroup( + "Tink with key id 1908", + JwtRsaSsaPssPublicKey.builder() + .setParameters(kidStrategyBase64Parameters) + .setModulus(MODULUS) + .setIdRequirement(1908) + .build()) + .doTests(); + } +} |