• 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.RsaSsaPkcs1TestUtil;
32 import com.google.crypto.tink.signature.internal.testing.SignatureTestVector;
33 import com.google.crypto.tink.subtle.Hex;
34 import com.google.crypto.tink.testing.TestUtil;
35 import java.math.BigInteger;
36 import java.util.Set;
37 import java.util.TreeSet;
38 import javax.annotation.Nullable;
39 import org.junit.BeforeClass;
40 import org.junit.Test;
41 import org.junit.experimental.theories.DataPoints;
42 import org.junit.experimental.theories.FromDataPoints;
43 import org.junit.experimental.theories.Theories;
44 import org.junit.experimental.theories.Theory;
45 import org.junit.runner.RunWith;
46 
47 /** Unit tests for RsaSsaPkcs1SignKeyManager. */
48 @RunWith(Theories.class)
49 public class RsaSsaPkcs1SignKeyManagerTest {
50 
51   @BeforeClass
beforeClass()52   public static void beforeClass() throws Exception {
53     RsaSsaPkcs1SignKeyManager.registerPair(/* newKeyAllowed= */ true);
54     PublicKeySignWrapper.register();
55     PublicKeyVerifyWrapper.register();
56   }
57 
58   @Test
createKey_smallKey_works()59   public void createKey_smallKey_works() throws Exception {
60     if (TestUtil.isTsan()) {
61       // factory.createKey is too slow in Tsan.
62       return;
63     }
64     RsaSsaPkcs1Parameters parameters =
65         RsaSsaPkcs1Parameters.builder()
66             .setModulusSizeBits(2048)
67             .setPublicExponent(RsaSsaPkcs1Parameters.F4)
68             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
69             .setVariant(RsaSsaPkcs1Parameters.Variant.NO_PREFIX)
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.RsaSsaPkcs1PrivateKey.class);
74     com.google.crypto.tink.signature.RsaSsaPkcs1PrivateKey privateKey =
75         (com.google.crypto.tink.signature.RsaSsaPkcs1PrivateKey) key;
76 
77     assertThat(privateKey.getPublicKey().getParameters()).isEqualTo(parameters);
78     assertThat(privateKey.getPublicKey().getModulus().bitLength()).isEqualTo(2048);
79   }
80 
81   @Test
createKey_alwaysNewElement()82   public void createKey_alwaysNewElement() throws Exception {
83     if (TestUtil.isTsan()) {
84       // factory.createKey is too slow in Tsan.
85       return;
86     }
87 
88     RsaSsaPkcs1Parameters parameters =
89         RsaSsaPkcs1Parameters.builder()
90             .setModulusSizeBits(2048)
91             .setPublicExponent(RsaSsaPkcs1Parameters.F4)
92             .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
93             .setVariant(RsaSsaPkcs1Parameters.Variant.TINK)
94             .build();
95     Set<BigInteger> primes = new TreeSet<>();
96     // Calls newKey multiple times and make sure that they generate different keys -- takes about a
97     // second per key.
98     int numTests = 5;
99     for (int i = 0; i < numTests; i++) {
100       KeysetHandle handle = KeysetHandle.generateNew(parameters);
101       assertThat(handle.size()).isEqualTo(1);
102       com.google.crypto.tink.signature.RsaSsaPkcs1PrivateKey key =
103           (com.google.crypto.tink.signature.RsaSsaPkcs1PrivateKey) handle.getAt(0).getKey();
104       primes.add(key.getPrimeP().getBigInteger(InsecureSecretKeyAccess.get()));
105       primes.add(key.getPrimeQ().getBigInteger(InsecureSecretKeyAccess.get()));
106     }
107     assertThat(primes).hasSize(2 * numTests);
108   }
109 
110   @Test
testRsa3072SsaPkcs1Sha256F4Template()111   public void testRsa3072SsaPkcs1Sha256F4Template() throws Exception {
112     KeyTemplate template = RsaSsaPkcs1SignKeyManager.rsa3072SsaPkcs1Sha256F4Template();
113     assertThat(template.toParameters())
114         .isEqualTo(
115             RsaSsaPkcs1Parameters.builder()
116                 .setModulusSizeBits(3072)
117                 .setPublicExponent(RsaSsaPkcs1Parameters.F4)
118                 .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
119                 .setVariant(RsaSsaPkcs1Parameters.Variant.TINK)
120                 .build());
121   }
122 
123   @Test
testRawRsa3072SsaPkcs1Sha256F4Template()124   public void testRawRsa3072SsaPkcs1Sha256F4Template() throws Exception {
125     KeyTemplate template = RsaSsaPkcs1SignKeyManager.rawRsa3072SsaPkcs1Sha256F4Template();
126     assertThat(template.toParameters())
127         .isEqualTo(
128             RsaSsaPkcs1Parameters.builder()
129                 .setModulusSizeBits(3072)
130                 .setPublicExponent(RsaSsaPkcs1Parameters.F4)
131                 .setHashType(RsaSsaPkcs1Parameters.HashType.SHA256)
132                 .setVariant(RsaSsaPkcs1Parameters.Variant.NO_PREFIX)
133                 .build());
134   }
135 
136   @Test
testRsa4096SsaPkcs1Sha512F4Template()137   public void testRsa4096SsaPkcs1Sha512F4Template() throws Exception {
138     KeyTemplate template = RsaSsaPkcs1SignKeyManager.rsa4096SsaPkcs1Sha512F4Template();
139     assertThat(template.toParameters())
140         .isEqualTo(
141             RsaSsaPkcs1Parameters.builder()
142                 .setModulusSizeBits(4096)
143                 .setPublicExponent(RsaSsaPkcs1Parameters.F4)
144                 .setHashType(RsaSsaPkcs1Parameters.HashType.SHA512)
145                 .setVariant(RsaSsaPkcs1Parameters.Variant.TINK)
146                 .build());
147   }
148 
149   @Test
testRawRsa4096SsaPkcs1Sha512F4Template()150   public void testRawRsa4096SsaPkcs1Sha512F4Template() throws Exception {
151     KeyTemplate template = RsaSsaPkcs1SignKeyManager.rawRsa4096SsaPkcs1Sha512F4Template();
152     assertThat(template.toParameters())
153         .isEqualTo(
154             RsaSsaPkcs1Parameters.builder()
155                 .setModulusSizeBits(4096)
156                 .setPublicExponent(RsaSsaPkcs1Parameters.F4)
157                 .setHashType(RsaSsaPkcs1Parameters.HashType.SHA512)
158                 .setVariant(RsaSsaPkcs1Parameters.Variant.NO_PREFIX)
159                 .build());
160   }
161 
162   @Test
testRsa3072SsaPkcs1Sha256F4TemplateWithManager()163   public void testRsa3072SsaPkcs1Sha256F4TemplateWithManager() throws Exception {
164     if (TestUtil.isTsan()) {
165       // factory.createKey is too slow in Tsan.
166       return;
167     }
168     Parameters p = RsaSsaPkcs1SignKeyManager.rsa3072SsaPkcs1Sha256F4Template().toParameters();
169     assertThat(KeysetHandle.generateNew(p).getAt(0).getKey().getParameters()).isEqualTo(p);
170   }
171 
172   @Test
testRawRsa3072SsaPkcs1Sha256F4TemplateWithManager()173   public void testRawRsa3072SsaPkcs1Sha256F4TemplateWithManager() throws Exception {
174     if (TestUtil.isTsan()) {
175       // factory.createKey is too slow in Tsan.
176       return;
177     }
178     Parameters p = RsaSsaPkcs1SignKeyManager.rawRsa3072SsaPkcs1Sha256F4Template().toParameters();
179     assertThat(KeysetHandle.generateNew(p).getAt(0).getKey().getParameters()).isEqualTo(p);
180   }
181 
182   @Test
testRsa4096SsaPkcs1Sha512F4TemplateWithManager()183   public void testRsa4096SsaPkcs1Sha512F4TemplateWithManager() throws Exception {
184     if (TestUtil.isTsan()) {
185       // factory.createKey is too slow in Tsan.
186       return;
187     }
188     Parameters p = RsaSsaPkcs1SignKeyManager.rsa4096SsaPkcs1Sha512F4Template().toParameters();
189     assertThat(KeysetHandle.generateNew(p).getAt(0).getKey().getParameters()).isEqualTo(p);
190   }
191 
192   @Test
testRawRsa4096SsaPkcs1Sha512F4TemplateWithManager()193   public void testRawRsa4096SsaPkcs1Sha512F4TemplateWithManager() throws Exception {
194     if (TestUtil.isTsan()) {
195       // factory.createKey is too slow in Tsan.
196       return;
197     }
198     Parameters p = RsaSsaPkcs1SignKeyManager.rawRsa4096SsaPkcs1Sha512F4Template().toParameters();
199     assertThat(KeysetHandle.generateNew(p).getAt(0).getKey().getParameters()).isEqualTo(p);
200   }
201 
202   @DataPoints("templateNames")
203   public static final String[] KEY_TEMPLATES =
204       new String[] {
205         "RSA_SSA_PKCS1_3072_SHA256_F4",
206         "RSA_SSA_PKCS1_3072_SHA256_F4_RAW",
207         "RSA_SSA_PKCS1_4096_SHA512_F4",
208         "RSA_SSA_PKCS1_4096_SHA512_F4_RAW",
209         "RSA_SSA_PKCS1_3072_SHA256_F4_WITHOUT_PREFIX"
210       };
211 
212   @Theory
testTemplates(@romDataPoints"templateNames") String templateName)213   public void testTemplates(@FromDataPoints("templateNames") String templateName) throws Exception {
214     if (TestUtil.isTsan()) {
215       // factory.createKey is too slow in Tsan.
216       return;
217     }
218     KeysetHandle h = KeysetHandle.generateNew(KeyTemplates.get(templateName));
219     assertThat(h.size()).isEqualTo(1);
220     assertThat(h.getAt(0).getKey().getParameters())
221         .isEqualTo(KeyTemplates.get(templateName).toParameters());
222   }
223 
224   @DataPoints("testVectors")
225   public static final SignatureTestVector[] SIGNATURE_TEST_VECTORS =
226       RsaSsaPkcs1TestUtil.createRsaSsaPkcs1TestVectors();
227 
228   @Theory
test_computeSignatureInTestVector( @romDataPoints"testVectors") SignatureTestVector v)229   public void test_computeSignatureInTestVector(
230       @FromDataPoints("testVectors") SignatureTestVector v) throws Exception {
231     KeysetHandle.Builder.Entry entry = KeysetHandle.importKey(v.getPrivateKey()).makePrimary();
232     @Nullable Integer id = v.getPrivateKey().getIdRequirementOrNull();
233     if (id == null) {
234       entry.withRandomId();
235     } else {
236       entry.withFixedId(id);
237     }
238     KeysetHandle handle = KeysetHandle.newBuilder().addEntry(entry).build();
239     PublicKeySign signer = handle.getPrimitive(RegistryConfiguration.get(), PublicKeySign.class);
240     byte[] signature = signer.sign(v.getMessage());
241     assertThat(Hex.encode(signature)).isEqualTo(Hex.encode(v.getSignature()));
242   }
243 
244   @Theory
test_validateSignatureInTestVector( @romDataPoints"testVectors") SignatureTestVector v)245   public void test_validateSignatureInTestVector(
246       @FromDataPoints("testVectors") SignatureTestVector v) throws Exception {
247     KeysetHandle.Builder.Entry entry = KeysetHandle.importKey(v.getPrivateKey()).makePrimary();
248     @Nullable Integer id = v.getPrivateKey().getIdRequirementOrNull();
249     if (id == null) {
250       entry.withRandomId();
251     } else {
252       entry.withFixedId(id);
253     }
254     KeysetHandle handle = KeysetHandle.newBuilder().addEntry(entry).build();
255     PublicKeyVerify verifier =
256         handle
257             .getPublicKeysetHandle()
258             .getPrimitive(RegistryConfiguration.get(), PublicKeyVerify.class);
259     verifier.verify(v.getSignature(), v.getMessage());
260   }
261 
262   @Test
test_serializeAndParse_works()263   public void test_serializeAndParse_works() throws Exception {
264     SignatureTestVector testVector = SIGNATURE_TEST_VECTORS[0];
265     com.google.crypto.tink.signature.RsaSsaPkcs1PrivateKey key =
266         (com.google.crypto.tink.signature.RsaSsaPkcs1PrivateKey) testVector.getPrivateKey();
267     KeysetHandle.Builder.Entry entry = KeysetHandle.importKey(key).withFixedId(1216).makePrimary();
268     KeysetHandle handle = KeysetHandle.newBuilder().addEntry(entry).build();
269 
270     byte[] serializedHandle =
271         TinkProtoKeysetFormat.serializeKeyset(handle, InsecureSecretKeyAccess.get());
272     KeysetHandle parsedHandle =
273         TinkProtoKeysetFormat.parseKeyset(serializedHandle, InsecureSecretKeyAccess.get());
274     assertThat(parsedHandle.equalsKeyset(handle)).isTrue();
275   }
276 
277   @Test
testKeyManagerRegistered()278   public void testKeyManagerRegistered() throws Exception {
279     assertThat(
280             KeyManagerRegistry.globalInstance()
281                 .getKeyManager(
282                     "type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey",
283                     PublicKeySign.class))
284         .isNotNull();
285   }
286 }
287