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 com.google.crypto.tink.InsecureSecretKeyAccess; 23 import com.google.crypto.tink.internal.KeyTester; 24 import com.google.crypto.tink.subtle.Base64; 25 import com.google.crypto.tink.subtle.Hex; 26 import com.google.crypto.tink.util.Bytes; 27 import com.google.crypto.tink.util.SecretBigInteger; 28 import com.google.crypto.tink.util.SecretBytes; 29 import java.math.BigInteger; 30 import java.security.GeneralSecurityException; 31 import java.security.KeyFactory; 32 import java.security.KeyPair; 33 import java.security.KeyPairGenerator; 34 import java.security.interfaces.RSAPrivateCrtKey; 35 import java.security.interfaces.RSAPublicKey; 36 import java.security.spec.RSAKeyGenParameterSpec; 37 import java.security.spec.RSAPrivateCrtKeySpec; 38 import java.security.spec.RSAPublicKeySpec; 39 import org.junit.Test; 40 import org.junit.runner.RunWith; 41 import org.junit.runners.JUnit4; 42 43 @RunWith(JUnit4.class) 44 public final class RsaSsaPssPrivateKeyTest { 45 46 // Test vector from https://www.rfc-editor.org/rfc/rfc7517#appendix-C.1 47 static final BigInteger EXPONENT = new BigInteger(1, Base64.urlSafeDecode("AQAB")); 48 static final BigInteger MODULUS = 49 new BigInteger( 50 1, 51 Base64.urlSafeDecode( 52 "t6Q8PWSi1dkJj9hTP8hNYFlvadM7DflW9mWepOJhJ66w7nyoK1gPNqFMSQRy" 53 + "O125Gp-TEkodhWr0iujjHVx7BcV0llS4w5ACGgPrcAd6ZcSR0-Iqom-QFcNP" 54 + "8Sjg086MwoqQU_LYywlAGZ21WSdS_PERyGFiNnj3QQlO8Yns5jCtLCRwLHL0" 55 + "Pb1fEv45AuRIuUfVcPySBWYnDyGxvjYGDSM-AqWS9zIQ2ZilgT-GqUmipg0X" 56 + "OC0Cc20rgLe2ymLHjpHciCKVAbY5-L32-lSeZO-Os6U15_aXrk9Gw8cPUaX1" 57 + "_I8sLGuSiVdt3C_Fn2PZ3Z8i744FPFGGcG1qs2Wz-Q")); 58 static final BigInteger P = 59 new BigInteger( 60 1, 61 Base64.urlSafeDecode( 62 "2rnSOV4hKSN8sS4CgcQHFbs08XboFDqKum3sc4h3GRxrTmQdl1ZK9uw-PIHf" 63 + "QP0FkxXVrx-WE-ZEbrqivH_2iCLUS7wAl6XvARt1KkIaUxPPSYB9yk31s0Q8" 64 + "UK96E3_OrADAYtAJs-M3JxCLfNgqh56HDnETTQhH3rCT5T3yJws")); 65 static final BigInteger Q = 66 new BigInteger( 67 1, 68 Base64.urlSafeDecode( 69 "1u_RiFDP7LBYh3N4GXLT9OpSKYP0uQZyiaZwBtOCBNJgQxaj10RWjsZu0c6I" 70 + "edis4S7B_coSKB0Kj9PaPaBzg-IySRvvcQuPamQu66riMhjVtG6TlV8CLCYK" 71 + "rYl52ziqK0E_ym2QnkwsUX7eYTB7LbAHRK9GqocDE5B0f808I4s")); 72 static final BigInteger D = 73 new BigInteger( 74 1, 75 Base64.urlSafeDecode( 76 "GRtbIQmhOZtyszfgKdg4u_N-R_mZGU_9k7JQ_jn1DnfTuMdSNprTeaSTyWfS" 77 + "NkuaAwnOEbIQVy1IQbWVV25NY3ybc_IhUJtfri7bAXYEReWaCl3hdlPKXy9U" 78 + "vqPYGR0kIXTQRqns-dVJ7jahlI7LyckrpTmrM8dWBo4_PMaenNnPiQgO0xnu" 79 + "ToxutRZJfJvG4Ox4ka3GORQd9CsCZ2vsUDmsXOfUENOyMqADC6p1M3h33tsu" 80 + "rY15k9qMSpG9OX_IJAXmxzAh_tWiZOwk2K4yxH9tS3Lq1yX8C1EWmeRDkK2a" 81 + "hecG85-oLKQt5VEpWHKmjOi_gJSdSgqcN96X52esAQ")); 82 static final BigInteger DP = 83 new BigInteger( 84 1, 85 Base64.urlSafeDecode( 86 "KkMTWqBUefVwZ2_Dbj1pPQqyHSHjj90L5x_MOzqYAJMcLMZtbUtwKqvVDq3" 87 + "tbEo3ZIcohbDtt6SbfmWzggabpQxNxuBpoOOf_a_HgMXK_lhqigI4y_kqS1w" 88 + "Y52IwjUn5rgRrJ-yYo1h41KR-vz2pYhEAeYrhttWtxVqLCRViD6c")); 89 static final BigInteger DQ = 90 new BigInteger( 91 1, 92 Base64.urlSafeDecode( 93 "AvfS0-gRxvn0bwJoMSnFxYcK1WnuEjQFluMGfwGitQBWtfZ1Er7t1xDkbN9" 94 + "GQTB9yqpDoYaN06H7CFtrkxhJIBQaj6nkF5KKS3TQtQ5qCzkOkmxIe3KRbBy" 95 + "mXxkb5qwUpX5ELD5xFc6FeiafWYY63TmmEAu_lRFCOJ3xDea-ots")); 96 static final BigInteger Q_INV = 97 new BigInteger( 98 1, 99 Base64.urlSafeDecode( 100 "lSQi-w9CpyUReMErP1RsBLk7wNtOvs5EQpPqmuMvqW57NBUczScEoPwmUqq" 101 + "abu9V0-Py4dQ57_bapoKRu1R90bvuFnU63SHWEFglZQvJDMeAvmj4sm-Fp0o" 102 + "Yu_neotgQ0hzbI5gry7ajdYy9-2lNx_76aBZoOUu9HCJ-UsfSOI8")); 103 104 @Test buildNoPrefixVariantAndGetProperties()105 public void buildNoPrefixVariantAndGetProperties() throws Exception { 106 RsaSsaPssParameters parameters = 107 RsaSsaPssParameters.builder() 108 .setModulusSizeBits(2048) 109 .setPublicExponent(EXPONENT) 110 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 111 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 112 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 113 .setSaltLengthBytes(32) 114 .build(); 115 assertThat(parameters.hasIdRequirement()).isFalse(); 116 RsaSsaPssPublicKey publicKey = 117 RsaSsaPssPublicKey.builder().setParameters(parameters).setModulus(MODULUS).build(); 118 RsaSsaPssPrivateKey privateKey = 119 RsaSsaPssPrivateKey.builder() 120 .setPublicKey(publicKey) 121 .setPrimes( 122 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 123 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 124 .setPrivateExponent(SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get())) 125 .setPrimeExponents( 126 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 127 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 128 .setCrtCoefficient( 129 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 130 .build(); 131 assertThat(privateKey.getParameters()).isEqualTo(parameters); 132 assertThat(privateKey.getPublicKey()).isEqualTo(publicKey); 133 assertThat(privateKey.getPrimeP().getBigInteger(InsecureSecretKeyAccess.get())).isEqualTo(P); 134 assertThat(privateKey.getPrimeQ().getBigInteger(InsecureSecretKeyAccess.get())).isEqualTo(Q); 135 assertThat(privateKey.getOutputPrefix()).isEqualTo(Bytes.copyFrom(new byte[] {})); 136 assertThat(privateKey.getIdRequirementOrNull()).isNull(); 137 } 138 139 @Test buildTinkVariantAndGetProperties()140 public void buildTinkVariantAndGetProperties() throws Exception { 141 RsaSsaPssParameters parameters = 142 RsaSsaPssParameters.builder() 143 .setModulusSizeBits(2048) 144 .setPublicExponent(EXPONENT) 145 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 146 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 147 .setVariant(RsaSsaPssParameters.Variant.TINK) 148 .setSaltLengthBytes(32) 149 .build(); 150 assertThat(parameters.hasIdRequirement()).isTrue(); 151 RsaSsaPssPublicKey publicKey = 152 RsaSsaPssPublicKey.builder() 153 .setParameters(parameters) 154 .setModulus(MODULUS) 155 .setIdRequirement(0x66AABBCC) 156 .build(); 157 RsaSsaPssPrivateKey privateKey = 158 RsaSsaPssPrivateKey.builder() 159 .setPublicKey(publicKey) 160 .setPrimes( 161 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 162 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 163 .setPrivateExponent(SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get())) 164 .setPrimeExponents( 165 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 166 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 167 .setCrtCoefficient( 168 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 169 .build(); 170 assertThat(privateKey.getParameters()).isEqualTo(parameters); 171 assertThat(privateKey.getPublicKey()).isEqualTo(publicKey); 172 assertThat(privateKey.getPrimeP().getBigInteger(InsecureSecretKeyAccess.get())).isEqualTo(P); 173 assertThat(privateKey.getPrimeQ().getBigInteger(InsecureSecretKeyAccess.get())).isEqualTo(Q); 174 assertThat(privateKey.getOutputPrefix()).isEqualTo(Bytes.copyFrom(Hex.decode("0166AABBCC"))); 175 assertThat(privateKey.getIdRequirementOrNull()).isEqualTo(0x66AABBCC); 176 } 177 178 @Test notAllValuesSet_throws()179 public void notAllValuesSet_throws() throws Exception { 180 RsaSsaPssParameters parameters = 181 RsaSsaPssParameters.builder() 182 .setModulusSizeBits(2048) 183 .setPublicExponent(EXPONENT) 184 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 185 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 186 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 187 .setSaltLengthBytes(32) 188 .build(); 189 RsaSsaPssPublicKey publicKey = 190 RsaSsaPssPublicKey.builder().setParameters(parameters).setModulus(MODULUS).build(); 191 192 assertThrows( 193 GeneralSecurityException.class, 194 () -> 195 RsaSsaPssPrivateKey.builder() 196 .setPrimes( 197 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 198 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 199 .setPrivateExponent( 200 SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get())) 201 .setPrimeExponents( 202 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 203 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 204 .setCrtCoefficient( 205 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 206 .build()); 207 assertThrows( 208 GeneralSecurityException.class, 209 () -> 210 RsaSsaPssPrivateKey.builder() 211 .setPublicKey(publicKey) 212 .setPrivateExponent( 213 SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get())) 214 .setPrimeExponents( 215 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 216 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 217 .setCrtCoefficient( 218 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 219 .build()); 220 assertThrows( 221 GeneralSecurityException.class, 222 () -> 223 RsaSsaPssPrivateKey.builder() 224 .setPublicKey(publicKey) 225 .setPrimes( 226 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 227 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 228 .setPrimeExponents( 229 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 230 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 231 .setCrtCoefficient( 232 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 233 .build()); 234 assertThrows( 235 GeneralSecurityException.class, 236 () -> 237 RsaSsaPssPrivateKey.builder() 238 .setPublicKey(publicKey) 239 .setPrimes( 240 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 241 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 242 .setPrivateExponent( 243 SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get())) 244 .setCrtCoefficient( 245 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 246 .build()); 247 assertThrows( 248 GeneralSecurityException.class, 249 () -> 250 RsaSsaPssPrivateKey.builder() 251 .setPublicKey(publicKey) 252 .setPrimes( 253 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 254 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 255 .setPrivateExponent( 256 SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get())) 257 .setPrimeExponents( 258 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 259 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 260 .build()); 261 } 262 263 @Test valuesSetToNull_throws()264 public void valuesSetToNull_throws() throws Exception { 265 RsaSsaPssParameters parameters = 266 RsaSsaPssParameters.builder() 267 .setModulusSizeBits(2048) 268 .setPublicExponent(EXPONENT) 269 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 270 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 271 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 272 .setSaltLengthBytes(32) 273 .build(); 274 RsaSsaPssPublicKey publicKey = 275 RsaSsaPssPublicKey.builder().setParameters(parameters).setModulus(MODULUS).build(); 276 277 assertThrows( 278 GeneralSecurityException.class, 279 () -> 280 RsaSsaPssPrivateKey.builder() 281 .setPublicKey(null) 282 .setPrimes( 283 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 284 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 285 .setPrivateExponent( 286 SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get())) 287 .setPrimeExponents( 288 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 289 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 290 .setCrtCoefficient( 291 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 292 .build()); 293 assertThrows( 294 GeneralSecurityException.class, 295 () -> 296 RsaSsaPssPrivateKey.builder() 297 .setPublicKey(publicKey) 298 .setPrimes(SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), null) 299 .setPrivateExponent( 300 SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get())) 301 .setPrimeExponents( 302 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 303 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 304 .setCrtCoefficient( 305 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 306 .build()); 307 assertThrows( 308 GeneralSecurityException.class, 309 () -> 310 RsaSsaPssPrivateKey.builder() 311 .setPublicKey(publicKey) 312 .setPrimes( 313 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 314 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 315 .setPrivateExponent(null) 316 .setPrimeExponents( 317 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 318 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 319 .setCrtCoefficient( 320 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 321 .build()); 322 assertThrows( 323 GeneralSecurityException.class, 324 () -> 325 RsaSsaPssPrivateKey.builder() 326 .setPublicKey(publicKey) 327 .setPrimes( 328 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 329 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 330 .setPrivateExponent( 331 SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get())) 332 .setPrimeExponents( 333 null, SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 334 .setCrtCoefficient( 335 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 336 .build()); 337 assertThrows( 338 GeneralSecurityException.class, 339 () -> 340 RsaSsaPssPrivateKey.builder() 341 .setPublicKey(publicKey) 342 .setPrimes( 343 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 344 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 345 .setPrivateExponent( 346 SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get())) 347 .setPrimeExponents( 348 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 349 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 350 .setCrtCoefficient(null) 351 .build()); 352 } 353 354 @Test buildFrom2048BitPrivateKeyGeneratedOnAndroidPhone()355 public void buildFrom2048BitPrivateKeyGeneratedOnAndroidPhone() throws Exception { 356 // This key pairs was generated on an android phone. 357 // It satisfies e * d = 1 mod LCM(p-1, q-1), but e * d != 1 mod (p-1)(q-1). 358 BigInteger modulus = 359 new BigInteger( 360 "b3795dceabcbd81fc437fd1bef3f441fb3e795e0def5dcb6c84d1136f1f5c552bcb549fc925a0bd84fba5014565a46e89c1b0f198323ddd6c74931eef6551414651d224965e880136a1ef0f58145aa1d801cf9abe8afcd79d18b71e992a440dac72e020622d707e39ef02422b3b5b60eee19e39262bef2c83384370d5af82208c905341cf3445357ebed8534e5d09e7e3faab0029eb72c4d67b784023dc3853601f46d8a76640c0cb70e32a7e1a915f64418b9872f90639e07c9c58cb6da7138ec00edceb95871f25b6d58541df81a05c20336ecb03d68f118e758fc8399c5afa965de8b3e6e2cffe05368c0c2e8f8d7651bc0595c315ad5ffc5e9181226a5d5", 361 16); 362 BigInteger e = new BigInteger("65537", 10); 363 BigInteger d = 364 new BigInteger( 365 "3221514782158521239046688407258406330028553231891834758638194651218489349712866325521438421714836367531316613927931498512071990193965798572643232627837201196644319517052327671563822639251731918047441576305607916660284178027387674162132050160094809919355636813793351064368082273962217034909172344404581974193241939373282144264114913662260588365672363893632683074989847367188654224412555194872230331733391324889200933302437700487142724975686901108577545454632839147323098141162449990768306604007013959695761622579370899486808808004842820432382650026507647986123784123174922931280866259315314620233905351359011687391313", 366 10); 367 BigInteger p = 368 new BigInteger( 369 "158774943353490113489753012135278111098541279368787638170427666092698662171983127156976037521575652098385551704113475827318417186165950163951987243985985522595184323477005539699476104661027759513072140468348507403972716866975866335912344241205454260491734974839813729609658331285715361068926273165265719385439", 370 10); 371 BigInteger q = 372 new BigInteger( 373 "142695718417290075651435513804876109623436685476916701891113040095977093917632889732962474426931910603260254832314306994757612331416172717945809235744856009131743301134864401372069413649983267047705657073804311818666915219978411279698814772814372316278090214109479349638211641740638165276131916195227128960331", 374 10); 375 BigInteger dp = 376 new BigInteger( 377 "54757332036492112014516953480958174268721943273163834138395198270094376648475863100263551887676471134286132102726288671270440594499638457751236945367826491626048737037509791541992445756573377184101446798993133105644007913505173122423833934109368405566843064243548986322802349874418093456823956331253120978221", 378 10); 379 BigInteger dq = 380 new BigInteger( 381 "4123864239778253555759629875435789731400416288406247362280362206719572392388981692085858775418603822002455447341246890276804213737312222527570116003185334716198816124470652855618955238309173562847773234932715360552895882122146435811061769377762503120843231541317940830596042685151421106138423322302824087933", 382 10); 383 BigInteger crt = 384 new BigInteger( 385 "43369284071361709125656993969231593842392884522437628906059039642593092160995429320609799019215633408868044592180219813214250943675517000006014828230986217788818608645218728222984926523616075543476651226972790298584420864753413872673062587182578776079528269917000933056174453680725934830997227408181738889955", 386 10); 387 RsaSsaPssParameters parameters = 388 RsaSsaPssParameters.builder() 389 .setModulusSizeBits(2048) 390 .setPublicExponent(e) 391 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 392 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 393 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 394 .setSaltLengthBytes(32) 395 .build(); 396 RsaSsaPssPublicKey publicKey = 397 RsaSsaPssPublicKey.builder().setParameters(parameters).setModulus(modulus).build(); 398 399 RsaSsaPssPrivateKey privateKey = 400 RsaSsaPssPrivateKey.builder() 401 .setPublicKey(publicKey) 402 .setPrimes( 403 SecretBigInteger.fromBigInteger(p, InsecureSecretKeyAccess.get()), 404 SecretBigInteger.fromBigInteger(q, InsecureSecretKeyAccess.get())) 405 .setPrivateExponent(SecretBigInteger.fromBigInteger(d, InsecureSecretKeyAccess.get())) 406 .setPrimeExponents( 407 SecretBigInteger.fromBigInteger(dp, InsecureSecretKeyAccess.get()), 408 SecretBigInteger.fromBigInteger(dq, InsecureSecretKeyAccess.get())) 409 .setCrtCoefficient(SecretBigInteger.fromBigInteger(crt, InsecureSecretKeyAccess.get())) 410 .build(); 411 assertThat(privateKey).isNotNull(); 412 } 413 414 @Test buildFromJavaRSAKeys()415 public void buildFromJavaRSAKeys() throws Exception { 416 // Create a new RSA key pair using Java's KeyPairGenerator, which gives us a 417 // RSAPublicKey and a RSAPrivateCrtKey. 418 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); 419 RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(2048, EXPONENT); 420 keyGen.initialize(spec); 421 KeyPair keyPair = keyGen.generateKeyPair(); 422 RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic(); 423 RSAPrivateCrtKey privKey = (RSAPrivateCrtKey) keyPair.getPrivate(); 424 425 // Build a RsaSsaPssPublicKey from a RSAPublicKey. 426 int pubKeyModulusSizeBits = pubKey.getModulus().bitLength(); 427 assertThat(pubKeyModulusSizeBits).isEqualTo(2048); 428 RsaSsaPssPublicKey publicKey = 429 RsaSsaPssPublicKey.builder() 430 .setParameters( 431 RsaSsaPssParameters.builder() 432 .setModulusSizeBits(pubKeyModulusSizeBits) 433 .setPublicExponent(pubKey.getPublicExponent()) 434 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 435 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 436 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 437 .setSaltLengthBytes(32) 438 .build()) 439 .setModulus(pubKey.getModulus()) 440 .build(); 441 442 // Build a RsaSsaPssPrivateKey from a RsaSsaPssPublicKey and a RSAPrivateCrtKey. 443 RsaSsaPssPrivateKey privateKey = 444 RsaSsaPssPrivateKey.builder() 445 .setPublicKey(publicKey) 446 .setPrimes( 447 SecretBigInteger.fromBigInteger(privKey.getPrimeP(), InsecureSecretKeyAccess.get()), 448 SecretBigInteger.fromBigInteger(privKey.getPrimeQ(), InsecureSecretKeyAccess.get())) 449 .setPrivateExponent( 450 SecretBigInteger.fromBigInteger( 451 privKey.getPrivateExponent(), InsecureSecretKeyAccess.get())) 452 .setPrimeExponents( 453 SecretBigInteger.fromBigInteger( 454 privKey.getPrimeExponentP(), InsecureSecretKeyAccess.get()), 455 SecretBigInteger.fromBigInteger( 456 privKey.getPrimeExponentQ(), InsecureSecretKeyAccess.get())) 457 .setCrtCoefficient( 458 SecretBigInteger.fromBigInteger( 459 privKey.getCrtCoefficient(), InsecureSecretKeyAccess.get())) 460 .build(); 461 462 // Build a RsaSsaPssPrivateKey from a RSAPrivateCrtKey, without a RSAPublicKey. 463 int privKeyModulusSizeBits = privKey.getModulus().bitLength(); 464 assertThat(privKeyModulusSizeBits).isEqualTo(2048); 465 RsaSsaPssPrivateKey privateKey2 = 466 RsaSsaPssPrivateKey.builder() 467 .setPublicKey( 468 RsaSsaPssPublicKey.builder() 469 .setParameters( 470 RsaSsaPssParameters.builder() 471 .setModulusSizeBits(privKeyModulusSizeBits) 472 .setPublicExponent(privKey.getPublicExponent()) 473 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 474 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 475 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 476 .setSaltLengthBytes(32) 477 .build()) 478 .setModulus(privKey.getModulus()) 479 .build()) 480 .setPrimes( 481 SecretBigInteger.fromBigInteger(privKey.getPrimeP(), InsecureSecretKeyAccess.get()), 482 SecretBigInteger.fromBigInteger(privKey.getPrimeQ(), InsecureSecretKeyAccess.get())) 483 .setPrivateExponent( 484 SecretBigInteger.fromBigInteger( 485 privKey.getPrivateExponent(), InsecureSecretKeyAccess.get())) 486 .setPrimeExponents( 487 SecretBigInteger.fromBigInteger( 488 privKey.getPrimeExponentP(), InsecureSecretKeyAccess.get()), 489 SecretBigInteger.fromBigInteger( 490 privKey.getPrimeExponentQ(), InsecureSecretKeyAccess.get())) 491 .setCrtCoefficient( 492 SecretBigInteger.fromBigInteger( 493 privKey.getCrtCoefficient(), InsecureSecretKeyAccess.get())) 494 .build(); 495 assertThat(privateKey.equalsKey(privateKey2)).isTrue(); 496 497 KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 498 499 // Convert RsaSsaPssPublicKey back into a RSAPublicKey. 500 RSAPublicKey pubKey2 = 501 (RSAPublicKey) 502 keyFactory.generatePublic( 503 new RSAPublicKeySpec( 504 publicKey.getModulus(), publicKey.getParameters().getPublicExponent())); 505 assertThat(pubKey2.getModulus()).isEqualTo(pubKey.getModulus()); 506 assertThat(pubKey2.getPublicExponent()).isEqualTo(pubKey.getPublicExponent()); 507 508 // Convert RsaSsaPssPrivateKey back into a RSAPrivateCrtKey. 509 BigInteger e = privateKey.getPublicKey().getParameters().getPublicExponent(); 510 BigInteger n = privateKey.getPublicKey().getModulus(); 511 BigInteger p = privateKey.getPrimeP().getBigInteger(InsecureSecretKeyAccess.get()); 512 BigInteger q = privateKey.getPrimeQ().getBigInteger(InsecureSecretKeyAccess.get()); 513 BigInteger d = privateKey.getPrivateExponent().getBigInteger(InsecureSecretKeyAccess.get()); 514 BigInteger dp = privateKey.getPrimeExponentP().getBigInteger(InsecureSecretKeyAccess.get()); 515 BigInteger dq = privateKey.getPrimeExponentQ().getBigInteger(InsecureSecretKeyAccess.get()); 516 BigInteger crt = privateKey.getCrtCoefficient().getBigInteger(InsecureSecretKeyAccess.get()); 517 RSAPrivateCrtKey privKey2 = 518 (RSAPrivateCrtKey) 519 keyFactory.generatePrivate(new RSAPrivateCrtKeySpec(n, e, d, p, q, dp, dq, crt)); 520 assertThat(privKey2.getPrivateExponent()).isEqualTo(privKey.getPrivateExponent()); 521 assertThat(privKey2.getPrimeExponentP()).isEqualTo(privKey.getPrimeExponentP()); 522 assertThat(privKey2.getPrimeExponentQ()).isEqualTo(privKey.getPrimeExponentQ()); 523 assertThat(privKey2.getCrtCoefficient()).isEqualTo(privKey.getCrtCoefficient()); 524 } 525 526 @Test emptyBuild_fails()527 public void emptyBuild_fails() throws Exception { 528 assertThrows(GeneralSecurityException.class, () -> RsaSsaPssPrivateKey.builder().build()); 529 } 530 531 @Test buildValidatesAllValues()532 public void buildValidatesAllValues() throws Exception { 533 RsaSsaPssParameters parameters = 534 RsaSsaPssParameters.builder() 535 .setModulusSizeBits(2048) 536 .setPublicExponent(EXPONENT) 537 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 538 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 539 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 540 .setSaltLengthBytes(32) 541 .build(); 542 // Check that build fails if any value is increased by 1. 543 assertThrows( 544 GeneralSecurityException.class, 545 () -> 546 RsaSsaPssPrivateKey.builder() 547 .setPublicKey( 548 RsaSsaPssPublicKey.builder() 549 .setParameters(parameters) 550 .setModulus(MODULUS.add(BigInteger.ONE)) // modulus is one off 551 .build()) 552 .setPrimes( 553 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 554 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 555 .setPrimeExponents( 556 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 557 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 558 .setCrtCoefficient( 559 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 560 .build()); 561 assertThrows( 562 GeneralSecurityException.class, 563 () -> 564 RsaSsaPssPrivateKey.builder() 565 .setPublicKey( 566 RsaSsaPssPublicKey.builder() 567 .setParameters(parameters) 568 .setModulus(MODULUS) 569 .build()) 570 .setPrimes( 571 SecretBigInteger.fromBigInteger( 572 P.add(BigInteger.ONE), InsecureSecretKeyAccess.get()), 573 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 574 .setPrimeExponents( 575 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 576 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 577 .setCrtCoefficient( 578 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 579 .build()); 580 assertThrows( 581 GeneralSecurityException.class, 582 () -> 583 RsaSsaPssPrivateKey.builder() 584 .setPublicKey( 585 RsaSsaPssPublicKey.builder() 586 .setParameters(parameters) 587 .setModulus(MODULUS) 588 .build()) 589 .setPrimes( 590 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 591 SecretBigInteger.fromBigInteger( 592 Q.add(BigInteger.ONE), InsecureSecretKeyAccess.get())) 593 .setPrimeExponents( 594 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 595 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 596 .setCrtCoefficient( 597 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 598 .build()); 599 assertThrows( 600 GeneralSecurityException.class, 601 () -> 602 RsaSsaPssPrivateKey.builder() 603 .setPublicKey( 604 RsaSsaPssPublicKey.builder() 605 .setParameters(parameters) 606 .setModulus(MODULUS) 607 .build()) 608 .setPrimes( 609 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 610 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 611 .setPrimeExponents( 612 SecretBigInteger.fromBigInteger( 613 DP.add(BigInteger.ONE), InsecureSecretKeyAccess.get()), 614 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 615 .setCrtCoefficient( 616 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 617 .build()); 618 assertThrows( 619 GeneralSecurityException.class, 620 () -> 621 RsaSsaPssPrivateKey.builder() 622 .setPublicKey( 623 RsaSsaPssPublicKey.builder() 624 .setParameters(parameters) 625 .setModulus(MODULUS) 626 .build()) 627 .setPrimes( 628 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 629 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 630 .setPrimeExponents( 631 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 632 SecretBigInteger.fromBigInteger( 633 DQ.add(BigInteger.ONE), InsecureSecretKeyAccess.get())) 634 .setCrtCoefficient( 635 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 636 .build()); 637 assertThrows( 638 GeneralSecurityException.class, 639 () -> 640 RsaSsaPssPrivateKey.builder() 641 .setPublicKey( 642 RsaSsaPssPublicKey.builder() 643 .setParameters(parameters) 644 .setModulus(MODULUS) 645 .build()) 646 .setPrimes( 647 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 648 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 649 .setPrimeExponents( 650 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 651 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 652 .setCrtCoefficient( 653 SecretBigInteger.fromBigInteger( 654 Q_INV.add(BigInteger.ONE), InsecureSecretKeyAccess.get())) 655 .build()); 656 } 657 658 @Test testEqualities()659 public void testEqualities() throws Exception { 660 RsaSsaPssParameters noPrefixParameters = 661 RsaSsaPssParameters.builder() 662 .setModulusSizeBits(2048) 663 .setPublicExponent(EXPONENT) 664 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 665 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 666 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 667 .setSaltLengthBytes(32) 668 .build(); 669 RsaSsaPssPublicKey noPrefixPublicKey = 670 RsaSsaPssPublicKey.builder().setParameters(noPrefixParameters).setModulus(MODULUS).build(); 671 672 RsaSsaPssParameters noPrefixParametersWithSha512 = 673 RsaSsaPssParameters.builder() 674 .setModulusSizeBits(2048) 675 .setPublicExponent(EXPONENT) 676 .setSigHashType(RsaSsaPssParameters.HashType.SHA512) 677 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA512) 678 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 679 .setSaltLengthBytes(32) 680 .build(); 681 682 RsaSsaPssParameters tinkPrefixParameters = 683 RsaSsaPssParameters.builder() 684 .setModulusSizeBits(2048) 685 .setPublicExponent(EXPONENT) 686 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 687 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 688 .setVariant(RsaSsaPssParameters.Variant.TINK) 689 .setSaltLengthBytes(32) 690 .build(); 691 RsaSsaPssPublicKey tinkPrefixPublicKey = 692 RsaSsaPssPublicKey.builder() 693 .setParameters(tinkPrefixParameters) 694 .setModulus(MODULUS) 695 .setIdRequirement(1907) 696 .build(); 697 698 // d2 = d + (p-1)(q-1) is also a valid d, yet if we change d to d2 the Key will be considered 699 // different. 700 BigInteger d2 = D.add(P.subtract(BigInteger.ONE).multiply(Q.subtract(BigInteger.ONE))); 701 702 Ed25519PublicKey ed25519PublicKey = 703 Ed25519PublicKey.create( 704 Bytes.copyFrom( 705 Hex.decode("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"))); 706 Ed25519PrivateKey ed25519PrivateKey = 707 Ed25519PrivateKey.create( 708 ed25519PublicKey, 709 SecretBytes.copyFrom( 710 Hex.decode("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"), 711 InsecureSecretKeyAccess.get())); 712 713 new KeyTester() 714 .addEqualityGroup( 715 "Unmodified", 716 RsaSsaPssPrivateKey.builder() 717 .setPublicKey(noPrefixPublicKey) 718 .setPrimes( 719 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 720 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 721 .setPrivateExponent( 722 SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get())) 723 .setPrimeExponents( 724 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 725 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 726 .setCrtCoefficient( 727 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 728 .build(), 729 // the same key built twice must be equal 730 RsaSsaPssPrivateKey.builder() 731 .setPublicKey( 732 RsaSsaPssPublicKey.builder() 733 .setParameters( 734 RsaSsaPssParameters.builder() 735 .setModulusSizeBits(2048) 736 .setPublicExponent(EXPONENT) 737 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 738 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 739 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 740 .setSaltLengthBytes(32) 741 .build()) 742 .setModulus(MODULUS) 743 .build()) 744 .setPrimes( 745 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 746 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 747 .setPrivateExponent( 748 SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get())) 749 .setPrimeExponents( 750 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 751 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 752 .setCrtCoefficient( 753 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 754 .build()) 755 // This group checks that a private key where p and q are swapped is considered different 756 .addEqualityGroup( 757 "p and q swapped", 758 RsaSsaPssPrivateKey.builder() 759 .setPublicKey(noPrefixPublicKey) 760 .setPrimes( 761 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get()), 762 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get())) 763 .setPrivateExponent( 764 SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get())) 765 .setPrimeExponents( 766 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get()), 767 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get())) 768 .setCrtCoefficient( 769 SecretBigInteger.fromBigInteger(P.modInverse(Q), InsecureSecretKeyAccess.get())) 770 .build()) 771 // Different d is considered a different key. 772 .addEqualityGroup( 773 "Different d", 774 RsaSsaPssPrivateKey.builder() 775 .setPublicKey(noPrefixPublicKey) 776 .setPrimes( 777 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 778 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 779 .setPrivateExponent( 780 SecretBigInteger.fromBigInteger(d2, InsecureSecretKeyAccess.get())) 781 .setPrimeExponents( 782 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 783 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 784 .setCrtCoefficient( 785 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 786 .build()) 787 // This group checks that keys with different parameters are not equal 788 .addEqualityGroup( 789 "SHA512", 790 RsaSsaPssPrivateKey.builder() 791 .setPublicKey( 792 RsaSsaPssPublicKey.builder() 793 .setParameters(noPrefixParametersWithSha512) 794 .setModulus(MODULUS) 795 .build()) 796 .setPrimes( 797 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 798 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 799 .setPrivateExponent( 800 SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get())) 801 .setPrimeExponents( 802 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 803 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 804 .setCrtCoefficient( 805 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 806 .build()) 807 .addEqualityGroup( 808 "Tink Prefix", 809 RsaSsaPssPrivateKey.builder() 810 .setPublicKey(tinkPrefixPublicKey) 811 .setPrimes( 812 SecretBigInteger.fromBigInteger(P, InsecureSecretKeyAccess.get()), 813 SecretBigInteger.fromBigInteger(Q, InsecureSecretKeyAccess.get())) 814 .setPrivateExponent( 815 SecretBigInteger.fromBigInteger(D, InsecureSecretKeyAccess.get())) 816 .setPrimeExponents( 817 SecretBigInteger.fromBigInteger(DP, InsecureSecretKeyAccess.get()), 818 SecretBigInteger.fromBigInteger(DQ, InsecureSecretKeyAccess.get())) 819 .setCrtCoefficient( 820 SecretBigInteger.fromBigInteger(Q_INV, InsecureSecretKeyAccess.get())) 821 .build()) 822 .addEqualityGroup("Other key type", ed25519PrivateKey) 823 .doTests(); 824 } 825 } 826