• 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.streamingaead;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static org.junit.Assert.assertThrows;
21 
22 import com.google.crypto.tink.InsecureSecretKeyAccess;
23 import com.google.crypto.tink.KeysetHandle;
24 import com.google.crypto.tink.RegistryConfiguration;
25 import com.google.crypto.tink.StreamingAead;
26 import com.google.crypto.tink.TinkProtoKeysetFormat;
27 import com.google.crypto.tink.internal.PrimitiveRegistry;
28 import com.google.crypto.tink.proto.HashType;
29 import com.google.crypto.tink.proto.KeyData;
30 import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
31 import com.google.crypto.tink.proto.KeyStatusType;
32 import com.google.crypto.tink.proto.Keyset;
33 import com.google.crypto.tink.proto.OutputPrefixType;
34 import com.google.crypto.tink.subtle.Hex;
35 import com.google.crypto.tink.testing.StreamingTestUtil;
36 import com.google.crypto.tink.util.SecretBytes;
37 import com.google.protobuf.ByteString;
38 import java.io.IOException;
39 import java.security.GeneralSecurityException;
40 import org.junit.BeforeClass;
41 import org.junit.Test;
42 import org.junit.runner.RunWith;
43 import org.junit.runners.JUnit4;
44 
45 /** Tests for StreamingAeadWrapper. */
46 @RunWith(JUnit4.class)
47 // Fully specifying proto key/parameters types to distinguish from the programmatic ones.
48 @SuppressWarnings("UnnecessarilyFullyQualified")
49 public class StreamingAeadWrapperTest {
50   private static final String AES_GCM_HKDF_TYPE_URL =
51       "type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey";
52 
53   @BeforeClass
setUp()54   public static void setUp() throws Exception {
55     StreamingAeadConfig.register();
56   }
57 
58   @Test
encryptDecrypt_works()59   public void encryptDecrypt_works() throws Exception {
60     AesCtrHmacStreamingParameters parameters =
61         AesCtrHmacStreamingParameters.builder()
62             .setKeySizeBytes(32)
63             .setDerivedKeySizeBytes(32)
64             .setHkdfHashType(AesCtrHmacStreamingParameters.HashType.SHA256)
65             .setHmacHashType(AesCtrHmacStreamingParameters.HashType.SHA256)
66             .setHmacTagSizeBytes(16)
67             .setCiphertextSegmentSizeBytes(64)
68             .build();
69     AesCtrHmacStreamingKey key =
70         AesCtrHmacStreamingKey.create(
71             parameters,
72             SecretBytes.copyFrom(
73                 Hex.decode("abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"),
74                 InsecureSecretKeyAccess.get()));
75     KeysetHandle keysetHandle =
76         KeysetHandle.newBuilder()
77             .addEntry(KeysetHandle.importKey(key).withFixedId(42).makePrimary())
78             .build();
79 
80     StreamingAead streamingAead =
81         keysetHandle.getPrimitive(RegistryConfiguration.get(), StreamingAead.class);
82 
83     StreamingTestUtil.testEncryptDecrypt(streamingAead, 0, 20, 5);
84   }
85 
86   @Test
encryptDecrypt_usesPrimary()87   public void encryptDecrypt_usesPrimary() throws Exception {
88     AesGcmHkdfStreamingParameters aesGcmHkdfStreamingParameters =
89         AesGcmHkdfStreamingParameters.builder()
90             .setKeySizeBytes(32)
91             .setDerivedAesGcmKeySizeBytes(32)
92             .setHkdfHashType(AesGcmHkdfStreamingParameters.HashType.SHA256)
93             .setCiphertextSegmentSizeBytes(64)
94             .build();
95     AesGcmHkdfStreamingKey aesGcmHkdfStreamingKey =
96         AesGcmHkdfStreamingKey.create(
97             aesGcmHkdfStreamingParameters,
98             SecretBytes.copyFrom(
99                 Hex.decode("abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"),
100                 InsecureSecretKeyAccess.get()));
101     AesCtrHmacStreamingParameters aesCtrHmacStreamingParameters =
102         AesCtrHmacStreamingParameters.builder()
103             .setKeySizeBytes(32)
104             .setDerivedKeySizeBytes(32)
105             .setHkdfHashType(AesCtrHmacStreamingParameters.HashType.SHA256)
106             .setHmacHashType(AesCtrHmacStreamingParameters.HashType.SHA256)
107             .setHmacTagSizeBytes(16)
108             .setCiphertextSegmentSizeBytes(64)
109             .build();
110     AesCtrHmacStreamingKey aesCtrHmacStreamingKey =
111         AesCtrHmacStreamingKey.create(
112             aesCtrHmacStreamingParameters,
113             SecretBytes.copyFrom(
114                 Hex.decode("abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"),
115                 InsecureSecretKeyAccess.get()));
116     KeysetHandle fullKeysetHandle =
117         KeysetHandle.newBuilder()
118             .addEntry(KeysetHandle.importKey(aesCtrHmacStreamingKey).withFixedId(43))
119             .addEntry(KeysetHandle.importKey(aesGcmHkdfStreamingKey).withFixedId(42).makePrimary())
120             .build();
121     KeysetHandle onlyPrimaryKeysetHandle =
122         KeysetHandle.newBuilder()
123             .addEntry(KeysetHandle.importKey(aesGcmHkdfStreamingKey).withFixedId(42).makePrimary())
124             .build();
125 
126     StreamingAead fullStreamingAead =
127         fullKeysetHandle.getPrimitive(RegistryConfiguration.get(), StreamingAead.class);
128     StreamingAead onlyPrimaryStreamingAead =
129         onlyPrimaryKeysetHandle.getPrimitive(RegistryConfiguration.get(), StreamingAead.class);
130 
131     StreamingTestUtil.testEncryptDecryptDifferentInstances(
132         fullStreamingAead, onlyPrimaryStreamingAead, 0, 20, 5);
133     StreamingTestUtil.testEncryptDecryptDifferentInstances(
134         onlyPrimaryStreamingAead, fullStreamingAead, 0, 20, 5);
135   }
136 
137   @Test
encryptDecrypt_shiftedPrimaryWorks()138   public void encryptDecrypt_shiftedPrimaryWorks() throws Exception {
139     AesGcmHkdfStreamingParameters aesGcmHkdfStreamingParameters =
140         AesGcmHkdfStreamingParameters.builder()
141             .setKeySizeBytes(32)
142             .setDerivedAesGcmKeySizeBytes(32)
143             .setHkdfHashType(AesGcmHkdfStreamingParameters.HashType.SHA256)
144             .setCiphertextSegmentSizeBytes(64)
145             .build();
146     AesGcmHkdfStreamingKey aesGcmHkdfStreamingKey =
147         AesGcmHkdfStreamingKey.create(
148             aesGcmHkdfStreamingParameters,
149             SecretBytes.copyFrom(
150                 Hex.decode("abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"),
151                 InsecureSecretKeyAccess.get()));
152     AesCtrHmacStreamingParameters aesCtrHmacStreamingParameters =
153         AesCtrHmacStreamingParameters.builder()
154             .setKeySizeBytes(32)
155             .setDerivedKeySizeBytes(32)
156             .setHkdfHashType(AesCtrHmacStreamingParameters.HashType.SHA256)
157             .setHmacHashType(AesCtrHmacStreamingParameters.HashType.SHA256)
158             .setHmacTagSizeBytes(16)
159             .setCiphertextSegmentSizeBytes(64)
160             .build();
161     AesCtrHmacStreamingKey aesCtrHmacStreamingKey =
162         AesCtrHmacStreamingKey.create(
163             aesCtrHmacStreamingParameters,
164             SecretBytes.copyFrom(
165                 Hex.decode("abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"),
166                 InsecureSecretKeyAccess.get()));
167     KeysetHandle keysetHandle =
168         KeysetHandle.newBuilder()
169             .addEntry(KeysetHandle.importKey(aesCtrHmacStreamingKey).withFixedId(43))
170             .addEntry(KeysetHandle.importKey(aesGcmHkdfStreamingKey).withFixedId(42).makePrimary())
171             .build();
172     KeysetHandle shiftedPrimaryKeysetHandle =
173         KeysetHandle.newBuilder()
174             .addEntry(KeysetHandle.importKey(aesCtrHmacStreamingKey).withFixedId(43).makePrimary())
175             .addEntry(KeysetHandle.importKey(aesGcmHkdfStreamingKey).withFixedId(42))
176             .build();
177 
178     StreamingAead streamingAead =
179         keysetHandle.getPrimitive(RegistryConfiguration.get(), StreamingAead.class);
180     StreamingAead shiftedPrimaryStreamingAead =
181         shiftedPrimaryKeysetHandle.getPrimitive(RegistryConfiguration.get(), StreamingAead.class);
182 
183     StreamingTestUtil.testEncryptDecryptDifferentInstances(
184         streamingAead, shiftedPrimaryStreamingAead, 0, 20, 5);
185     StreamingTestUtil.testEncryptDecryptDifferentInstances(
186         shiftedPrimaryStreamingAead, streamingAead, 0, 20, 5);
187   }
188 
189   @Test
wrongKey_throws()190   public void wrongKey_throws() throws Exception {
191     AesGcmHkdfStreamingParameters aesGcmHkdfStreamingParameters =
192         AesGcmHkdfStreamingParameters.builder()
193             .setKeySizeBytes(32)
194             .setDerivedAesGcmKeySizeBytes(32)
195             .setHkdfHashType(AesGcmHkdfStreamingParameters.HashType.SHA256)
196             .setCiphertextSegmentSizeBytes(64)
197             .build();
198     AesGcmHkdfStreamingKey aesGcmHkdfStreamingKey =
199         AesGcmHkdfStreamingKey.create(
200             aesGcmHkdfStreamingParameters,
201             SecretBytes.copyFrom(
202                 Hex.decode("abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"),
203                 InsecureSecretKeyAccess.get()));
204     AesCtrHmacStreamingParameters aesCtrHmacStreamingParameters =
205         AesCtrHmacStreamingParameters.builder()
206             .setKeySizeBytes(32)
207             .setDerivedKeySizeBytes(32)
208             .setHkdfHashType(AesCtrHmacStreamingParameters.HashType.SHA256)
209             .setHmacHashType(AesCtrHmacStreamingParameters.HashType.SHA256)
210             .setHmacTagSizeBytes(16)
211             .setCiphertextSegmentSizeBytes(64)
212             .build();
213     AesCtrHmacStreamingKey aesCtrHmacStreamingKey =
214         AesCtrHmacStreamingKey.create(
215             aesCtrHmacStreamingParameters,
216             SecretBytes.copyFrom(
217                 Hex.decode("abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"),
218                 InsecureSecretKeyAccess.get()));
219     KeysetHandle aesCtrHmacKeysetHandle =
220         KeysetHandle.newBuilder()
221             .addEntry(KeysetHandle.importKey(aesCtrHmacStreamingKey).withFixedId(43).makePrimary())
222             .build();
223     KeysetHandle aesGcmHkdfKeysetHandle =
224         KeysetHandle.newBuilder()
225             .addEntry(KeysetHandle.importKey(aesGcmHkdfStreamingKey).withFixedId(42).makePrimary())
226             .build();
227 
228     StreamingAead aesCtrHmac =
229         aesCtrHmacKeysetHandle.getPrimitive(RegistryConfiguration.get(), StreamingAead.class);
230     StreamingAead aesGcmHkdf =
231         aesGcmHkdfKeysetHandle.getPrimitive(RegistryConfiguration.get(), StreamingAead.class);
232 
233     assertThrows(
234         IOException.class,
235         () ->
236             StreamingTestUtil.testEncryptDecryptDifferentInstances(
237                 aesCtrHmac, aesGcmHkdf, 0, 20, 5));
238     assertThrows(
239         IOException.class,
240         () ->
241             StreamingTestUtil.testEncryptDecryptDifferentInstances(
242                 aesGcmHkdf, aesCtrHmac, 0, 20, 5));
243   }
244 
245   @Test
testEncryptDecryptWithTinkKey()246   public void testEncryptDecryptWithTinkKey() throws Exception {
247     com.google.crypto.tink.proto.AesGcmHkdfStreamingKey protoKey1 =
248         com.google.crypto.tink.proto.AesGcmHkdfStreamingKey.newBuilder()
249             .setVersion(0)
250             .setKeyValue(ByteString.copyFromUtf8("0123456789012345"))
251             .setParams(
252                 com.google.crypto.tink.proto.AesGcmHkdfStreamingParams.newBuilder()
253                     .setHkdfHashType(HashType.SHA1)
254                     .setDerivedKeySize(16)
255                     .setCiphertextSegmentSize(512 * 1024))
256             .build();
257     Keyset.Key keysetKey1 =
258         Keyset.Key.newBuilder()
259             .setKeyData(
260                 KeyData.newBuilder()
261                     .setTypeUrl(AES_GCM_HKDF_TYPE_URL)
262                     .setValue(protoKey1.toByteString())
263                     .setKeyMaterialType(KeyMaterialType.SYMMETRIC))
264             .setKeyId(1)
265             .setOutputPrefixType(OutputPrefixType.TINK)
266             .setStatus(KeyStatusType.ENABLED)
267             .build();
268     com.google.crypto.tink.proto.AesGcmHkdfStreamingKey protoKey2 =
269         com.google.crypto.tink.proto.AesGcmHkdfStreamingKey.newBuilder()
270             .setVersion(0)
271             .setKeyValue(ByteString.copyFromUtf8("0123456789abcdef"))
272             .setParams(
273                 com.google.crypto.tink.proto.AesGcmHkdfStreamingParams.newBuilder()
274                     .setHkdfHashType(HashType.SHA1)
275                     .setDerivedKeySize(16)
276                     .setCiphertextSegmentSize(512 * 1024))
277             .build();
278     Keyset.Key keysetKey2 =
279         Keyset.Key.newBuilder()
280             .setKeyData(
281                 KeyData.newBuilder()
282                     .setTypeUrl(AES_GCM_HKDF_TYPE_URL)
283                     .setValue(protoKey2.toByteString())
284                     .setKeyMaterialType(KeyMaterialType.SYMMETRIC))
285             .setKeyId(2)
286             .setOutputPrefixType(OutputPrefixType.RAW)
287             .setStatus(KeyStatusType.ENABLED)
288             .build();
289 
290     Keyset keyset =
291         Keyset.newBuilder().addKey(keysetKey1).addKey(keysetKey2).setPrimaryKeyId(1).build();
292     KeysetHandle keysetHandle =
293         TinkProtoKeysetFormat.parseKeyset(keyset.toByteArray(), InsecureSecretKeyAccess.get());
294     StreamingAead streamingAead =
295         keysetHandle.getPrimitive(RegistryConfiguration.get(), StreamingAead.class);
296 
297     StreamingTestUtil.testEncryptionAndDecryption(streamingAead, streamingAead);
298   }
299 
300   @Test
registerToInternalPrimitiveRegistry_works()301   public void registerToInternalPrimitiveRegistry_works() throws Exception {
302     PrimitiveRegistry.Builder initialBuilder = PrimitiveRegistry.builder();
303     PrimitiveRegistry initialRegistry = initialBuilder.build();
304     PrimitiveRegistry.Builder processedBuilder = PrimitiveRegistry.builder(initialRegistry);
305 
306     StreamingAeadWrapper.registerToInternalPrimitiveRegistry(processedBuilder);
307     PrimitiveRegistry processedRegistry = processedBuilder.build();
308 
309     assertThrows(
310         GeneralSecurityException.class,
311         () -> initialRegistry.getInputPrimitiveClass(StreamingAead.class));
312     assertThat(processedRegistry.getInputPrimitiveClass(StreamingAead.class))
313         .isEqualTo(StreamingAead.class);
314   }
315 }
316