• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 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.daead;
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.aead.AesGcmSivKey;
24 import com.google.crypto.tink.aead.AesGcmSivParameters;
25 import com.google.crypto.tink.internal.KeyTester;
26 import com.google.crypto.tink.subtle.Hex;
27 import com.google.crypto.tink.util.Bytes;
28 import com.google.crypto.tink.util.SecretBytes;
29 import java.security.GeneralSecurityException;
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 import org.junit.runners.JUnit4;
33 
34 @RunWith(JUnit4.class)
35 public final class AesSivKeyTest {
36   @Test
buildNoPrefixVariantAndGetProperties()37   public void buildNoPrefixVariantAndGetProperties() throws Exception {
38     AesSivParameters parameters =
39         AesSivParameters.builder()
40             .setKeySizeBytes(32)
41             .setVariant(AesSivParameters.Variant.NO_PREFIX)
42             .build();
43     assertThat(parameters.hasIdRequirement()).isFalse();
44     SecretBytes keyBytes = SecretBytes.randomBytes(32);
45 
46     AesSivKey key = AesSivKey.builder().setParameters(parameters).setKeyBytes(keyBytes).build();
47 
48     assertThat(key.getParameters()).isEqualTo(parameters);
49     assertThat(key.getKeyBytes()).isEqualTo(keyBytes);
50     assertThat(key.getOutputPrefix()).isEqualTo(Bytes.copyFrom(new byte[] {}));
51     assertThat(key.getIdRequirementOrNull()).isNull();
52   }
53 
54   @Test
buildTinkVariantAndGetProperties()55   public void buildTinkVariantAndGetProperties() throws Exception {
56     AesSivParameters parameters =
57         AesSivParameters.builder()
58             .setKeySizeBytes(32)
59             .setVariant(AesSivParameters.Variant.TINK)
60             .build();
61     assertThat(parameters.hasIdRequirement()).isTrue();
62     SecretBytes keyBytes = SecretBytes.randomBytes(32);
63 
64     AesSivKey key =
65         AesSivKey.builder()
66             .setParameters(parameters)
67             .setKeyBytes(keyBytes)
68             .setIdRequirement(0x66AABBCC)
69             .build();
70 
71     assertThat(key.getParameters()).isEqualTo(parameters);
72     assertThat(key.getKeyBytes()).isEqualTo(keyBytes);
73     assertThat(key.getOutputPrefix()).isEqualTo(Bytes.copyFrom(Hex.decode("0166AABBCC")));
74     assertThat(key.getIdRequirementOrNull()).isEqualTo(0x66AABBCC);
75   }
76 
77   @Test
buildCrunchyVariantAndGetProperties()78   public void buildCrunchyVariantAndGetProperties() throws Exception {
79     AesSivParameters parameters =
80         AesSivParameters.builder()
81             .setKeySizeBytes(32)
82             .setVariant(AesSivParameters.Variant.CRUNCHY)
83             .build();
84     assertThat(parameters.hasIdRequirement()).isTrue();
85     SecretBytes keyBytes = SecretBytes.randomBytes(32);
86 
87     AesSivKey key =
88         AesSivKey.builder()
89             .setParameters(parameters)
90             .setKeyBytes(keyBytes)
91             .setIdRequirement(0x66AABBCC)
92             .build();
93 
94     assertThat(key.getParameters()).isEqualTo(parameters);
95     assertThat(key.getKeyBytes()).isEqualTo(keyBytes);
96     assertThat(key.getOutputPrefix()).isEqualTo(Bytes.copyFrom(Hex.decode("0066AABBCC")));
97     assertThat(key.getIdRequirementOrNull()).isEqualTo(0x66AABBCC);
98   }
99 
100   @Test
emptyBuild_fails()101   public void emptyBuild_fails() throws Exception {
102     assertThrows(IllegalArgumentException.class, () -> AesSivKey.builder().build());
103   }
104 
105   @Test
buildWithoutParameters_fails()106   public void buildWithoutParameters_fails() throws Exception {
107     assertThrows(
108         IllegalArgumentException.class,
109         () -> AesSivKey.builder().setKeyBytes(SecretBytes.randomBytes(32)).build());
110   }
111 
112   @Test
buildWithoutKeyBytes_fails()113   public void buildWithoutKeyBytes_fails() throws Exception {
114     AesSivParameters parameters =
115         AesSivParameters.builder()
116             .setKeySizeBytes(32)
117             .setVariant(AesSivParameters.Variant.NO_PREFIX)
118             .build();
119     assertThrows(
120         IllegalArgumentException.class,
121         () -> AesSivKey.builder().setParameters(parameters).build());
122   }
123 
124   @Test
paramtersRequireIdButIdIsNotSetInBuild_fails()125   public void paramtersRequireIdButIdIsNotSetInBuild_fails() throws Exception {
126     AesSivParameters parametersWithIdRequirement =
127         AesSivParameters.builder()
128             .setKeySizeBytes(32)
129             .setVariant(AesSivParameters.Variant.TINK)
130             .build();
131     assertThat(parametersWithIdRequirement.hasIdRequirement()).isTrue();
132     assertThrows(
133         GeneralSecurityException.class,
134         () ->
135             AesSivKey.builder()
136                 .setKeyBytes(SecretBytes.randomBytes(32))
137                 .setParameters(parametersWithIdRequirement)
138                 .build());
139   }
140 
141   @Test
buildBadKeySize_fails()142   public void buildBadKeySize_fails() throws Exception {
143     AesSivParameters parameters =
144         AesSivParameters.builder()
145             .setKeySizeBytes(32)
146             .setVariant(AesSivParameters.Variant.NO_PREFIX)
147             .build();
148     assertThrows(
149         GeneralSecurityException.class,
150         () ->
151             AesSivKey.builder()
152                 .setParameters(parameters)
153                 .setKeyBytes(SecretBytes.randomBytes(16))
154                 .build());
155   }
156 
157   @Test
testEqualities()158   public void testEqualities() throws Exception {
159     SecretBytes keyBytes32 = SecretBytes.randomBytes(32);
160     SecretBytes keyBytes32Copy =
161         SecretBytes.copyFrom(
162             keyBytes32.toByteArray(InsecureSecretKeyAccess.get()), InsecureSecretKeyAccess.get());
163     SecretBytes keyBytes32Diff = SecretBytes.randomBytes(32);
164     SecretBytes keyBytes64 = SecretBytes.randomBytes(64);
165 
166     AesSivParameters noPrefixParametersKeySize32 =
167         AesSivParameters.builder()
168             .setKeySizeBytes(32)
169             .setVariant(AesSivParameters.Variant.NO_PREFIX)
170             .build();
171     AesSivParameters tinkPrefixParametersKeySize32 =
172         AesSivParameters.builder()
173             .setKeySizeBytes(32)
174             .setVariant(AesSivParameters.Variant.TINK)
175             .build();
176     AesSivParameters crunchyPrefixParametersKeySize32 =
177         AesSivParameters.builder()
178             .setKeySizeBytes(32)
179             .setVariant(AesSivParameters.Variant.CRUNCHY)
180             .build();
181     AesSivParameters noPrefixParametersKeySize64 =
182         AesSivParameters.builder()
183             .setKeySizeBytes(64)
184             .setVariant(AesSivParameters.Variant.NO_PREFIX)
185             .build();
186 
187     new KeyTester()
188         .addEqualityGroup(
189             "No prefix, keyBytes32",
190             AesSivKey.builder()
191                 .setParameters(noPrefixParametersKeySize32)
192                 .setKeyBytes(keyBytes32)
193                 .build(),
194             // The same key built twice must be equal.
195             AesSivKey.builder()
196                 .setParameters(noPrefixParametersKeySize32)
197                 .setKeyBytes(keyBytes32)
198                 .build(),
199             // The same key built with a copy of key bytes must be equal.
200             AesSivKey.builder()
201                 .setParameters(noPrefixParametersKeySize32)
202                 .setKeyBytes(keyBytes32Copy)
203                 .build(),
204             // Setting id requirement to null is equal to not setting it.
205             AesSivKey.builder()
206                 .setParameters(noPrefixParametersKeySize32)
207                 .setKeyBytes(keyBytes32)
208                 .setIdRequirement(null)
209                 .build())
210         // This group checks that keys with different key bytes are not equal.
211         .addEqualityGroup(
212             "No prefix, newly generated keyBytes32",
213             AesSivKey.builder()
214                 .setParameters(noPrefixParametersKeySize32)
215                 .setKeyBytes(keyBytes32Diff)
216                 .build())
217         // This group checks that keys with different key sizes are not equal.
218         .addEqualityGroup(
219             "No prefix, keyBytes64",
220             AesSivKey.builder()
221                 .setParameters(noPrefixParametersKeySize64)
222                 .setKeyBytes(keyBytes64)
223                 .build())
224         .addEqualityGroup(
225             "Tink with key id 1907, keyBytes32",
226             AesSivKey.builder()
227                 .setParameters(tinkPrefixParametersKeySize32)
228                 .setKeyBytes(keyBytes32)
229                 .setIdRequirement(1907)
230                 .build(),
231             AesSivKey.builder()
232                 .setParameters(tinkPrefixParametersKeySize32)
233                 .setKeyBytes(keyBytes32Copy)
234                 .setIdRequirement(1907)
235                 .build())
236         // This group checks that keys with different key ids are not equal.
237         .addEqualityGroup(
238             "Tink with key id 1908, keyBytes32",
239             AesSivKey.builder()
240                 .setParameters(tinkPrefixParametersKeySize32)
241                 .setKeyBytes(keyBytes32)
242                 .setIdRequirement(1908)
243                 .build())
244         // This groups checks that keys with different output prefix types are not equal.
245         .addEqualityGroup(
246             "Crunchy with key id 1907, keyBytes32",
247             AesSivKey.builder()
248                 .setParameters(crunchyPrefixParametersKeySize32)
249                 .setKeyBytes(keyBytes32)
250                 .setIdRequirement(1907)
251                 .build())
252         .doTests();
253   }
254 
255   @Test
testDifferentKeyTypesEquality_fails()256   public void testDifferentKeyTypesEquality_fails() throws Exception {
257     AesSivParameters aesSivParameters =
258         AesSivParameters.builder()
259             .setKeySizeBytes(32)
260             .setVariant(AesSivParameters.Variant.NO_PREFIX)
261             .build();
262 
263     AesGcmSivParameters aesGcmSivParameters =
264         AesGcmSivParameters.builder()
265             .setKeySizeBytes(32)
266             .setVariant(AesGcmSivParameters.Variant.NO_PREFIX)
267             .build();
268     SecretBytes keyBytes = SecretBytes.randomBytes(32);
269 
270     AesSivKey aesSivKey =
271         AesSivKey.builder().setParameters(aesSivParameters).setKeyBytes(keyBytes).build();
272     AesGcmSivKey aesGcmSivKey =
273         AesGcmSivKey.builder().setParameters(aesGcmSivParameters).setKeyBytes(keyBytes).build();
274 
275     assertThat(aesSivKey.equalsKey(aesGcmSivKey)).isFalse();
276   }
277 }
278