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.aead; 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.internal.KeyTester; 24 import com.google.crypto.tink.subtle.Hex; 25 import com.google.crypto.tink.util.Bytes; 26 import com.google.crypto.tink.util.SecretBytes; 27 import java.security.GeneralSecurityException; 28 import org.junit.Test; 29 import org.junit.runner.RunWith; 30 import org.junit.runners.JUnit4; 31 32 @RunWith(JUnit4.class) 33 public final class AesCtrHmacAeadKeyTest { 34 @Test buildNoPrefixVariantAndGetProperties()35 public void buildNoPrefixVariantAndGetProperties() throws Exception { 36 AesCtrHmacAeadParameters parameters = 37 AesCtrHmacAeadParameters.builder() 38 .setAesKeySizeBytes(16) 39 .setHmacKeySizeBytes(16) 40 .setTagSizeBytes(10) 41 .setIvSizeBytes(16) 42 .setHashType(AesCtrHmacAeadParameters.HashType.SHA256) 43 .setVariant(AesCtrHmacAeadParameters.Variant.NO_PREFIX) 44 .build(); 45 assertThat(parameters.hasIdRequirement()).isFalse(); 46 SecretBytes aesKeyBytes = SecretBytes.randomBytes(16); 47 SecretBytes hmacKeyBytes = SecretBytes.randomBytes(16); 48 AesCtrHmacAeadKey key = 49 AesCtrHmacAeadKey.builder() 50 .setParameters(parameters) 51 .setAesKeyBytes(aesKeyBytes) 52 .setHmacKeyBytes(hmacKeyBytes) 53 .build(); 54 assertThat(key.getParameters()).isEqualTo(parameters); 55 assertThat(key.getAesKeyBytes()).isEqualTo(aesKeyBytes); 56 assertThat(key.getHmacKeyBytes()).isEqualTo(hmacKeyBytes); 57 assertThat(key.getOutputPrefix()).isEqualTo(Bytes.copyFrom(new byte[] {})); 58 assertThat(key.getIdRequirementOrNull()).isNull(); 59 } 60 61 @Test buildTinkVariantAndGetProperties()62 public void buildTinkVariantAndGetProperties() throws Exception { 63 AesCtrHmacAeadParameters parameters = 64 AesCtrHmacAeadParameters.builder() 65 .setAesKeySizeBytes(16) 66 .setHmacKeySizeBytes(16) 67 .setTagSizeBytes(10) 68 .setIvSizeBytes(16) 69 .setHashType(AesCtrHmacAeadParameters.HashType.SHA256) 70 .setVariant(AesCtrHmacAeadParameters.Variant.TINK) 71 .build(); 72 assertThat(parameters.hasIdRequirement()).isTrue(); 73 SecretBytes aesKeyBytes = SecretBytes.randomBytes(16); 74 SecretBytes hmacKeyBytes = SecretBytes.randomBytes(16); 75 AesCtrHmacAeadKey key = 76 AesCtrHmacAeadKey.builder() 77 .setParameters(parameters) 78 .setAesKeyBytes(aesKeyBytes) 79 .setHmacKeyBytes(hmacKeyBytes) 80 .setIdRequirement(0x66AABBCC) 81 .build(); 82 assertThat(key.getParameters()).isEqualTo(parameters); 83 assertThat(key.getAesKeyBytes()).isEqualTo(aesKeyBytes); 84 assertThat(key.getHmacKeyBytes()).isEqualTo(hmacKeyBytes); 85 assertThat(key.getOutputPrefix()).isEqualTo(Bytes.copyFrom(Hex.decode("0166AABBCC"))); 86 assertThat(key.getIdRequirementOrNull()).isEqualTo(0x66AABBCC); 87 } 88 89 @Test buildCrunchyVariantAndGetProperties()90 public void buildCrunchyVariantAndGetProperties() throws Exception { 91 AesCtrHmacAeadParameters parameters = 92 AesCtrHmacAeadParameters.builder() 93 .setAesKeySizeBytes(16) 94 .setHmacKeySizeBytes(16) 95 .setTagSizeBytes(10) 96 .setIvSizeBytes(16) 97 .setHashType(AesCtrHmacAeadParameters.HashType.SHA256) 98 .setVariant(AesCtrHmacAeadParameters.Variant.CRUNCHY) 99 .build(); 100 assertThat(parameters.hasIdRequirement()).isTrue(); 101 SecretBytes aesKeyBytes = SecretBytes.randomBytes(16); 102 SecretBytes hmacKeyBytes = SecretBytes.randomBytes(16); 103 AesCtrHmacAeadKey key = 104 AesCtrHmacAeadKey.builder() 105 .setParameters(parameters) 106 .setAesKeyBytes(aesKeyBytes) 107 .setHmacKeyBytes(hmacKeyBytes) 108 .setIdRequirement(0x66AABBCC) 109 .build(); 110 assertThat(key.getParameters()).isEqualTo(parameters); 111 assertThat(key.getAesKeyBytes()).isEqualTo(aesKeyBytes); 112 assertThat(key.getHmacKeyBytes()).isEqualTo(hmacKeyBytes); 113 assertThat(key.getOutputPrefix()).isEqualTo(Bytes.copyFrom(Hex.decode("0066AABBCC"))); 114 assertThat(key.getIdRequirementOrNull()).isEqualTo(0x66AABBCC); 115 } 116 117 @Test emptyBuild_fails()118 public void emptyBuild_fails() throws Exception { 119 assertThrows(GeneralSecurityException.class, () -> AesCtrHmacAeadKey.builder().build()); 120 } 121 122 @Test buildWithoutParameters_fails()123 public void buildWithoutParameters_fails() throws Exception { 124 assertThrows( 125 GeneralSecurityException.class, 126 () -> 127 AesCtrHmacAeadKey.builder() 128 .setAesKeyBytes(SecretBytes.randomBytes(32)) 129 .setHmacKeyBytes(SecretBytes.randomBytes(32)) 130 .build()); 131 } 132 133 @Test buildWithoutKeyBytes_fails()134 public void buildWithoutKeyBytes_fails() throws Exception { 135 AesCtrHmacAeadParameters parameters = 136 AesCtrHmacAeadParameters.builder() 137 .setAesKeySizeBytes(16) 138 .setHmacKeySizeBytes(16) 139 .setTagSizeBytes(10) 140 .setIvSizeBytes(16) 141 .setHashType(AesCtrHmacAeadParameters.HashType.SHA256) 142 .setVariant(AesCtrHmacAeadParameters.Variant.NO_PREFIX) 143 .build(); 144 assertThrows( 145 GeneralSecurityException.class, 146 () -> AesCtrHmacAeadKey.builder().setParameters(parameters).build()); 147 } 148 149 @Test paramtersRequireIdButIdIsNotSetInBuild_fails()150 public void paramtersRequireIdButIdIsNotSetInBuild_fails() throws Exception { 151 AesCtrHmacAeadParameters parametersWithIdRequirement = 152 AesCtrHmacAeadParameters.builder() 153 .setAesKeySizeBytes(16) 154 .setHmacKeySizeBytes(16) 155 .setTagSizeBytes(10) 156 .setIvSizeBytes(16) 157 .setHashType(AesCtrHmacAeadParameters.HashType.SHA256) 158 .setVariant(AesCtrHmacAeadParameters.Variant.TINK) 159 .build(); 160 assertThat(parametersWithIdRequirement.hasIdRequirement()).isTrue(); 161 assertThrows( 162 GeneralSecurityException.class, 163 () -> 164 AesCtrHmacAeadKey.builder() 165 .setAesKeyBytes(SecretBytes.randomBytes(16)) 166 .setHmacKeyBytes(SecretBytes.randomBytes(16)) 167 .setParameters(parametersWithIdRequirement) 168 .build()); 169 } 170 171 @Test paramtersDoesNotRequireIdButIdIsSetInBuild_fails()172 public void paramtersDoesNotRequireIdButIdIsSetInBuild_fails() throws Exception { 173 AesCtrHmacAeadParameters parametersWithoutIdRequirement = 174 AesCtrHmacAeadParameters.builder() 175 .setAesKeySizeBytes(16) 176 .setHmacKeySizeBytes(16) 177 .setTagSizeBytes(10) 178 .setIvSizeBytes(16) 179 .setHashType(AesCtrHmacAeadParameters.HashType.SHA256) 180 .setVariant(AesCtrHmacAeadParameters.Variant.NO_PREFIX) 181 .build(); 182 assertThat(parametersWithoutIdRequirement.hasIdRequirement()).isFalse(); 183 assertThrows( 184 GeneralSecurityException.class, 185 () -> 186 AesCtrHmacAeadKey.builder() 187 .setAesKeyBytes(SecretBytes.randomBytes(16)) 188 .setHmacKeyBytes(SecretBytes.randomBytes(16)) 189 .setParameters(parametersWithoutIdRequirement) 190 .setIdRequirement(0x66AABBCC) 191 .build()); 192 } 193 194 @Test build_keyTooSmall_fails()195 public void build_keyTooSmall_fails() throws Exception { 196 AesCtrHmacAeadParameters parameters = 197 AesCtrHmacAeadParameters.builder() 198 .setAesKeySizeBytes(32) 199 .setHmacKeySizeBytes(32) 200 .setTagSizeBytes(10) 201 .setIvSizeBytes(16) 202 .setHashType(AesCtrHmacAeadParameters.HashType.SHA256) 203 .setVariant(AesCtrHmacAeadParameters.Variant.NO_PREFIX) 204 .build(); 205 assertThrows( 206 GeneralSecurityException.class, 207 () -> 208 AesCtrHmacAeadKey.builder() 209 .setParameters(parameters) 210 .setAesKeyBytes(SecretBytes.randomBytes(16)) 211 .setHmacKeyBytes(SecretBytes.randomBytes(16)) 212 .build()); 213 } 214 215 @Test build_keyTooLarge_fails()216 public void build_keyTooLarge_fails() throws Exception { 217 AesCtrHmacAeadParameters parameters = 218 AesCtrHmacAeadParameters.builder() 219 .setAesKeySizeBytes(16) 220 .setHmacKeySizeBytes(16) 221 .setTagSizeBytes(10) 222 .setIvSizeBytes(16) 223 .setHashType(AesCtrHmacAeadParameters.HashType.SHA256) 224 .setVariant(AesCtrHmacAeadParameters.Variant.NO_PREFIX) 225 .build(); 226 assertThrows( 227 GeneralSecurityException.class, 228 () -> 229 AesCtrHmacAeadKey.builder() 230 .setParameters(parameters) 231 .setAesKeyBytes(SecretBytes.randomBytes(32)) 232 .setHmacKeyBytes(SecretBytes.randomBytes(32)) 233 .build()); 234 } 235 236 @Test testEqualities()237 public void testEqualities() throws Exception { 238 SecretBytes keyBytes1 = SecretBytes.randomBytes(32); 239 SecretBytes keyBytes1Copy = 240 SecretBytes.copyFrom( 241 keyBytes1.toByteArray(InsecureSecretKeyAccess.get()), InsecureSecretKeyAccess.get()); 242 SecretBytes keyBytes2 = SecretBytes.randomBytes(32); 243 SecretBytes keyBytes16 = SecretBytes.randomBytes(16); 244 245 AesCtrHmacAeadParameters noPrefixParameters = 246 AesCtrHmacAeadParameters.builder() 247 .setAesKeySizeBytes(32) 248 .setHmacKeySizeBytes(32) 249 .setTagSizeBytes(10) 250 .setIvSizeBytes(16) 251 .setHashType(AesCtrHmacAeadParameters.HashType.SHA256) 252 .setVariant(AesCtrHmacAeadParameters.Variant.NO_PREFIX) 253 .build(); 254 AesCtrHmacAeadParameters noPrefixParameters16 = 255 AesCtrHmacAeadParameters.builder() 256 .setAesKeySizeBytes(16) 257 .setHmacKeySizeBytes(16) 258 .setTagSizeBytes(10) 259 .setIvSizeBytes(16) 260 .setHashType(AesCtrHmacAeadParameters.HashType.SHA256) 261 .setVariant(AesCtrHmacAeadParameters.Variant.NO_PREFIX) 262 .build(); 263 AesCtrHmacAeadParameters tinkPrefixParameters = 264 AesCtrHmacAeadParameters.builder() 265 .setAesKeySizeBytes(32) 266 .setHmacKeySizeBytes(32) 267 .setTagSizeBytes(10) 268 .setIvSizeBytes(16) 269 .setHashType(AesCtrHmacAeadParameters.HashType.SHA256) 270 .setVariant(AesCtrHmacAeadParameters.Variant.TINK) 271 .build(); 272 AesCtrHmacAeadParameters crunchyPrefixParameters = 273 AesCtrHmacAeadParameters.builder() 274 .setAesKeySizeBytes(32) 275 .setHmacKeySizeBytes(32) 276 .setTagSizeBytes(10) 277 .setIvSizeBytes(16) 278 .setHashType(AesCtrHmacAeadParameters.HashType.SHA256) 279 .setVariant(AesCtrHmacAeadParameters.Variant.CRUNCHY) 280 .build(); 281 AesCtrHmacAeadParameters noPrefixParametersSha512 = 282 AesCtrHmacAeadParameters.builder() 283 .setAesKeySizeBytes(32) 284 .setHmacKeySizeBytes(32) 285 .setTagSizeBytes(10) 286 .setIvSizeBytes(16) 287 .setHashType(AesCtrHmacAeadParameters.HashType.SHA512) 288 .setVariant(AesCtrHmacAeadParameters.Variant.NO_PREFIX) 289 .build(); 290 AesCtrHmacAeadParameters noPrefixParametersIvSize12 = 291 AesCtrHmacAeadParameters.builder() 292 .setAesKeySizeBytes(32) 293 .setHmacKeySizeBytes(32) 294 .setTagSizeBytes(10) 295 .setIvSizeBytes(12) 296 .setHashType(AesCtrHmacAeadParameters.HashType.SHA256) 297 .setVariant(AesCtrHmacAeadParameters.Variant.NO_PREFIX) 298 .build(); 299 new KeyTester() 300 .addEqualityGroup( 301 "No prefix, keyBytes1", 302 AesCtrHmacAeadKey.builder() 303 .setParameters(noPrefixParameters) 304 .setAesKeyBytes(keyBytes1) 305 .setHmacKeyBytes(keyBytes1) 306 .build(), 307 // the same key built twice must be equal 308 AesCtrHmacAeadKey.builder() 309 .setParameters(noPrefixParameters) 310 .setAesKeyBytes(keyBytes1) 311 .setHmacKeyBytes(keyBytes1) 312 .build(), 313 // the same key built with a copy of key bytes must be equal 314 AesCtrHmacAeadKey.builder() 315 .setParameters(noPrefixParameters) 316 .setAesKeyBytes(keyBytes1Copy) 317 .setHmacKeyBytes(keyBytes1Copy) 318 .build(), 319 // setting id requirement to null is equal to not setting it 320 AesCtrHmacAeadKey.builder() 321 .setParameters(noPrefixParameters) 322 .setAesKeyBytes(keyBytes1) 323 .setHmacKeyBytes(keyBytes1) 324 .setIdRequirement(null) 325 .build()) 326 // This 2 groups check that keys with different key bytes are not equal 327 .addEqualityGroup( 328 "No prefix, different aes key bytes", 329 AesCtrHmacAeadKey.builder() 330 .setParameters(noPrefixParameters) 331 .setAesKeyBytes(keyBytes2) 332 .setHmacKeyBytes(keyBytes1) 333 .build()) 334 .addEqualityGroup( 335 "No prefix, different hmac key bytes", 336 AesCtrHmacAeadKey.builder() 337 .setParameters(noPrefixParameters) 338 .setAesKeyBytes(keyBytes1) 339 .setHmacKeyBytes(keyBytes2) 340 .build()) 341 // This group checks that keys with different parameters are not equal 342 .addEqualityGroup( 343 "No prefix with SHA512, keyBytes1", 344 AesCtrHmacAeadKey.builder() 345 .setParameters(noPrefixParametersSha512) 346 .setAesKeyBytes(keyBytes1) 347 .setHmacKeyBytes(keyBytes1) 348 .build()) 349 .addEqualityGroup( 350 "No prefix, keyBytes16", 351 AesCtrHmacAeadKey.builder() 352 .setParameters(noPrefixParameters16) 353 .setAesKeyBytes(keyBytes16) 354 .setHmacKeyBytes(keyBytes16) 355 .build()) 356 .addEqualityGroup( 357 "Tink with key id 1907, keyBytes1", 358 AesCtrHmacAeadKey.builder() 359 .setParameters(tinkPrefixParameters) 360 .setAesKeyBytes(keyBytes1) 361 .setHmacKeyBytes(keyBytes1) 362 .setIdRequirement(1907) 363 .build(), 364 AesCtrHmacAeadKey.builder() 365 .setParameters(tinkPrefixParameters) 366 .setAesKeyBytes(keyBytes1Copy) 367 .setHmacKeyBytes(keyBytes1Copy) 368 .setIdRequirement(1907) 369 .build()) 370 .addEqualityGroup( 371 "No prefix, IV size 12", 372 AesCtrHmacAeadKey.builder() 373 .setParameters(noPrefixParametersIvSize12) 374 .setAesKeyBytes(keyBytes1) 375 .setHmacKeyBytes(keyBytes1) 376 .build()) 377 // This group checks that keys with different key ids are not equal 378 .addEqualityGroup( 379 "Tink with key id 1908, keyBytes1", 380 AesCtrHmacAeadKey.builder() 381 .setParameters(tinkPrefixParameters) 382 .setAesKeyBytes(keyBytes1) 383 .setHmacKeyBytes(keyBytes1) 384 .setIdRequirement(1908) 385 .build()) 386 // This group checks that keys with different output prefix types are not equal 387 .addEqualityGroup( 388 "Crunchy with key id 1907, keyBytes1", 389 AesCtrHmacAeadKey.builder() 390 .setParameters(crunchyPrefixParameters) 391 .setAesKeyBytes(keyBytes1) 392 .setHmacKeyBytes(keyBytes1) 393 .setIdRequirement(1907) 394 .build()) 395 .doTests(); 396 } 397 398 @Test testDifferentKeyTypesEquality_fails()399 public void testDifferentKeyTypesEquality_fails() throws Exception { 400 AesGcmParameters aesGcmParameters = 401 AesGcmParameters.builder() 402 .setKeySizeBytes(16) 403 .setIvSizeBytes(16) 404 .setTagSizeBytes(16) 405 .setVariant(AesGcmParameters.Variant.NO_PREFIX) 406 .build(); 407 408 AesCtrHmacAeadParameters aesCtrHmacAeadParameters = 409 AesCtrHmacAeadParameters.builder() 410 .setAesKeySizeBytes(16) 411 .setHmacKeySizeBytes(16) 412 .setTagSizeBytes(16) 413 .setIvSizeBytes(16) 414 .setHashType(AesCtrHmacAeadParameters.HashType.SHA256) 415 .setVariant(AesCtrHmacAeadParameters.Variant.NO_PREFIX) 416 .build(); 417 418 SecretBytes keyBytes = SecretBytes.randomBytes(16); 419 AesGcmKey aesGcmKey = 420 AesGcmKey.builder().setParameters(aesGcmParameters).setKeyBytes(keyBytes).build(); 421 AesCtrHmacAeadKey aesCtrHmacAeadKey = 422 AesCtrHmacAeadKey.builder() 423 .setParameters(aesCtrHmacAeadParameters) 424 .setAesKeyBytes(keyBytes) 425 .setHmacKeyBytes(keyBytes) 426 .build(); 427 428 assertThat(aesCtrHmacAeadKey.equalsKey(aesGcmKey)).isFalse(); 429 } 430 } 431