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.signature; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static org.junit.Assert.assertThrows; 21 22 import java.math.BigInteger; 23 import java.security.GeneralSecurityException; 24 import org.junit.Test; 25 import org.junit.runner.RunWith; 26 import org.junit.runners.JUnit4; 27 28 @RunWith(JUnit4.class) 29 public final class RsaSsaPssParametersTest { 30 31 @Test buildWithNoPrefixAndGetProperties()32 public void buildWithNoPrefixAndGetProperties() throws Exception { 33 RsaSsaPssParameters parameters = 34 RsaSsaPssParameters.builder() 35 .setModulusSizeBits(2048) 36 .setPublicExponent(RsaSsaPssParameters.F4) 37 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 38 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 39 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 40 .setSaltLengthBytes(32) 41 .build(); 42 assertThat(parameters.getModulusSizeBits()).isEqualTo(2048); 43 assertThat(parameters.getPublicExponent()).isEqualTo(RsaSsaPssParameters.F4); 44 assertThat(parameters.getSigHashType()).isEqualTo(RsaSsaPssParameters.HashType.SHA256); 45 assertThat(parameters.getMgf1HashType()).isEqualTo(RsaSsaPssParameters.HashType.SHA256); 46 assertThat(parameters.getVariant()).isEqualTo(RsaSsaPssParameters.Variant.NO_PREFIX); 47 assertThat(parameters.getSaltLengthBytes()).isEqualTo(32); 48 assertThat(parameters.hasIdRequirement()).isFalse(); 49 } 50 51 @Test buildParametersWithoutSettingVariant_hasNoPrefix()52 public void buildParametersWithoutSettingVariant_hasNoPrefix() throws Exception { 53 RsaSsaPssParameters parameters = 54 RsaSsaPssParameters.builder() 55 .setModulusSizeBits(2048) 56 .setPublicExponent(RsaSsaPssParameters.F4) 57 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 58 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 59 .setSaltLengthBytes(32) 60 .build(); 61 assertThat(parameters.getVariant()).isEqualTo(RsaSsaPssParameters.Variant.NO_PREFIX); 62 assertThat(parameters.hasIdRequirement()).isFalse(); 63 } 64 65 @Test buildParametersWithoutExponent_defaultsToF4()66 public void buildParametersWithoutExponent_defaultsToF4() throws Exception { 67 RsaSsaPssParameters parameters = 68 RsaSsaPssParameters.builder() 69 .setModulusSizeBits(2048) 70 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 71 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 72 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 73 .setSaltLengthBytes(32) 74 .build(); 75 assertThat(parameters.getPublicExponent()).isEqualTo(RsaSsaPssParameters.F4); 76 } 77 78 @Test buildParametersWithTinkPrefix()79 public void buildParametersWithTinkPrefix() throws Exception { 80 RsaSsaPssParameters parameters = 81 RsaSsaPssParameters.builder() 82 .setModulusSizeBits(2048) 83 .setPublicExponent(RsaSsaPssParameters.F4) 84 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 85 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 86 .setVariant(RsaSsaPssParameters.Variant.TINK) 87 .setSaltLengthBytes(32) 88 .build(); 89 assertThat(parameters.getVariant()).isEqualTo(RsaSsaPssParameters.Variant.TINK); 90 assertThat(parameters.hasIdRequirement()).isTrue(); 91 } 92 93 @Test buildParametersWithLegacyPrefix()94 public void buildParametersWithLegacyPrefix() throws Exception { 95 RsaSsaPssParameters parameters = 96 RsaSsaPssParameters.builder() 97 .setModulusSizeBits(2048) 98 .setPublicExponent(RsaSsaPssParameters.F4) 99 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 100 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 101 .setVariant(RsaSsaPssParameters.Variant.LEGACY) 102 .setSaltLengthBytes(32) 103 .build(); 104 assertThat(parameters.getVariant()).isEqualTo(RsaSsaPssParameters.Variant.LEGACY); 105 assertThat(parameters.hasIdRequirement()).isTrue(); 106 } 107 108 @Test buildParametersWithCrunchyPrefix()109 public void buildParametersWithCrunchyPrefix() throws Exception { 110 RsaSsaPssParameters parameters = 111 RsaSsaPssParameters.builder() 112 .setModulusSizeBits(4096) 113 .setPublicExponent(RsaSsaPssParameters.F4) 114 .setSigHashType(RsaSsaPssParameters.HashType.SHA512) 115 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA512) 116 .setVariant(RsaSsaPssParameters.Variant.CRUNCHY) 117 .setSaltLengthBytes(64) 118 .build(); 119 assertThat(parameters.getVariant()).isEqualTo(RsaSsaPssParameters.Variant.CRUNCHY); 120 assertThat(parameters.hasIdRequirement()).isTrue(); 121 } 122 123 @Test buildParametersWithSha384()124 public void buildParametersWithSha384() throws Exception { 125 RsaSsaPssParameters parameters = 126 RsaSsaPssParameters.builder() 127 .setModulusSizeBits(3072) 128 .setPublicExponent(RsaSsaPssParameters.F4) 129 .setSigHashType(RsaSsaPssParameters.HashType.SHA384) 130 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA384) 131 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 132 .setSaltLengthBytes(48) 133 .build(); 134 assertThat(parameters.getSigHashType()).isEqualTo(RsaSsaPssParameters.HashType.SHA384); 135 assertThat(parameters.getMgf1HashType()).isEqualTo(RsaSsaPssParameters.HashType.SHA384); 136 } 137 138 @Test buildParametersWithSha512()139 public void buildParametersWithSha512() throws Exception { 140 RsaSsaPssParameters parameters = 141 RsaSsaPssParameters.builder() 142 .setModulusSizeBits(4096) 143 .setPublicExponent(RsaSsaPssParameters.F4) 144 .setSigHashType(RsaSsaPssParameters.HashType.SHA512) 145 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA512) 146 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 147 .setSaltLengthBytes(64) 148 .build(); 149 assertThat(parameters.getSigHashType()).isEqualTo(RsaSsaPssParameters.HashType.SHA512); 150 assertThat(parameters.getMgf1HashType()).isEqualTo(RsaSsaPssParameters.HashType.SHA512); 151 } 152 153 @Test buildParametersWithLargeModulusSize()154 public void buildParametersWithLargeModulusSize() throws Exception { 155 RsaSsaPssParameters parameters = 156 RsaSsaPssParameters.builder() 157 .setModulusSizeBits(16789) 158 .setPublicExponent(RsaSsaPssParameters.F4) 159 .setSigHashType(RsaSsaPssParameters.HashType.SHA512) 160 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA512) 161 .setVariant(RsaSsaPssParameters.Variant.CRUNCHY) 162 .setSaltLengthBytes(64) 163 .build(); 164 assertThat(parameters.getModulusSizeBits()).isEqualTo(16789); 165 } 166 167 @Test buildParametersWithValidNonF4PublicExponentSet()168 public void buildParametersWithValidNonF4PublicExponentSet() throws Exception { 169 RsaSsaPssParameters parameters = 170 RsaSsaPssParameters.builder() 171 .setModulusSizeBits(2048) 172 .setPublicExponent(BigInteger.valueOf(1234567)) 173 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 174 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 175 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 176 .setSaltLengthBytes(32) 177 .build(); 178 assertThat(parameters.getPublicExponent()).isEqualTo(BigInteger.valueOf(1234567)); 179 } 180 181 @Test buildParametersWithTooSmallModulusSize_fails()182 public void buildParametersWithTooSmallModulusSize_fails() throws Exception { 183 assertThrows( 184 GeneralSecurityException.class, 185 () -> 186 RsaSsaPssParameters.builder() 187 .setModulusSizeBits(2047) 188 .setPublicExponent(RsaSsaPssParameters.F4) 189 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 190 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 191 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 192 .build()); 193 } 194 195 @Test buildParametersWithSmallPublicExponent_fails()196 public void buildParametersWithSmallPublicExponent_fails() throws Exception { 197 assertThrows( 198 GeneralSecurityException.class, 199 () -> 200 RsaSsaPssParameters.builder() 201 .setModulusSizeBits(2048) 202 .setPublicExponent(BigInteger.valueOf(3)) 203 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 204 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 205 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 206 .setSaltLengthBytes(32) 207 .build()); 208 } 209 210 @Test buildParametersWithEvenPublicExponent_fails()211 public void buildParametersWithEvenPublicExponent_fails() throws Exception { 212 assertThrows( 213 GeneralSecurityException.class, 214 () -> 215 RsaSsaPssParameters.builder() 216 .setModulusSizeBits(2048) 217 .setPublicExponent(BigInteger.valueOf(1234568)) 218 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 219 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 220 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 221 .setSaltLengthBytes(32) 222 .build()); 223 } 224 225 @Test buildParametersWithLargePublicExponent_works()226 public void buildParametersWithLargePublicExponent_works() throws Exception { 227 BigInteger largeE = BigInteger.valueOf(100000000001L); 228 RsaSsaPssParameters parameters = 229 RsaSsaPssParameters.builder() 230 .setModulusSizeBits(2048) 231 .setPublicExponent(largeE) 232 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 233 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 234 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 235 .setSaltLengthBytes(32) 236 .build(); 237 assertThat(parameters.getPublicExponent()).isEqualTo(largeE); 238 } 239 240 // Public exponents larger than 2^256 are rejected. See: 241 // https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf, B.3 242 @Test buildParametersWithTooLargePublicExponent_fails()243 public void buildParametersWithTooLargePublicExponent_fails() throws Exception { 244 BigInteger tooLargeE = BigInteger.valueOf(2).pow(256).add(BigInteger.ONE); 245 assertThat(tooLargeE.bitLength()).isEqualTo(257); 246 assertThrows( 247 GeneralSecurityException.class, 248 () -> 249 RsaSsaPssParameters.builder() 250 .setModulusSizeBits(2048) 251 .setPublicExponent(tooLargeE) 252 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 253 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 254 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 255 .setSaltLengthBytes(32) 256 .build()); 257 } 258 259 @Test buildParametersWithoutSettingModulusSize_fails()260 public void buildParametersWithoutSettingModulusSize_fails() throws Exception { 261 assertThrows( 262 GeneralSecurityException.class, 263 () -> 264 RsaSsaPssParameters.builder() 265 .setPublicExponent(RsaSsaPssParameters.F4) 266 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 267 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 268 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 269 .setSaltLengthBytes(32) 270 .build()); 271 } 272 273 @Test buildParametersWithoutSettingSigHashType_fails()274 public void buildParametersWithoutSettingSigHashType_fails() throws Exception { 275 assertThrows( 276 GeneralSecurityException.class, 277 () -> 278 RsaSsaPssParameters.builder() 279 .setModulusSizeBits(2048) 280 .setPublicExponent(RsaSsaPssParameters.F4) 281 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 282 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 283 .setSaltLengthBytes(32) 284 .build()); 285 } 286 287 @Test buildParametersWithoutSettingMgf1HashType_fails()288 public void buildParametersWithoutSettingMgf1HashType_fails() throws Exception { 289 assertThrows( 290 GeneralSecurityException.class, 291 () -> 292 RsaSsaPssParameters.builder() 293 .setModulusSizeBits(2048) 294 .setPublicExponent(RsaSsaPssParameters.F4) 295 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 296 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 297 .setSaltLengthBytes(32) 298 .build()); 299 } 300 301 @Test buildParametersWithDifferentHashTypes_fails()302 public void buildParametersWithDifferentHashTypes_fails() throws Exception { 303 assertThrows( 304 GeneralSecurityException.class, 305 () -> 306 RsaSsaPssParameters.builder() 307 .setModulusSizeBits(2048) 308 .setPublicExponent(RsaSsaPssParameters.F4) 309 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 310 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 311 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA512) 312 .setSaltLengthBytes(32) 313 .build()); 314 } 315 316 @Test buildParametersWithoutSettingSaltLength_fails()317 public void buildParametersWithoutSettingSaltLength_fails() throws Exception { 318 assertThrows( 319 GeneralSecurityException.class, 320 () -> 321 RsaSsaPssParameters.builder() 322 .setModulusSizeBits(2048) 323 .setPublicExponent(RsaSsaPssParameters.F4) 324 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 325 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 326 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 327 .build()); 328 } 329 330 @Test buildParametersWithVariantSetToNull_fails()331 public void buildParametersWithVariantSetToNull_fails() throws Exception { 332 assertThrows( 333 GeneralSecurityException.class, 334 () -> 335 RsaSsaPssParameters.builder() 336 .setModulusSizeBits(2048) 337 .setPublicExponent(RsaSsaPssParameters.F4) 338 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 339 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 340 .setVariant(null) 341 .build()); 342 } 343 344 @Test buildParametersWithExponentSetToNull_fails()345 public void buildParametersWithExponentSetToNull_fails() throws Exception { 346 assertThrows( 347 GeneralSecurityException.class, 348 () -> 349 RsaSsaPssParameters.builder() 350 .setModulusSizeBits(2048) 351 .setPublicExponent(null) 352 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 353 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 354 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 355 .build()); 356 } 357 358 @Test testEqualsAndEqualHashCode()359 public void testEqualsAndEqualHashCode() throws Exception { 360 RsaSsaPssParameters parameters1 = 361 RsaSsaPssParameters.builder() 362 .setModulusSizeBits(2048) 363 .setPublicExponent(RsaSsaPssParameters.F4) 364 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 365 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 366 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 367 .setSaltLengthBytes(32) 368 .build(); 369 RsaSsaPssParameters parameters2 = 370 RsaSsaPssParameters.builder() 371 .setModulusSizeBits(2048) 372 .setPublicExponent(RsaSsaPssParameters.F4) 373 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 374 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 375 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 376 .setSaltLengthBytes(32) 377 .build(); 378 379 assertThat(parameters1).isEqualTo(parameters2); 380 assertThat(parameters1.hashCode()).isEqualTo(parameters2.hashCode()); 381 } 382 383 @Test testNotEqual()384 public void testNotEqual() throws Exception { 385 RsaSsaPssParameters parameters = 386 RsaSsaPssParameters.builder() 387 .setModulusSizeBits(2048) 388 .setPublicExponent(RsaSsaPssParameters.F4) 389 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 390 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 391 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 392 .setSaltLengthBytes(32) 393 .build(); 394 assertThat(parameters) 395 .isNotEqualTo( 396 RsaSsaPssParameters.builder() 397 .setModulusSizeBits(2049) 398 .setPublicExponent(RsaSsaPssParameters.F4) 399 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 400 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 401 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 402 .setSaltLengthBytes(32) 403 .build()); 404 assertThat(parameters) 405 .isNotEqualTo( 406 RsaSsaPssParameters.builder() 407 .setModulusSizeBits(2048) 408 .setPublicExponent(BigInteger.valueOf(65539)) 409 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 410 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 411 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 412 .setSaltLengthBytes(32) 413 .build()); 414 assertThat(parameters) 415 .isNotEqualTo( 416 RsaSsaPssParameters.builder() 417 .setModulusSizeBits(2048) 418 .setPublicExponent(RsaSsaPssParameters.F4) 419 .setSigHashType(RsaSsaPssParameters.HashType.SHA384) 420 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA384) 421 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 422 .setSaltLengthBytes(32) 423 .build()); 424 assertThat(parameters) 425 .isNotEqualTo( 426 RsaSsaPssParameters.builder() 427 .setModulusSizeBits(2048) 428 .setPublicExponent(RsaSsaPssParameters.F4) 429 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 430 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 431 .setVariant(RsaSsaPssParameters.Variant.TINK) 432 .setSaltLengthBytes(32) 433 .build()); 434 assertThat(parameters) 435 .isNotEqualTo( 436 RsaSsaPssParameters.builder() 437 .setModulusSizeBits(2048) 438 .setPublicExponent(RsaSsaPssParameters.F4) 439 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 440 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 441 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 442 .setSaltLengthBytes(64) 443 .build()); 444 } 445 } 446