• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 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.internal.KeyTester;
23 import com.google.crypto.tink.subtle.Hex;
24 import com.google.crypto.tink.util.Bytes;
25 import java.math.BigInteger;
26 import java.security.GeneralSecurityException;
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
29 import org.junit.runners.JUnit4;
30 
31 @RunWith(JUnit4.class)
32 public final class RsaSsaPkcs1PublicKeyTest {
33 
34   // Test vector from
35   // https://github.com/google/wycheproof/blob/master/testvectors/rsa_pkcs1_2048_test.json
36   static final BigInteger MODULUS =
37       new BigInteger(
38           "00b3510a2bcd4ce644c5b594ae5059e12b2f054b658d5da5959a2fdf1871b808bc3df3e628d2792e51aad5c1"
39               + "24b43bda453dca5cde4bcf28e7bd4effba0cb4b742bbb6d5a013cb63d1aa3a89e02627ef5398b52c0c"
40               + "fd97d208abeb8d7c9bce0bbeb019a86ddb589beb29a5b74bf861075c677c81d430f030c265247af9d3"
41               + "c9140ccb65309d07e0adc1efd15cf17e7b055d7da3868e4648cc3a180f0ee7f8e1e7b18098a3391b4c"
42               + "e7161e98d57af8a947e201a463e2d6bbca8059e5706e9dfed8f4856465ffa712ed1aa18e888d12dc6a"
43               + "a09ce95ecfca83cc5b0b15db09c8647f5d524c0f2e7620a3416b9623cadc0f097af573261c98c8400a"
44               + "a12af38e43cad84d",
45           16);
46   static final BigInteger EXPONENT = BigInteger.valueOf(65537);
47 
48   @Test
buildNoPrefixVariantAndGetProperties()49   public void buildNoPrefixVariantAndGetProperties() throws Exception {
50     RsaSsaPkcs1Parameters parameters =
51         RsaSsaPkcs1Parameters.builder()
52             .setModulusSizeBits(2048)
53             .setPublicExponent(EXPONENT)
54             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
55             .setVariant(RsaSsaPkcs1Parameters.Variant.NO_PREFIX)
56             .build();
57     assertThat(parameters.hasIdRequirement()).isFalse();
58     RsaSsaPkcs1PublicKey key =
59         RsaSsaPkcs1PublicKey.builder().setParameters(parameters).setModulus(MODULUS).build();
60     assertThat(key.getParameters()).isEqualTo(parameters);
61     assertThat(key.getModulus()).isEqualTo(MODULUS);
62     assertThat(key.getOutputPrefix()).isEqualTo(Bytes.copyFrom(new byte[] {}));
63     assertThat(key.getIdRequirementOrNull()).isNull();
64   }
65 
66   @Test
buildTinkVariantAndGetProperties()67   public void buildTinkVariantAndGetProperties() throws Exception {
68     RsaSsaPkcs1Parameters parameters =
69         RsaSsaPkcs1Parameters.builder()
70             .setModulusSizeBits(2048)
71             .setPublicExponent(EXPONENT)
72             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
73             .setVariant(RsaSsaPkcs1Parameters.Variant.TINK)
74             .build();
75     assertThat(parameters.hasIdRequirement()).isTrue();
76     RsaSsaPkcs1PublicKey key =
77         RsaSsaPkcs1PublicKey.builder()
78             .setParameters(parameters)
79             .setModulus(MODULUS)
80             .setIdRequirement(0x66AABBCC)
81             .build();
82     assertThat(key.getParameters()).isEqualTo(parameters);
83     assertThat(key.getModulus()).isEqualTo(MODULUS);
84     assertThat(key.getOutputPrefix()).isEqualTo(Bytes.copyFrom(Hex.decode("0166AABBCC")));
85     assertThat(key.getIdRequirementOrNull()).isEqualTo(0x66AABBCC);
86   }
87 
88   @Test
buildLegacyVariantAndGetProperties()89   public void buildLegacyVariantAndGetProperties() throws Exception {
90     RsaSsaPkcs1Parameters parameters =
91         RsaSsaPkcs1Parameters.builder()
92             .setModulusSizeBits(2048)
93             .setPublicExponent(EXPONENT)
94             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
95             .setVariant(RsaSsaPkcs1Parameters.Variant.LEGACY)
96             .build();
97     assertThat(parameters.hasIdRequirement()).isTrue();
98     RsaSsaPkcs1PublicKey key =
99         RsaSsaPkcs1PublicKey.builder()
100             .setParameters(parameters)
101             .setModulus(MODULUS)
102             .setIdRequirement(0x66AABBCC)
103             .build();
104     assertThat(key.getParameters()).isEqualTo(parameters);
105     assertThat(key.getModulus()).isEqualTo(MODULUS);
106     assertThat(key.getOutputPrefix()).isEqualTo(Bytes.copyFrom(Hex.decode("0066AABBCC")));
107     assertThat(key.getIdRequirementOrNull()).isEqualTo(0x66AABBCC);
108   }
109 
110   @Test
buildCrunchyVariantAndGetProperties()111   public void buildCrunchyVariantAndGetProperties() throws Exception {
112     RsaSsaPkcs1Parameters parameters =
113         RsaSsaPkcs1Parameters.builder()
114             .setModulusSizeBits(2048)
115             .setPublicExponent(EXPONENT)
116             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
117             .setVariant(RsaSsaPkcs1Parameters.Variant.CRUNCHY)
118             .build();
119     assertThat(parameters.hasIdRequirement()).isTrue();
120     RsaSsaPkcs1PublicKey key =
121         RsaSsaPkcs1PublicKey.builder()
122             .setParameters(parameters)
123             .setModulus(MODULUS)
124             .setIdRequirement(0x66AABBCC)
125             .build();
126     assertThat(key.getParameters()).isEqualTo(parameters);
127     assertThat(key.getModulus()).isEqualTo(MODULUS);
128     assertThat(key.getOutputPrefix()).isEqualTo(Bytes.copyFrom(Hex.decode("0066AABBCC")));
129     assertThat(key.getIdRequirementOrNull()).isEqualTo(0x66AABBCC);
130   }
131 
132   @Test
emptyBuild_fails()133   public void emptyBuild_fails() throws Exception {
134     assertThrows(GeneralSecurityException.class, () -> RsaSsaPkcs1PublicKey.builder().build());
135   }
136 
137   @Test
buildWithoutParameters_fails()138   public void buildWithoutParameters_fails() throws Exception {
139     assertThrows(
140         GeneralSecurityException.class,
141         () -> RsaSsaPkcs1PublicKey.builder().setModulus(MODULUS).build());
142   }
143 
144   @Test
buildWithoutModulus_fails()145   public void buildWithoutModulus_fails() throws Exception {
146     RsaSsaPkcs1Parameters parameters =
147         RsaSsaPkcs1Parameters.builder()
148             .setModulusSizeBits(2048)
149             .setPublicExponent(EXPONENT)
150             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
151             .setVariant(RsaSsaPkcs1Parameters.Variant.NO_PREFIX)
152             .build();
153     assertThrows(
154         GeneralSecurityException.class,
155         () -> RsaSsaPkcs1PublicKey.builder().setParameters(parameters).build());
156   }
157 
158   @Test
parametersRequireIdButIdIsNotSetInBuild_fails()159   public void parametersRequireIdButIdIsNotSetInBuild_fails() throws Exception {
160     RsaSsaPkcs1Parameters parametersWithIdRequirement =
161         RsaSsaPkcs1Parameters.builder()
162             .setModulusSizeBits(2048)
163             .setPublicExponent(EXPONENT)
164             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
165             .setVariant(RsaSsaPkcs1Parameters.Variant.TINK)
166             .build();
167     assertThat(parametersWithIdRequirement.hasIdRequirement()).isTrue();
168     assertThrows(
169         GeneralSecurityException.class,
170         () ->
171             RsaSsaPkcs1PublicKey.builder()
172                 .setParameters(parametersWithIdRequirement)
173                 .setModulus(MODULUS)
174                 .build());
175   }
176 
177   @Test
parametersDoesNotRequireIdButIdIsSetInBuild_fails()178   public void parametersDoesNotRequireIdButIdIsSetInBuild_fails() throws Exception {
179     RsaSsaPkcs1Parameters parametersWithoutIdRequirement =
180         RsaSsaPkcs1Parameters.builder()
181             .setModulusSizeBits(2048)
182             .setPublicExponent(EXPONENT)
183             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
184             .setVariant(RsaSsaPkcs1Parameters.Variant.NO_PREFIX)
185             .build();
186     assertThat(parametersWithoutIdRequirement.hasIdRequirement()).isFalse();
187     assertThrows(
188         GeneralSecurityException.class,
189         () ->
190             RsaSsaPkcs1PublicKey.builder()
191                 .setParameters(parametersWithoutIdRequirement)
192                 .setModulus(MODULUS)
193                 .setIdRequirement(0x66AABBCC)
194                 .build());
195   }
196 
197   @Test
modulusSizeIsValidated()198   public void modulusSizeIsValidated() throws Exception {
199     RsaSsaPkcs1Parameters parameters =
200         RsaSsaPkcs1Parameters.builder()
201             .setModulusSizeBits(3456)
202             .setPublicExponent(EXPONENT)
203             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
204             .setVariant(RsaSsaPkcs1Parameters.Variant.NO_PREFIX)
205             .build();
206     // Modulus between 2^3455 and 2^3456 are valid.
207     BigInteger tooSmall = BigInteger.valueOf(2).pow(3455).subtract(BigInteger.ONE);
208     BigInteger smallest = BigInteger.valueOf(2).pow(3455).add(BigInteger.ONE);
209     BigInteger biggest = BigInteger.valueOf(2).pow(3456).subtract(BigInteger.ONE);
210     BigInteger tooBig = BigInteger.valueOf(2).pow(3456).add(BigInteger.ONE);
211     assertThrows(
212         GeneralSecurityException.class,
213         () ->
214             RsaSsaPkcs1PublicKey.builder().setParameters(parameters).setModulus(tooSmall).build());
215     RsaSsaPkcs1PublicKey publicKeyWithSmallestModulus =
216         RsaSsaPkcs1PublicKey.builder().setParameters(parameters).setModulus(smallest).build();
217     assertThat(publicKeyWithSmallestModulus.getModulus()).isEqualTo(smallest);
218     RsaSsaPkcs1PublicKey publicKeyWithBiggestModulus =
219         RsaSsaPkcs1PublicKey.builder().setParameters(parameters).setModulus(biggest).build();
220     assertThat(publicKeyWithBiggestModulus.getModulus()).isEqualTo(biggest);
221     assertThrows(
222         GeneralSecurityException.class,
223         () -> RsaSsaPkcs1PublicKey.builder().setParameters(parameters).setModulus(tooBig).build());
224   }
225 
226   @Test
testEqualities()227   public void testEqualities() throws Exception {
228     RsaSsaPkcs1Parameters noPrefixParameters =
229         RsaSsaPkcs1Parameters.builder()
230             .setModulusSizeBits(2048)
231             .setPublicExponent(EXPONENT)
232             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
233             .setVariant(RsaSsaPkcs1Parameters.Variant.NO_PREFIX)
234             .build();
235     RsaSsaPkcs1Parameters noPrefixParametersCopy =
236         RsaSsaPkcs1Parameters.builder()
237             .setModulusSizeBits(2048)
238             .setPublicExponent(EXPONENT)
239             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
240             .setVariant(RsaSsaPkcs1Parameters.Variant.NO_PREFIX)
241             .build();
242     RsaSsaPkcs1Parameters tinkPrefixParameters =
243         RsaSsaPkcs1Parameters.builder()
244             .setModulusSizeBits(2048)
245             .setPublicExponent(EXPONENT)
246             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
247             .setVariant(RsaSsaPkcs1Parameters.Variant.TINK)
248             .build();
249     RsaSsaPkcs1Parameters legacyPrefixParameters =
250         RsaSsaPkcs1Parameters.builder()
251             .setModulusSizeBits(2048)
252             .setPublicExponent(EXPONENT)
253             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
254             .setVariant(RsaSsaPkcs1Parameters.Variant.LEGACY)
255             .build();
256     RsaSsaPkcs1Parameters crunchyPrefixParameters =
257         RsaSsaPkcs1Parameters.builder()
258             .setModulusSizeBits(2048)
259             .setPublicExponent(EXPONENT)
260             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
261             .setVariant(RsaSsaPkcs1Parameters.Variant.CRUNCHY)
262             .build();
263     RsaSsaPkcs1Parameters noPrefixParametersExponent65539 =
264         RsaSsaPkcs1Parameters.builder()
265             .setModulusSizeBits(2048)
266             .setPublicExponent(BigInteger.valueOf(65539))
267             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
268             .setVariant(RsaSsaPkcs1Parameters.Variant.NO_PREFIX)
269             .build();
270     RsaSsaPkcs1Parameters noPrefixParametersSha512 =
271         RsaSsaPkcs1Parameters.builder()
272             .setModulusSizeBits(2048)
273             .setPublicExponent(EXPONENT)
274             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA512)
275             .setVariant(RsaSsaPkcs1Parameters.Variant.NO_PREFIX)
276             .build();
277     new KeyTester()
278         .addEqualityGroup(
279             "No prefix, P256",
280             RsaSsaPkcs1PublicKey.builder()
281                 .setParameters(noPrefixParameters)
282                 .setModulus(MODULUS)
283                 .build(),
284             // the same key built twice must be equal
285             RsaSsaPkcs1PublicKey.builder()
286                 .setParameters(noPrefixParametersCopy)
287                 .setModulus(MODULUS)
288                 .build(),
289             // setting id requirement to null is equal to not setting it
290             RsaSsaPkcs1PublicKey.builder()
291                 .setParameters(noPrefixParameters)
292                 .setModulus(MODULUS)
293                 .setIdRequirement(null)
294                 .build())
295         // This group checks that keys with different key bytes are not equal
296         .addEqualityGroup(
297             "No prefix, different modulus",
298             RsaSsaPkcs1PublicKey.builder()
299                 .setParameters(noPrefixParameters)
300                 .setModulus(MODULUS.add(BigInteger.ONE))
301                 .build())
302         // These groups checks that keys with different parameters are not equal
303         .addEqualityGroup(
304             "No prefix, e=65539",
305             RsaSsaPkcs1PublicKey.builder()
306                 .setParameters(noPrefixParametersExponent65539)
307                 .setModulus(MODULUS)
308                 .build())
309         .addEqualityGroup(
310             "No prefix, SHA512",
311             RsaSsaPkcs1PublicKey.builder()
312                 .setParameters(noPrefixParametersSha512)
313                 .setModulus(MODULUS)
314                 .build())
315         .addEqualityGroup(
316             "Tink with key id 1907",
317             RsaSsaPkcs1PublicKey.builder()
318                 .setParameters(tinkPrefixParameters)
319                 .setModulus(MODULUS)
320                 .setIdRequirement(1907)
321                 .build())
322         // This group checks that keys with different key ids are not equal
323         .addEqualityGroup(
324             "Tink with key id 1908",
325             RsaSsaPkcs1PublicKey.builder()
326                 .setParameters(tinkPrefixParameters)
327                 .setModulus(MODULUS)
328                 .setIdRequirement(1908)
329                 .build())
330         // These 2 groups check that keys with different output prefix types are not equal
331         .addEqualityGroup(
332             "Legacy with key id 1907",
333             RsaSsaPkcs1PublicKey.builder()
334                 .setParameters(legacyPrefixParameters)
335                 .setModulus(MODULUS)
336                 .setIdRequirement(1907)
337                 .build())
338         .addEqualityGroup(
339             "Crunchy with key id 1907",
340             RsaSsaPkcs1PublicKey.builder()
341                 .setParameters(crunchyPrefixParameters)
342                 .setModulus(MODULUS)
343                 .setIdRequirement(1907)
344                 .build())
345         .doTests();
346   }
347 }
348