• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ////////////////////////////////////////////////////////////////////////////////
16 
17 package com.google.crypto.tink.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