• 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.prf;
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.Key;
24 import com.google.crypto.tink.KeyTemplate;
25 import com.google.crypto.tink.KeyTemplates;
26 import com.google.crypto.tink.KeysetHandle;
27 import com.google.crypto.tink.Parameters;
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.internal.MutablePrimitiveRegistry;
32 import com.google.crypto.tink.internal.SlowInputStream;
33 import com.google.crypto.tink.keyderivation.KeyDerivationConfig;
34 import com.google.crypto.tink.keyderivation.KeysetDeriver;
35 import com.google.crypto.tink.keyderivation.PrfBasedKeyDerivationKey;
36 import com.google.crypto.tink.keyderivation.PrfBasedKeyDerivationParameters;
37 import com.google.crypto.tink.subtle.Hex;
38 import com.google.crypto.tink.subtle.PrfHmacJce;
39 import com.google.crypto.tink.util.SecretBytes;
40 import java.io.ByteArrayInputStream;
41 import java.util.Arrays;
42 import java.util.Set;
43 import java.util.TreeSet;
44 import org.junit.Before;
45 import org.junit.Test;
46 import org.junit.experimental.theories.DataPoints;
47 import org.junit.experimental.theories.FromDataPoints;
48 import org.junit.experimental.theories.Theories;
49 import org.junit.experimental.theories.Theory;
50 import org.junit.runner.RunWith;
51 
52 /** Unit tests for {@link HmacPrfKeyManager}. */
53 @RunWith(Theories.class)
54 public class HmacPrfKeyManagerTest {
55   @Before
register()56   public void register() throws Exception {
57     KeyDerivationConfig.register();
58     PrfConfig.register();
59   }
60 
61   @Test
testHmacSha256Template()62   public void testHmacSha256Template() throws Exception {
63     KeyTemplate template = HmacPrfKeyManager.hmacSha256Template();
64     assertThat(template.toParameters())
65         .isEqualTo(
66             HmacPrfParameters.builder()
67                 .setKeySizeBytes(32)
68                 .setHashType(HmacPrfParameters.HashType.SHA256)
69                 .build());
70   }
71 
72   @Test
testHmacSha512Template()73   public void testHmacSha512Template() throws Exception {
74     KeyTemplate template = HmacPrfKeyManager.hmacSha512Template();
75     assertThat(template.toParameters())
76         .isEqualTo(
77             HmacPrfParameters.builder()
78                 .setKeySizeBytes(64)
79                 .setHashType(HmacPrfParameters.HashType.SHA512)
80                 .build());
81   }
82 
83   @Test
testKeyTemplateAndManagerCompatibility()84   public void testKeyTemplateAndManagerCompatibility() throws Exception {
85     Parameters p = HmacPrfKeyManager.hmacSha256Template().toParameters();
86     assertThat(KeysetHandle.generateNew(p).getAt(0).getKey().getParameters()).isEqualTo(p);
87 
88     p = HmacPrfKeyManager.hmacSha256Template().toParameters();
89     assertThat(KeysetHandle.generateNew(p).getAt(0).getKey().getParameters()).isEqualTo(p);
90   }
91 
92   @DataPoints("templateNames")
93   public static final String[] KEY_TEMPLATES = new String[] {"HMAC_SHA256_PRF", "HMAC_SHA512_PRF"};
94 
95   @Theory
testTemplates(@romDataPoints"templateNames") String templateName)96   public void testTemplates(@FromDataPoints("templateNames") String templateName) throws Exception {
97     KeysetHandle h = KeysetHandle.generateNew(KeyTemplates.get(templateName));
98     assertThat(h.size()).isEqualTo(1);
99     assertThat(h.getAt(0).getKey().getParameters())
100         .isEqualTo(KeyTemplates.get(templateName).toParameters());
101   }
102 
103   @Test
registersPrfPrimitiveConstructor()104   public void registersPrfPrimitiveConstructor() throws Exception {
105     Prf prf =
106         MutablePrimitiveRegistry.globalInstance()
107             .getPrimitive(
108                 com.google.crypto.tink.prf.HmacPrfKey.builder()
109                     .setParameters(
110                         HmacPrfParameters.builder()
111                             .setHashType(HmacPrfParameters.HashType.SHA256)
112                             .setKeySizeBytes(32)
113                             .build())
114                     .setKeyBytes(SecretBytes.randomBytes(32))
115                     .build(),
116                 Prf.class);
117 
118     assertThat(prf).isInstanceOf(PrfHmacJce.class);
119   }
120 
121   @Theory
testCreateKeyFromRandomness(@romDataPoints"templateNames") String templateName)122   public void testCreateKeyFromRandomness(@FromDataPoints("templateNames") String templateName)
123       throws Exception {
124     byte[] keyMaterial =
125         new byte[] {
126           0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
127           25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
128           47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
129         };
130     HmacPrfParameters parameters =
131         (HmacPrfParameters) KeyTemplates.get(templateName).toParameters();
132     com.google.crypto.tink.prf.HmacPrfKey key =
133         HmacPrfKeyManager.createHmacKeyFromRandomness(
134             parameters, new ByteArrayInputStream(keyMaterial), null, InsecureSecretKeyAccess.get());
135     byte[] expectedKeyBytes = Arrays.copyOf(keyMaterial, parameters.getKeySizeBytes());
136     Key expectedKey =
137         com.google.crypto.tink.prf.HmacPrfKey.builder()
138             .setParameters(parameters)
139             .setKeyBytes(SecretBytes.copyFrom(expectedKeyBytes, InsecureSecretKeyAccess.get()))
140             .build();
141     assertTrue(key.equalsKey(expectedKey));
142   }
143 
144   @Test
testCreateKeyFromRandomness_slowInputStream_works()145   public void testCreateKeyFromRandomness_slowInputStream_works() throws Exception {
146     byte[] keyMaterial =
147         new byte[] {
148           0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
149           25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
150           47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
151         };
152     HmacPrfParameters parameters =
153         HmacPrfParameters.builder()
154             .setKeySizeBytes(64)
155             .setHashType(HmacPrfParameters.HashType.SHA512)
156             .build();
157     com.google.crypto.tink.prf.HmacPrfKey key =
158         HmacPrfKeyManager.createHmacKeyFromRandomness(
159             parameters, SlowInputStream.copyFrom(keyMaterial), null, InsecureSecretKeyAccess.get());
160     byte[] expectedKeyBytes = Arrays.copyOf(keyMaterial, parameters.getKeySizeBytes());
161     Key expectedKey =
162         com.google.crypto.tink.prf.HmacPrfKey.builder()
163             .setParameters(parameters)
164             .setKeyBytes(SecretBytes.copyFrom(expectedKeyBytes, InsecureSecretKeyAccess.get()))
165             .build();
166     assertTrue(key.equalsKey(expectedKey));
167   }
168 
169   @Test
testKeyManagerRegistered()170   public void testKeyManagerRegistered() throws Exception {
171     assertThat(
172             KeyManagerRegistry.globalInstance()
173                 .getKeyManager("type.googleapis.com/google.crypto.tink.HmacPrfKey", Prf.class))
174         .isNotNull();
175   }
176 
177   @Test
createKey_works()178   public void createKey_works() throws Exception {
179     HmacPrfParameters params =
180         HmacPrfParameters.builder()
181             .setHashType(HmacPrfParameters.HashType.SHA256)
182             .setKeySizeBytes(32)
183             .build();
184     KeysetHandle handle = KeysetHandle.generateNew(params);
185     assertThat(handle.size()).isEqualTo(1);
186     com.google.crypto.tink.prf.HmacPrfKey key =
187         (com.google.crypto.tink.prf.HmacPrfKey) handle.getAt(0).getKey();
188     assertThat(key.getParameters()).isEqualTo(params);
189   }
190 
191   @Test
createKey_otherParams_works()192   public void createKey_otherParams_works() throws Exception {
193     HmacPrfParameters params =
194         HmacPrfParameters.builder()
195             .setHashType(HmacPrfParameters.HashType.SHA512)
196             .setKeySizeBytes(32)
197             .build();
198     KeysetHandle handle = KeysetHandle.generateNew(params);
199     assertThat(handle.size()).isEqualTo(1);
200     com.google.crypto.tink.prf.HmacPrfKey key =
201         (com.google.crypto.tink.prf.HmacPrfKey) handle.getAt(0).getKey();
202     assertThat(key.getParameters()).isEqualTo(params);
203   }
204 
205   @Test
createKey_differentKeyValues_alwaysDifferent()206   public void createKey_differentKeyValues_alwaysDifferent() throws Exception {
207     HmacPrfParameters params =
208         HmacPrfParameters.builder()
209             .setHashType(HmacPrfParameters.HashType.SHA512)
210             .setKeySizeBytes(32)
211             .build();
212 
213     int numKeys = 100;
214     Set<String> keys = new TreeSet<>();
215     for (int i = 0; i < numKeys; i++) {
216       KeysetHandle handle = KeysetHandle.generateNew(params);
217       assertThat(handle.size()).isEqualTo(1);
218       com.google.crypto.tink.prf.HmacPrfKey key =
219           (com.google.crypto.tink.prf.HmacPrfKey) handle.getAt(0).getKey();
220       keys.add(Hex.encode(key.getKeyBytes().toByteArray(InsecureSecretKeyAccess.get())));
221     }
222     assertThat(keys).hasSize(numKeys);
223   }
224 
225   @Test
createPrimitiveAndUseIt_works()226   public void createPrimitiveAndUseIt_works() throws Exception {
227     HmacPrfParameters params =
228         HmacPrfParameters.builder()
229             .setHashType(HmacPrfParameters.HashType.SHA512)
230             .setKeySizeBytes(32)
231             .build();
232     KeysetHandle handle = KeysetHandle.generateNew(params);
233     assertThat(handle.size()).isEqualTo(1);
234     PrfSet prfSet = handle.getPrimitive(RegistryConfiguration.get(), PrfSet.class);
235     Prf directPrf =
236         PrfHmacJce.create((com.google.crypto.tink.prf.HmacPrfKey) handle.getAt(0).getKey());
237     assertThat(prfSet.computePrimary(new byte[0], 16))
238         .isEqualTo(directPrf.compute(new byte[0], 16));
239   }
240 
241   @Test
serializeAndDeserializeKeysets()242   public void serializeAndDeserializeKeysets() throws Exception {
243     HmacPrfParameters params =
244         HmacPrfParameters.builder()
245             .setHashType(HmacPrfParameters.HashType.SHA512)
246             .setKeySizeBytes(32)
247             .build();
248     KeysetHandle handle = KeysetHandle.generateNew(params);
249 
250     byte[] serializedKeyset =
251         TinkProtoKeysetFormat.serializeKeyset(handle, InsecureSecretKeyAccess.get());
252     KeysetHandle parsed =
253         TinkProtoKeysetFormat.parseKeyset(serializedKeyset, InsecureSecretKeyAccess.get());
254     assertTrue(parsed.equalsKeyset(handle));
255   }
256 
257   @Test
deriveHmacPrfKey_works()258   public void deriveHmacPrfKey_works() throws Exception {
259     PrfKey prfKeyForDeriver =
260         HkdfPrfKey.builder()
261             .setParameters(
262                 HkdfPrfParameters.builder()
263                     .setKeySizeBytes(32)
264                     .setHashType(HkdfPrfParameters.HashType.SHA256)
265                     .build())
266             .setKeyBytes(
267                 SecretBytes.copyFrom(
268                     Hex.decode("0102030405060708091011121314151617181920212123242526272829303132"),
269                     InsecureSecretKeyAccess.get()))
270             .build();
271     PrfBasedKeyDerivationParameters derivationParameters =
272         PrfBasedKeyDerivationParameters.builder()
273             .setDerivedKeyParameters(PredefinedPrfParameters.HMAC_SHA256_PRF)
274             .setPrfParameters(prfKeyForDeriver.getParameters())
275             .build();
276     PrfBasedKeyDerivationKey key =
277         PrfBasedKeyDerivationKey.create(
278             derivationParameters, prfKeyForDeriver, /* idRequirement= */ null);
279 
280     KeysetHandle keyset =
281         KeysetHandle.newBuilder()
282             .addEntry(KeysetHandle.importKey(key).withFixedId(112233).makePrimary())
283             .build();
284     KeysetDeriver deriver = keyset.getPrimitive(RegistryConfiguration.get(), KeysetDeriver.class);
285 
286     KeysetHandle derivedKeyset = deriver.deriveKeyset(Hex.decode("000102"));
287 
288     assertThat(derivedKeyset.size()).isEqualTo(1);
289     assertThat(
290             derivedKeyset
291                 .getAt(0)
292                 .getKey()
293                 .equalsKey(
294                     com.google.crypto.tink.prf.HmacPrfKey.builder()
295                         .setParameters(PredefinedPrfParameters.HMAC_SHA256_PRF)
296                         .setKeyBytes(
297                             SecretBytes.copyFrom(
298                                 Hex.decode(
299                                     "94e397d674deda6e965295698491a3feb69838a35f1d48143f3c4cbad9"
300                                         + "0eeb24"),
301                                 InsecureSecretKeyAccess.get()))
302                         .build()))
303         .isTrue();
304   }
305 }
306