• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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 
21 import com.google.crypto.tink.InsecureSecretKeyAccess;
22 import com.google.crypto.tink.KeyTemplate;
23 import com.google.crypto.tink.KeyTemplates;
24 import com.google.crypto.tink.KeysetHandle;
25 import com.google.crypto.tink.Parameters;
26 import com.google.crypto.tink.PublicKeySign;
27 import com.google.crypto.tink.PublicKeyVerify;
28 import com.google.crypto.tink.RegistryConfiguration;
29 import com.google.crypto.tink.TinkProtoKeysetFormat;
30 import com.google.crypto.tink.internal.KeyManagerRegistry;
31 import com.google.crypto.tink.signature.internal.testing.RsaSsaPssTestUtil;
32 import com.google.crypto.tink.signature.internal.testing.SignatureTestVector;
33 import com.google.crypto.tink.testing.TestUtil;
34 import java.math.BigInteger;
35 import java.util.Set;
36 import java.util.TreeSet;
37 import javax.annotation.Nullable;
38 import org.junit.BeforeClass;
39 import org.junit.Test;
40 import org.junit.experimental.theories.DataPoints;
41 import org.junit.experimental.theories.FromDataPoints;
42 import org.junit.experimental.theories.Theories;
43 import org.junit.experimental.theories.Theory;
44 import org.junit.runner.RunWith;
45 
46 /** Unit tests for RsaSsaPssSignKeyManager. */
47 @RunWith(Theories.class)
48 public class RsaSsaPssSignKeyManagerTest {
49   @BeforeClass
beforeClass()50   public static void beforeClass() throws Exception {
51     RsaSsaPssSignKeyManager.registerPair(/* newKeyAllowed= */ true);
52     PublicKeySignWrapper.register();
53     PublicKeyVerifyWrapper.register();
54   }
55 
56   @Test
createSmallKeyUsingParameters_works()57   public void createSmallKeyUsingParameters_works() throws Exception {
58     if (TestUtil.isTsan()) {
59       // factory.createKey is too slow in Tsan.
60       return;
61     }
62     RsaSsaPssParameters parameters =
63         RsaSsaPssParameters.builder()
64             .setModulusSizeBits(3072)
65             .setPublicExponent(RsaSsaPssParameters.F4)
66             .setSigHashType(RsaSsaPssParameters.HashType.SHA256)
67             .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256)
68             .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX)
69             .setSaltLengthBytes(32)
70             .build();
71     KeysetHandle handle = KeysetHandle.generateNew(parameters);
72     com.google.crypto.tink.Key key = handle.getAt(0).getKey();
73     assertThat(key).isInstanceOf(com.google.crypto.tink.signature.RsaSsaPssPrivateKey.class);
74     com.google.crypto.tink.signature.RsaSsaPssPrivateKey privateKey =
75         (com.google.crypto.tink.signature.RsaSsaPssPrivateKey) key;
76 
77     assertThat(privateKey.getPublicKey().getParameters()).isEqualTo(parameters);
78     assertThat(privateKey.getPublicKey().getModulus().bitLength()).isEqualTo(3072);
79   }
80 
81 
82   @Test
createKey_alwaysNewElement()83   public void createKey_alwaysNewElement() throws Exception {
84     if (TestUtil.isTsan()) {
85       // factory.createKey is too slow in Tsan.
86       return;
87     }
88     RsaSsaPssParameters parameters =
89         RsaSsaPssParameters.builder()
90             .setModulusSizeBits(2048)
91             .setPublicExponent(RsaSsaPssParameters.F4)
92             .setSigHashType(RsaSsaPssParameters.HashType.SHA256)
93             .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256)
94             .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX)
95             .setSaltLengthBytes(32)
96             .build();
97     Set<BigInteger> primes = new TreeSet<>();
98     // Calls newKey multiple times and make sure that they generate different keys -- takes about a
99     // second per key.
100     int numTests = 5;
101     for (int i = 0; i < numTests; i++) {
102       KeysetHandle handle = KeysetHandle.generateNew(parameters);
103       assertThat(handle.size()).isEqualTo(1);
104       com.google.crypto.tink.signature.RsaSsaPssPrivateKey key =
105           (com.google.crypto.tink.signature.RsaSsaPssPrivateKey) handle.getAt(0).getKey();
106       primes.add(key.getPrimeP().getBigInteger(InsecureSecretKeyAccess.get()));
107       primes.add(key.getPrimeQ().getBigInteger(InsecureSecretKeyAccess.get()));
108     }
109     assertThat(primes).hasSize(2 * numTests);
110   }
111 
112 
113   @Test
testRsa3072PssSha256F4Template()114   public void testRsa3072PssSha256F4Template() throws Exception {
115     KeyTemplate template = RsaSsaPssSignKeyManager.rsa3072PssSha256F4Template();
116     assertThat(template.toParameters())
117         .isEqualTo(
118             RsaSsaPssParameters.builder()
119                 .setSigHashType(RsaSsaPssParameters.HashType.SHA256)
120                 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256)
121                 .setSaltLengthBytes(32)
122                 .setModulusSizeBits(3072)
123                 .setPublicExponent(RsaSsaPssParameters.F4)
124                 .setVariant(RsaSsaPssParameters.Variant.TINK)
125                 .build());
126   }
127 
128   @Test
testRawRsa3072PssSha256F4Template()129   public void testRawRsa3072PssSha256F4Template() throws Exception {
130     KeyTemplate template = RsaSsaPssSignKeyManager.rawRsa3072PssSha256F4Template();
131     assertThat(template.toParameters())
132         .isEqualTo(
133             RsaSsaPssParameters.builder()
134                 .setSigHashType(RsaSsaPssParameters.HashType.SHA256)
135                 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256)
136                 .setSaltLengthBytes(32)
137                 .setModulusSizeBits(3072)
138                 .setPublicExponent(RsaSsaPssParameters.F4)
139                 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX)
140                 .build());
141   }
142 
143   @Test
testRsa4096PssSha512F4Template()144   public void testRsa4096PssSha512F4Template() throws Exception {
145     KeyTemplate template = RsaSsaPssSignKeyManager.rsa4096PssSha512F4Template();
146     assertThat(template.toParameters())
147         .isEqualTo(
148             RsaSsaPssParameters.builder()
149                 .setSigHashType(RsaSsaPssParameters.HashType.SHA512)
150                 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA512)
151                 .setSaltLengthBytes(64)
152                 .setModulusSizeBits(4096)
153                 .setPublicExponent(RsaSsaPssParameters.F4)
154                 .setVariant(RsaSsaPssParameters.Variant.TINK)
155                 .build());
156   }
157 
158   @Test
testRawRsa4096PssSha512F4Template()159   public void testRawRsa4096PssSha512F4Template() throws Exception {
160     KeyTemplate template = RsaSsaPssSignKeyManager.rawRsa4096PssSha512F4Template();
161     assertThat(template.toParameters())
162         .isEqualTo(
163             RsaSsaPssParameters.builder()
164                 .setSigHashType(RsaSsaPssParameters.HashType.SHA512)
165                 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA512)
166                 .setSaltLengthBytes(64)
167                 .setModulusSizeBits(4096)
168                 .setPublicExponent(RsaSsaPssParameters.F4)
169                 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX)
170                 .build());
171   }
172 
173   @Test
testRsa3072PssSha256F4TemplateWithManager()174   public void testRsa3072PssSha256F4TemplateWithManager() throws Exception {
175     if (TestUtil.isTsan()) {
176       return; // too slow for tsan
177     }
178     Parameters p = RsaSsaPssSignKeyManager.rsa3072PssSha256F4Template().toParameters();
179     assertThat(KeysetHandle.generateNew(p).getAt(0).getKey().getParameters()).isEqualTo(p);
180   }
181 
182   @Test
testRawRsa3072PssSha256F4TemplateWithManager()183   public void testRawRsa3072PssSha256F4TemplateWithManager() throws Exception {
184     if (TestUtil.isTsan()) {
185       return; // too slow for tsan
186     }
187     Parameters p = RsaSsaPssSignKeyManager.rawRsa3072PssSha256F4Template().toParameters();
188     assertThat(KeysetHandle.generateNew(p).getAt(0).getKey().getParameters()).isEqualTo(p);
189   }
190 
191   @Test
testRsa4096PssSha512F4TemplateWithManager()192   public void testRsa4096PssSha512F4TemplateWithManager() throws Exception {
193     if (TestUtil.isTsan()) {
194       return; // too slow for tsan
195     }
196     Parameters p = RsaSsaPssSignKeyManager.rsa4096PssSha512F4Template().toParameters();
197     assertThat(KeysetHandle.generateNew(p).getAt(0).getKey().getParameters()).isEqualTo(p);
198   }
199 
200   @Test
testRawRsa4096PssSha512F4TemplateWithManager()201   public void testRawRsa4096PssSha512F4TemplateWithManager() throws Exception {
202     if (TestUtil.isTsan()) {
203       return; // too slow for tsan
204     }
205     Parameters p = RsaSsaPssSignKeyManager.rawRsa4096PssSha512F4Template().toParameters();
206     assertThat(KeysetHandle.generateNew(p).getAt(0).getKey().getParameters()).isEqualTo(p);
207   }
208 
209   @DataPoints("templateNames")
210   public static final String[] KEY_TEMPLATES =
211       new String[] {
212         "RSA_SSA_PSS_3072_SHA256_F4",
213         "RSA_SSA_PSS_3072_SHA256_F4_RAW",
214         "RSA_SSA_PSS_3072_SHA256_SHA256_32_F4",
215         "RSA_SSA_PSS_4096_SHA512_F4",
216         "RSA_SSA_PSS_4096_SHA512_F4_RAW",
217         "RSA_SSA_PSS_4096_SHA512_SHA512_64_F4",
218       };
219 
220   @Theory
testTemplates(@romDataPoints"templateNames") String templateName)221   public void testTemplates(@FromDataPoints("templateNames") String templateName) throws Exception {
222     if (TestUtil.isTsan()) {
223       // factory.createKey is too slow in Tsan.
224       return;
225     }
226     KeysetHandle h = KeysetHandle.generateNew(KeyTemplates.get(templateName));
227     assertThat(h.size()).isEqualTo(1);
228     assertThat(h.getAt(0).getKey().getParameters())
229         .isEqualTo(KeyTemplates.get(templateName).toParameters());
230   }
231 
232   /**
233    * Tests that the verifier can verify a the signature for the message and key in the test vector.
234    */
235   @Theory
test_validateSignatureInTestVector( @romDataPoints"allTests") SignatureTestVector testVector)236   public void test_validateSignatureInTestVector(
237       @FromDataPoints("allTests") SignatureTestVector testVector) throws Exception {
238     com.google.crypto.tink.signature.RsaSsaPssPrivateKey key =
239         (com.google.crypto.tink.signature.RsaSsaPssPrivateKey) testVector.getPrivateKey();
240     KeysetHandle.Builder.Entry entry = KeysetHandle.importKey(key).makePrimary();
241     @Nullable Integer id = key.getIdRequirementOrNull();
242     if (id == null) {
243       entry.withRandomId();
244     } else {
245       entry.withFixedId(id);
246     }
247     KeysetHandle handle = KeysetHandle.newBuilder().addEntry(entry).build();
248     PublicKeyVerify verifier =
249         handle
250             .getPublicKeysetHandle()
251             .getPrimitive(RegistryConfiguration.get(), PublicKeyVerify.class);
252     verifier.verify(testVector.getSignature(), testVector.getMessage());
253   }
254 
255   /**
256    * Tests that the verifier can verify a newly generated signature for the message and key in the
257    * test vector.
258    */
259   @Theory
test_computeAndValidateFreshSignatureWithTestVector( @romDataPoints"allTests") SignatureTestVector testVector)260   public void test_computeAndValidateFreshSignatureWithTestVector(
261       @FromDataPoints("allTests") SignatureTestVector testVector) throws Exception {
262     com.google.crypto.tink.signature.RsaSsaPssPrivateKey key =
263         (com.google.crypto.tink.signature.RsaSsaPssPrivateKey) testVector.getPrivateKey();
264     KeysetHandle.Builder.Entry entry = KeysetHandle.importKey(key).makePrimary();
265     @Nullable Integer id = key.getIdRequirementOrNull();
266     if (id == null) {
267       entry.withRandomId();
268     } else {
269       entry.withFixedId(id);
270     }
271     KeysetHandle handle = KeysetHandle.newBuilder().addEntry(entry).build();
272     PublicKeySign signer = handle.getPrimitive(RegistryConfiguration.get(), PublicKeySign.class);
273     byte[] signature = signer.sign(testVector.getMessage());
274     PublicKeyVerify verifier =
275         handle
276             .getPublicKeysetHandle()
277             .getPrimitive(RegistryConfiguration.get(), PublicKeyVerify.class);
278     verifier.verify(signature, testVector.getMessage());
279   }
280 
281   @DataPoints("allTests")
282   public static final SignatureTestVector[] ALL_TEST_VECTORS =
283       RsaSsaPssTestUtil.createRsaPssTestVectors();
284 
285   @Test
test_serializeAndParse_works()286   public void test_serializeAndParse_works() throws Exception {
287     SignatureTestVector testVector = ALL_TEST_VECTORS[0];
288     com.google.crypto.tink.signature.RsaSsaPssPrivateKey key =
289         (com.google.crypto.tink.signature.RsaSsaPssPrivateKey) testVector.getPrivateKey();
290     KeysetHandle.Builder.Entry entry = KeysetHandle.importKey(key).withFixedId(1216).makePrimary();
291     KeysetHandle handle = KeysetHandle.newBuilder().addEntry(entry).build();
292 
293     byte[] serializedHandle =
294         TinkProtoKeysetFormat.serializeKeyset(handle, InsecureSecretKeyAccess.get());
295     KeysetHandle parsedHandle =
296         TinkProtoKeysetFormat.parseKeyset(serializedHandle, InsecureSecretKeyAccess.get());
297     assertThat(parsedHandle.equalsKeyset(handle)).isTrue();
298   }
299 
300   @Test
testKeyManagerRegistered()301   public void testKeyManagerRegistered() throws Exception {
302     assertThat(
303             KeyManagerRegistry.globalInstance()
304                 .getKeyManager(
305                     "type.googleapis.com/google.crypto.tink.RsaSsaPssPrivateKey",
306                     PublicKeySign.class))
307         .isNotNull();
308   }
309 }
310