• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 Google Inc.
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.assertTrue;
21 
22 import com.google.crypto.tink.InsecureSecretKeyAccess;
23 import com.google.crypto.tink.KeyTemplate;
24 import com.google.crypto.tink.KeyTemplates;
25 import com.google.crypto.tink.KeysetHandle;
26 import com.google.crypto.tink.Parameters;
27 import com.google.crypto.tink.PublicKeySign;
28 import com.google.crypto.tink.PublicKeyVerify;
29 import com.google.crypto.tink.RegistryConfiguration;
30 import com.google.crypto.tink.TinkProtoKeysetFormat;
31 import com.google.crypto.tink.internal.KeyManagerRegistry;
32 import com.google.crypto.tink.internal.SlowInputStream;
33 import com.google.crypto.tink.signature.internal.testing.Ed25519TestUtil;
34 import com.google.crypto.tink.signature.internal.testing.SignatureTestVector;
35 import com.google.crypto.tink.subtle.Hex;
36 import com.google.crypto.tink.util.Bytes;
37 import com.google.crypto.tink.util.SecretBytes;
38 import java.io.ByteArrayInputStream;
39 import java.util.Set;
40 import java.util.TreeSet;
41 import javax.annotation.Nullable;
42 import org.junit.Before;
43 import org.junit.Test;
44 import org.junit.experimental.theories.DataPoints;
45 import org.junit.experimental.theories.FromDataPoints;
46 import org.junit.experimental.theories.Theories;
47 import org.junit.experimental.theories.Theory;
48 import org.junit.runner.RunWith;
49 
50 /** Unit tests for Ed25519PrivateKeyManager. */
51 @RunWith(Theories.class)
52 public class Ed25519PrivateKeyManagerTest {
53 
54   @Before
register()55   public void register() throws Exception {
56     SignatureConfig.register();
57   }
58 
59   // Tests that generated keys are different.
60   @Test
createKey_differentValues()61   public void createKey_differentValues() throws Exception {
62     Set<String> keys = new TreeSet<>();
63     int numTests = 100;
64     for (int i = 0; i < numTests; i++) {
65       KeysetHandle handle = KeysetHandle.generateNew(Ed25519Parameters.create());
66       assertThat(handle.size()).isEqualTo(1);
67       assertThat(handle.getAt(0).getKey().getParameters()).isEqualTo(Ed25519Parameters.create());
68       com.google.crypto.tink.signature.Ed25519PrivateKey key =
69           (com.google.crypto.tink.signature.Ed25519PrivateKey) handle.getAt(0).getKey();
70       keys.add(Hex.encode(key.getPrivateKeyBytes().toByteArray(InsecureSecretKeyAccess.get())));
71     }
72     assertThat(keys).hasSize(numTests);
73   }
74 
75   @Test
testEd25519Template()76   public void testEd25519Template() throws Exception {
77     KeyTemplate template = Ed25519PrivateKeyManager.ed25519Template();
78     assertThat(template.toParameters())
79         .isEqualTo(Ed25519Parameters.create(Ed25519Parameters.Variant.TINK));
80   }
81 
82   @Test
testRawEd25519Template()83   public void testRawEd25519Template() throws Exception {
84     KeyTemplate template = Ed25519PrivateKeyManager.rawEd25519Template();
85     assertThat(template.toParameters())
86         .isEqualTo(Ed25519Parameters.create());
87   }
88 
89   @Test
testKeyTemplateAndManagerCompatibility()90   public void testKeyTemplateAndManagerCompatibility() throws Exception {
91     Parameters p = Ed25519PrivateKeyManager.ed25519Template().toParameters();
92     assertThat(KeysetHandle.generateNew(p).getAt(0).getKey().getParameters()).isEqualTo(p);
93 
94     p = Ed25519PrivateKeyManager.rawEd25519Template().toParameters();
95     assertThat(KeysetHandle.generateNew(p).getAt(0).getKey().getParameters()).isEqualTo(p);
96   }
97 
98   @DataPoints("templateNames")
99   public static final String[] KEY_TEMPLATES =
100       new String[] {
101         "ED25519", "ED25519_RAW", "ED25519WithRawOutput",
102       };
103 
104   @Theory
testTemplates(@romDataPoints"templateNames") String templateName)105   public void testTemplates(@FromDataPoints("templateNames") String templateName) throws Exception {
106     KeysetHandle h = KeysetHandle.generateNew(KeyTemplates.get(templateName));
107     assertThat(h.size()).isEqualTo(1);
108     assertThat(h.getAt(0).getKey().getParameters())
109         .isEqualTo(KeyTemplates.get(templateName).toParameters());
110   }
111 
112   @Test
testKeyManagerRegistered()113   public void testKeyManagerRegistered() throws Exception {
114     assertThat(
115             KeyManagerRegistry.globalInstance()
116                 .getKeyManager(
117                     "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey",
118                     PublicKeySign.class))
119         .isNotNull();
120   }
121 
122   @Test
testCreateRawKeyFromRandomness()123   public void testCreateRawKeyFromRandomness() throws Exception {
124     byte[] keyMaterial =
125         Hex.decode(
126             ""
127                 + "000102030405060708090A0B0C0D0E0F"
128                 + "101112131415161718191A1B1C1D1E1F"
129                 + "202122232425262728292A2B2C2D2E2F");
130     com.google.crypto.tink.signature.Ed25519PrivateKey key =
131         Ed25519PrivateKeyManager.createEd25519KeyFromRandomness(
132             Ed25519Parameters.create(Ed25519Parameters.Variant.NO_PREFIX),
133             new ByteArrayInputStream(keyMaterial),
134             null,
135             InsecureSecretKeyAccess.get());
136     com.google.crypto.tink.signature.Ed25519PublicKey expectedPublicKey =
137         com.google.crypto.tink.signature.Ed25519PublicKey.create(
138             Ed25519Parameters.Variant.NO_PREFIX,
139             Bytes.copyFrom(
140                 Hex.decode("03a107bff3ce10be1d70dd18e74bc09967e4d6309ba50d5f1ddc8664125531b8")),
141             /* idRequirement= */ null);
142 
143     com.google.crypto.tink.signature.Ed25519PrivateKey expectedPrivateKey =
144         com.google.crypto.tink.signature.Ed25519PrivateKey.create(
145             expectedPublicKey,
146             SecretBytes.copyFrom(
147                 Hex.decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"),
148                 InsecureSecretKeyAccess.get()));
149     assertTrue(key.equalsKey(expectedPrivateKey));
150   }
151 
152   @Test
testCreateTinkKeyFromRandomness()153   public void testCreateTinkKeyFromRandomness() throws Exception {
154     byte[] keyMaterial =
155         Hex.decode(
156             ""
157                 + "000102030405060708090A0B0C0D0E0F"
158                 + "101112131415161718191A1B1C1D1E1F"
159                 + "202122232425262728292A2B2C2D2E2F");
160     com.google.crypto.tink.signature.Ed25519PrivateKey key =
161         Ed25519PrivateKeyManager.createEd25519KeyFromRandomness(
162             Ed25519Parameters.create(Ed25519Parameters.Variant.TINK),
163             new ByteArrayInputStream(keyMaterial),
164             2344,
165             InsecureSecretKeyAccess.get());
166     com.google.crypto.tink.signature.Ed25519PublicKey expectedPublicKey =
167         com.google.crypto.tink.signature.Ed25519PublicKey.create(
168             Ed25519Parameters.Variant.TINK,
169             Bytes.copyFrom(
170                 Hex.decode("03a107bff3ce10be1d70dd18e74bc09967e4d6309ba50d5f1ddc8664125531b8")),
171             2344);
172 
173     com.google.crypto.tink.signature.Ed25519PrivateKey expectedPrivateKey =
174         com.google.crypto.tink.signature.Ed25519PrivateKey.create(
175             expectedPublicKey,
176             SecretBytes.copyFrom(
177                 Hex.decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"),
178                 InsecureSecretKeyAccess.get()));
179     assertTrue(key.equalsKey(expectedPrivateKey));
180   }
181 
182   @Test
testCreateKeyFromRandomness_slowInputStream_works()183   public void testCreateKeyFromRandomness_slowInputStream_works() throws Exception {
184     byte[] keyMaterial =
185         Hex.decode(
186             ""
187                 + "000102030405060708090A0B0C0D0E0F"
188                 + "101112131415161718191A1B1C1D1E1F"
189                 + "202122232425262728292A2B2C2D2E2F");
190     com.google.crypto.tink.signature.Ed25519PrivateKey key =
191         Ed25519PrivateKeyManager.createEd25519KeyFromRandomness(
192             Ed25519Parameters.create(Ed25519Parameters.Variant.TINK),
193             SlowInputStream.copyFrom(keyMaterial),
194             2344,
195             InsecureSecretKeyAccess.get());
196     com.google.crypto.tink.signature.Ed25519PublicKey expectedPublicKey =
197         com.google.crypto.tink.signature.Ed25519PublicKey.create(
198             Ed25519Parameters.Variant.TINK,
199             Bytes.copyFrom(
200                 Hex.decode("03a107bff3ce10be1d70dd18e74bc09967e4d6309ba50d5f1ddc8664125531b8")),
201             2344);
202     com.google.crypto.tink.signature.Ed25519PrivateKey expectedPrivateKey =
203         com.google.crypto.tink.signature.Ed25519PrivateKey.create(
204             expectedPublicKey,
205             SecretBytes.copyFrom(
206                 Hex.decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"),
207                 InsecureSecretKeyAccess.get()));
208     assertTrue(key.equalsKey(expectedPrivateKey));
209   }
210 
211   @DataPoints("testVectors")
212   public static final SignatureTestVector[] ALL_TEST_VECTORS =
213       Ed25519TestUtil.createEd25519TestVectors();
214 
215   @Theory
test_computeSignatureInTestVector( @romDataPoints"testVectors") SignatureTestVector v)216   public void test_computeSignatureInTestVector(
217       @FromDataPoints("testVectors") SignatureTestVector v) throws Exception {
218     KeysetHandle.Builder.Entry entry = KeysetHandle.importKey(v.getPrivateKey()).makePrimary();
219     @Nullable Integer id = v.getPrivateKey().getIdRequirementOrNull();
220     if (id == null) {
221       entry.withRandomId();
222     } else {
223       entry.withFixedId(id);
224     }
225     KeysetHandle handle = KeysetHandle.newBuilder().addEntry(entry).build();
226     PublicKeySign signer = handle.getPrimitive(RegistryConfiguration.get(), PublicKeySign.class);
227     byte[] signature = signer.sign(v.getMessage());
228     assertThat(Hex.encode(signature)).isEqualTo(Hex.encode(v.getSignature()));
229   }
230 
231   @Theory
test_validateSignatureInTestVector( @romDataPoints"testVectors") SignatureTestVector v)232   public void test_validateSignatureInTestVector(
233       @FromDataPoints("testVectors") SignatureTestVector v) throws Exception {
234     KeysetHandle.Builder.Entry entry = KeysetHandle.importKey(v.getPrivateKey()).makePrimary();
235     @Nullable Integer id = v.getPrivateKey().getIdRequirementOrNull();
236     if (id == null) {
237       entry.withRandomId();
238     } else {
239       entry.withFixedId(id);
240     }
241     KeysetHandle handle = KeysetHandle.newBuilder().addEntry(entry).build();
242     PublicKeyVerify verifier =
243         handle
244             .getPublicKeysetHandle()
245             .getPrimitive(RegistryConfiguration.get(), PublicKeyVerify.class);
246     verifier.verify(v.getSignature(), v.getMessage());
247   }
248 
249   @Test
test_serializeAndParse_works()250   public void test_serializeAndParse_works() throws Exception {
251     KeysetHandle handle = KeysetHandle.generateNew(Ed25519Parameters.create());
252     byte[] serializedHandle =
253         TinkProtoKeysetFormat.serializeKeyset(handle, InsecureSecretKeyAccess.get());
254     KeysetHandle parsedHandle =
255         TinkProtoKeysetFormat.parseKeyset(serializedHandle, InsecureSecretKeyAccess.get());
256     assertThat(parsedHandle.equalsKeyset(handle)).isTrue();
257   }
258 }
259