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; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static java.nio.charset.StandardCharsets.UTF_8; 21 import static org.junit.Assert.assertFalse; 22 import static org.junit.Assert.assertThrows; 23 import static org.junit.Assert.assertTrue; 24 import static org.junit.Assume.assumeFalse; 25 26 import com.google.common.truth.Expect; 27 import com.google.crypto.tink.aead.AeadConfig; 28 import com.google.crypto.tink.aead.AesEaxKeyManager; 29 import com.google.crypto.tink.aead.XChaCha20Poly1305Key; 30 import com.google.crypto.tink.aead.XChaCha20Poly1305Parameters; 31 import com.google.crypto.tink.internal.InternalConfiguration; 32 import com.google.crypto.tink.internal.KeyParser; 33 import com.google.crypto.tink.internal.KeyStatusTypeProtoConverter; 34 import com.google.crypto.tink.internal.LegacyProtoKey; 35 import com.google.crypto.tink.internal.MonitoringUtil; 36 import com.google.crypto.tink.internal.MutableMonitoringRegistry; 37 import com.google.crypto.tink.internal.MutablePrimitiveRegistry; 38 import com.google.crypto.tink.internal.MutableSerializationRegistry; 39 import com.google.crypto.tink.internal.PrimitiveConstructor; 40 import com.google.crypto.tink.internal.PrimitiveRegistry; 41 import com.google.crypto.tink.internal.ProtoKeySerialization; 42 import com.google.crypto.tink.internal.testing.FakeMonitoringClient; 43 import com.google.crypto.tink.mac.AesCmacKey; 44 import com.google.crypto.tink.mac.AesCmacParameters; 45 import com.google.crypto.tink.mac.AesCmacParameters.Variant; 46 import com.google.crypto.tink.mac.ChunkedMac; 47 import com.google.crypto.tink.mac.ChunkedMacComputation; 48 import com.google.crypto.tink.mac.HmacKey; 49 import com.google.crypto.tink.mac.HmacParameters; 50 import com.google.crypto.tink.mac.MacConfig; 51 import com.google.crypto.tink.monitoring.MonitoringAnnotations; 52 import com.google.crypto.tink.monitoring.MonitoringClient; 53 import com.google.crypto.tink.prf.PrfConfig; 54 import com.google.crypto.tink.proto.AesEaxKey; 55 import com.google.crypto.tink.proto.EcdsaPrivateKey; 56 import com.google.crypto.tink.proto.HashType; 57 import com.google.crypto.tink.proto.HmacParams; 58 import com.google.crypto.tink.proto.HmacPrfKey; 59 import com.google.crypto.tink.proto.HmacPrfParams; 60 import com.google.crypto.tink.proto.KeyData; 61 import com.google.crypto.tink.proto.KeyData.KeyMaterialType; 62 import com.google.crypto.tink.proto.KeyStatusType; 63 import com.google.crypto.tink.proto.Keyset; 64 import com.google.crypto.tink.proto.OutputPrefixType; 65 import com.google.crypto.tink.signature.SignatureConfig; 66 import com.google.crypto.tink.subtle.Hex; 67 import com.google.crypto.tink.subtle.Random; 68 import com.google.crypto.tink.testing.TestUtil; 69 import com.google.crypto.tink.tinkkey.KeyAccess; 70 import com.google.crypto.tink.tinkkey.KeyHandle; 71 import com.google.crypto.tink.tinkkey.SecretKeyAccess; 72 import com.google.crypto.tink.tinkkey.internal.ProtoKey; 73 import com.google.crypto.tink.util.Bytes; 74 import com.google.crypto.tink.util.SecretBytes; 75 import com.google.errorprone.annotations.Immutable; 76 import com.google.protobuf.ByteString; 77 import com.google.protobuf.ExtensionRegistryLite; 78 import java.io.ByteArrayInputStream; 79 import java.io.ByteArrayOutputStream; 80 import java.nio.ByteBuffer; 81 import java.security.GeneralSecurityException; 82 import java.util.HashSet; 83 import java.util.List; 84 import java.util.Map; 85 import java.util.Set; 86 import java.util.TreeSet; 87 import java.util.stream.Collectors; 88 import javax.annotation.Nullable; 89 import org.junit.BeforeClass; 90 import org.junit.Rule; 91 import org.junit.Test; 92 import org.junit.runner.RunWith; 93 import org.junit.runners.JUnit4; 94 95 /** 96 * Tests for {@link KeysetHandle}. 97 * 98 * <p>Please note, that in relation to the {@link PrimitiveSet#fullPrimitive} this file only tests 99 * the legacy scenario where the {@link PrimitiveSet#primitive} is set and {@link 100 * PrimitiveSet#fullPrimitive} isn't; the other scenarios are tested in 101 * {@link KeysetHandleFullPrimitiveTest}. 102 */ 103 @RunWith(JUnit4.class) 104 @SuppressWarnings("UnnecessarilyFullyQualified") // Fully specifying proto types is more readable 105 public class KeysetHandleTest { 106 107 @Rule public final Expect expect = Expect.create(); 108 109 private static interface EncryptOnly { encrypt(final byte[] plaintext)110 byte[] encrypt(final byte[] plaintext) throws GeneralSecurityException; 111 } 112 113 private static class AeadToEncryptOnlyWrapper implements PrimitiveWrapper<Aead, EncryptOnly> { 114 115 private static final AeadToEncryptOnlyWrapper WRAPPER = new AeadToEncryptOnlyWrapper(); 116 117 private static class EncryptOnlyWithMonitoring implements EncryptOnly { 118 119 private final MonitoringClient.Logger logger; 120 private final PrimitiveSet<Aead> primitiveSet; 121 EncryptOnlyWithMonitoring(PrimitiveSet<Aead> primitiveSet)122 EncryptOnlyWithMonitoring(PrimitiveSet<Aead> primitiveSet) { 123 this.primitiveSet = primitiveSet; 124 MonitoringClient client = MutableMonitoringRegistry.globalInstance().getMonitoringClient(); 125 logger = 126 client.createLogger( 127 MonitoringUtil.getMonitoringKeysetInfo(primitiveSet), "encrypt_only", "encrypt"); 128 } 129 130 @Override encrypt(final byte[] plaintext)131 public byte[] encrypt(final byte[] plaintext) throws GeneralSecurityException { 132 logger.log(primitiveSet.getPrimary().getKeyId(), plaintext.length); 133 return primitiveSet.getPrimary().getPrimitive().encrypt(plaintext, new byte[0]); 134 } 135 } 136 137 @Override wrap(PrimitiveSet<Aead> set)138 public EncryptOnly wrap(PrimitiveSet<Aead> set) throws GeneralSecurityException { 139 return new EncryptOnlyWithMonitoring(set); 140 } 141 142 @Override getPrimitiveClass()143 public Class<EncryptOnly> getPrimitiveClass() { 144 return EncryptOnly.class; 145 } 146 147 @Override getInputPrimitiveClass()148 public Class<Aead> getInputPrimitiveClass() { 149 return Aead.class; 150 } 151 register()152 static void register() throws GeneralSecurityException { 153 Registry.registerPrimitiveWrapper(WRAPPER); 154 } 155 } 156 157 private static final int HMAC_KEY_SIZE = 20; 158 private static final int HMAC_TAG_SIZE = 10; 159 160 private static HmacKey rawKey; 161 162 @BeforeClass setUp()163 public static void setUp() throws GeneralSecurityException { 164 MacConfig.register(); 165 AeadConfig.register(); 166 PrfConfig.register(); 167 SignatureConfig.register(); 168 AeadToEncryptOnlyWrapper.register(); 169 170 createTestKeys(); 171 } 172 createTestKeys()173 private static void createTestKeys() { 174 try { 175 rawKey = 176 HmacKey.builder() 177 .setParameters( 178 HmacParameters.builder() 179 .setKeySizeBytes(HMAC_KEY_SIZE) 180 .setTagSizeBytes(HMAC_TAG_SIZE) 181 .setVariant(HmacParameters.Variant.NO_PREFIX) 182 .setHashType(HmacParameters.HashType.SHA256) 183 .build()) 184 .setKeyBytes(SecretBytes.randomBytes(HMAC_KEY_SIZE)) 185 .setIdRequirement(null) 186 .build(); 187 } catch (GeneralSecurityException e) { 188 throw new IllegalStateException(e); 189 } 190 } 191 192 @SuppressWarnings("deprecation") // This is a test for the deprecated function 193 @Test deprecated_getKeys()194 public void deprecated_getKeys() throws Exception { 195 KeysetHandle handle = 196 KeysetHandle.newBuilder() 197 .addEntry(KeysetHandle.generateEntryFromParametersName("AES128_EAX").withRandomId()) 198 .addEntry( 199 KeysetHandle.generateEntryFromParametersName("AES128_EAX") 200 .withRandomId() 201 .makePrimary()) 202 .addEntry(KeysetHandle.generateEntryFromParametersName("AES128_EAX").withRandomId()) 203 .build(); 204 Keyset keyset = handle.getKeyset(); 205 206 List<KeyHandle> keysetKeys = handle.getKeys(); 207 208 expect.that(keysetKeys).hasSize(3); 209 Map<Integer, KeyHandle> keysetKeysMap = 210 keysetKeys.stream().collect(Collectors.toMap(KeyHandle::getId, key -> key)); 211 for (Keyset.Key key : keyset.getKeyList()) { 212 expect.that(keysetKeysMap).containsKey(key.getKeyId()); 213 KeyHandle keysetKey = keysetKeysMap.get(key.getKeyId()); 214 expect 215 .that(KeyStatusTypeProtoConverter.toProto(keysetKey.getStatus())) 216 .isEqualTo(key.getStatus()); 217 KeyData keyData = 218 ((ProtoKey) keysetKey.getKey(SecretKeyAccess.insecureSecretAccess())).getProtoKey(); 219 expect.that(keyData).isEqualTo(key.getKeyData()); 220 } 221 } 222 223 @Test generateNew_tink_shouldWork()224 public void generateNew_tink_shouldWork() throws Exception { 225 KeyTemplate template = KeyTemplates.get("AES128_EAX"); 226 227 KeysetHandle handle = KeysetHandle.generateNew(template); 228 229 assertThat(handle.size()).isEqualTo(1); 230 assertThat(handle.getAt(0).getKey().getParameters()).isEqualTo(template.toParameters()); 231 } 232 233 @Test testKeysetHandleGenerateNew_parameters_works()234 public void testKeysetHandleGenerateNew_parameters_works() throws Exception { 235 AesCmacParameters parameters = 236 AesCmacParameters.builder() 237 .setVariant(Variant.CRUNCHY) 238 .setKeySizeBytes(32) 239 .setTagSizeBytes(16) 240 .build(); 241 KeysetHandle h = KeysetHandle.generateNew(parameters); 242 assertThat(h.size()).isEqualTo(1); 243 assertThat(h.getAt(0).getKey().getParameters()).isEqualTo(parameters); 244 } 245 246 @Test testKeysetHandleGenerateNew_parameters_fails()247 public void testKeysetHandleGenerateNew_parameters_fails() throws Exception { 248 Parameters p = 249 new Parameters() { 250 @Override 251 public boolean hasIdRequirement() { 252 return false; 253 } 254 }; 255 256 assertThrows(GeneralSecurityException.class, () -> KeysetHandle.generateNew(p)); 257 } 258 259 260 @Test generateNew_raw_shouldWork()261 public void generateNew_raw_shouldWork() throws Exception { 262 KeyTemplate template = KeyTemplates.get("AES128_EAX_RAW"); 263 264 KeysetHandle handle = KeysetHandle.generateNew(template); 265 266 assertThat(handle.size()).isEqualTo(1); 267 assertThat(handle.getAt(0).getKey().getParameters()).isEqualTo(template.toParameters()); 268 } 269 270 @Test generateNew_withProtoKeyTemplate_shouldWork()271 public void generateNew_withProtoKeyTemplate_shouldWork() throws Exception { 272 KeyTemplate template = KeyTemplates.get("AES128_EAX"); 273 com.google.crypto.tink.proto.KeyTemplate protoTemplate = template.getProto(); 274 275 @SuppressWarnings("deprecation") // Need to test the deprecated function 276 KeysetHandle handle = KeysetHandle.generateNew(protoTemplate); 277 278 assertThat(handle.size()).isEqualTo(1); 279 assertThat(handle.getAt(0).getKey().getParameters()).isEqualTo(template.toParameters()); 280 } 281 282 @Test generateNew_generatesDifferentKeys()283 public void generateNew_generatesDifferentKeys() throws Exception { 284 KeyTemplate template = KeyTemplates.get("AES128_EAX"); 285 Set<String> keys = new TreeSet<>(); 286 287 int numKeys = 2; 288 for (int j = 0; j < numKeys; j++) { 289 KeysetHandle handle = KeysetHandle.generateNew(template); 290 AesEaxKey aesEaxKey = 291 AesEaxKey.parseFrom( 292 handle.getKeyset().getKey(0).getKeyData().getValue(), 293 ExtensionRegistryLite.getEmptyRegistry()); 294 keys.add(aesEaxKey.getKeyValue().toStringUtf8()); 295 } 296 297 assertThat(keys).hasSize(numKeys); 298 } 299 300 @SuppressWarnings("deprecation") // This is a test for the deprecated function 301 @Test deprecated_createFromKey_shouldWork()302 public void deprecated_createFromKey_shouldWork() throws Exception { 303 KeyTemplate template = KeyTemplates.get("AES128_EAX"); 304 KeyHandle keyHandle = KeyHandle.generateNew(template); 305 KeyAccess token = SecretKeyAccess.insecureSecretAccess(); 306 307 KeysetHandle handle = KeysetHandle.createFromKey(keyHandle, token); 308 309 assertThat(handle.size()).isEqualTo(1); 310 assertThat(handle.getAt(0).getKey().getParameters()).isEqualTo(template.toParameters()); 311 } 312 313 @Test toString_containsNoKeyMaterial()314 public void toString_containsNoKeyMaterial() throws Exception { 315 String keyValue = "01234567890123456"; 316 Keyset keyset = 317 TestUtil.createKeyset( 318 TestUtil.createKey( 319 TestUtil.createHmacKeyData(keyValue.getBytes(UTF_8), 16), 320 42, 321 KeyStatusType.ENABLED, 322 OutputPrefixType.TINK)); 323 KeysetHandle handle = KeysetHandle.fromKeyset(keyset); 324 325 String keysetInfo = handle.toString(); 326 327 expect.that(keysetInfo).doesNotContain(keyValue); 328 expect.that(handle.getKeyset().toString()).contains(keyValue); 329 } 330 331 @Test writeThenRead_returnsSameKeyset()332 public void writeThenRead_returnsSameKeyset() throws Exception { 333 KeysetHandle handle = KeysetHandle.generateNew(KeyTemplates.get("HMAC_SHA256_256BITTAG")); 334 Aead masterKey = 335 Registry.getPrimitive(Registry.newKeyData(KeyTemplates.get("AES128_EAX")), Aead.class); 336 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 337 KeysetWriter writer = BinaryKeysetWriter.withOutputStream(outputStream); 338 339 handle.write(writer, masterKey); 340 ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); 341 KeysetReader reader = BinaryKeysetReader.withInputStream(inputStream); 342 KeysetHandle handle2 = KeysetHandle.read(reader, masterKey); 343 344 assertThat(handle.getKeyset()).isEqualTo(handle2.getKeyset()); 345 } 346 347 @Test writeThenReadWithAssociatedData_returnsSameKeyset()348 public void writeThenReadWithAssociatedData_returnsSameKeyset() throws Exception { 349 KeysetHandle handle = KeysetHandle.generateNew(KeyTemplates.get("HMAC_SHA256_256BITTAG")); 350 Aead masterKey = 351 Registry.getPrimitive(Registry.newKeyData(KeyTemplates.get("AES128_EAX")), Aead.class); 352 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 353 KeysetWriter writer = BinaryKeysetWriter.withOutputStream(outputStream); 354 355 handle.writeWithAssociatedData(writer, masterKey, new byte[] {0x01, 0x02}); 356 ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); 357 KeysetReader reader = BinaryKeysetReader.withInputStream(inputStream); 358 KeysetHandle handle2 = 359 KeysetHandle.readWithAssociatedData(reader, masterKey, new byte[] {0x01, 0x02}); 360 361 assertThat(handle.getKeyset()).isEqualTo(handle2.getKeyset()); 362 } 363 364 @Test writeThenReadWithDifferentAssociatedData_shouldThrow()365 public void writeThenReadWithDifferentAssociatedData_shouldThrow() throws Exception { 366 KeysetHandle handle = KeysetHandle.generateNew(KeyTemplates.get("HMAC_SHA256_256BITTAG")); 367 Aead masterKey = 368 Registry.getPrimitive(Registry.newKeyData(KeyTemplates.get("AES128_EAX")), Aead.class); 369 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 370 KeysetWriter writer = BinaryKeysetWriter.withOutputStream(outputStream); 371 372 handle.writeWithAssociatedData(writer, masterKey, new byte[] {0x01, 0x02}); 373 ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); 374 KeysetReader reader = BinaryKeysetReader.withInputStream(inputStream); 375 assertThrows( 376 GeneralSecurityException.class, 377 () -> KeysetHandle.readWithAssociatedData(reader, masterKey, new byte[] {0x01, 0x03})); 378 } 379 380 /** 381 * A test vector for readWithAssociatedData, generated with this implementation. It uses a 382 * AES128_EAX template for the wrapping key, and a HMAC_SHA256_128BITTAG for the mac. 383 */ 384 @Test readWithAssociatedDataTestVector()385 public void readWithAssociatedDataTestVector() throws Exception { 386 // An AEAD key, with which we encrypt the mac key below (using the encrypted keyset api). 387 final byte[] serializedWrappingKeyset = 388 Hex.decode( 389 "08b891f5a20412580a4c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e6372797" 390 + "0746f2e74696e6b2e4165734561784b65791216120208101a10e5d7d0cdd649e81e7952260689b2" 391 + "e1971801100118b891f5a2042001"); 392 final byte[] associatedData = Hex.decode("abcdef330012"); 393 // A Mac key, encrypted with the above, using ASSOCIATED_DATA as aad. 394 final byte[] encryptedSerializedKeyset = 395 Hex.decode( 396 "12950101445d48b8b5f591efaf73a46df9ebd7b6ac471cc0cf4f815a4f012fcaffc8f0b2b10b30c33194f" 397 + "0b291614bd8e1d2e80118e5d6226b6c41551e104ef8cd8ee20f1c14c1b87f6eed5fb04a91feafaa" 398 + "cbf6f368519f36f97f7d08b24c8e71b5e620c4f69615ef0479391666e2fb32e46b416893fc4e564" 399 + "ba927b22ebff2a77bd3b5b8d5afa162cbd35c94c155cdfa13c8a9c964cde21a4208f5909ce90112" 400 + "3a0a2e747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696" 401 + "e6b2e486d61634b6579100118f5909ce9012001"); 402 // A message whose tag we computed with the wrapped key. 403 final byte[] message = Hex.decode(""); 404 final byte[] tag = Hex.decode("011d270875989dd6fbd5f54dbc9520bb41efd058d5"); 405 406 KeysetReader wrappingReader = BinaryKeysetReader.withBytes(serializedWrappingKeyset); 407 Aead wrapperAead = CleartextKeysetHandle.read(wrappingReader).getPrimitive(Aead.class); 408 409 KeysetReader encryptedReader = BinaryKeysetReader.withBytes(encryptedSerializedKeyset); 410 Mac mac = 411 KeysetHandle.readWithAssociatedData(encryptedReader, wrapperAead, associatedData) 412 .getPrimitive(Mac.class); 413 mac.verifyMac(tag, message); 414 } 415 416 @Test getPublicKeysetHandle_shouldWork()417 public void getPublicKeysetHandle_shouldWork() throws Exception { 418 KeysetHandle privateHandle = KeysetHandle.generateNew(KeyTemplates.get("ECDSA_P256")); 419 KeyData privateKeyData = privateHandle.getKeyset().getKey(0).getKeyData(); 420 EcdsaPrivateKey privateKey = 421 EcdsaPrivateKey.parseFrom( 422 privateKeyData.getValue(), ExtensionRegistryLite.getEmptyRegistry()); 423 424 KeysetHandle publicHandle = privateHandle.getPublicKeysetHandle(); 425 426 expect.that(publicHandle.getKeyset().getKeyCount()).isEqualTo(1); 427 expect 428 .that(privateHandle.getKeyset().getPrimaryKeyId()) 429 .isEqualTo(publicHandle.getKeyset().getPrimaryKeyId()); 430 KeyData publicKeyData = publicHandle.getKeyset().getKey(0).getKeyData(); 431 expect.that(publicKeyData.getTypeUrl()).isEqualTo(SignatureConfig.ECDSA_PUBLIC_KEY_TYPE_URL); 432 expect 433 .that(publicKeyData.getKeyMaterialType()) 434 .isEqualTo(KeyData.KeyMaterialType.ASYMMETRIC_PUBLIC); 435 expect 436 .that(publicKeyData.getValue().toByteArray()) 437 .isEqualTo(privateKey.getPublicKey().toByteArray()); 438 PublicKeySign signer = privateHandle.getPrimitive(PublicKeySign.class); 439 PublicKeyVerify verifier = publicHandle.getPrimitive(PublicKeyVerify.class); 440 byte[] message = Random.randBytes(20); 441 verifier.verify(signer.sign(message), message); 442 } 443 444 /** Tests that when encryption failed an exception is thrown. */ 445 @Test write_withFaultyAead_shouldThrow()446 public void write_withFaultyAead_shouldThrow() throws Exception { 447 KeysetHandle handle = KeysetHandle.generateNew(KeyTemplates.get("HMAC_SHA256_256BITTAG")); 448 TestUtil.DummyAead faultyAead = new TestUtil.DummyAead(); 449 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 450 KeysetWriter writer = BinaryKeysetWriter.withOutputStream(outputStream); 451 452 assertThrows(GeneralSecurityException.class, () -> handle.write(writer, faultyAead)); 453 } 454 455 @Test read_withNoMasterKeyInput_shouldThrow()456 public void read_withNoMasterKeyInput_shouldThrow() throws Exception { 457 KeysetReader reader = BinaryKeysetReader.withBytes(new byte[0]); 458 459 assertThrows( 460 GeneralSecurityException.class, () -> KeysetHandle.read(reader, /* masterKey= */ null)); 461 } 462 463 @Test getPrimitive_shouldWork()464 public void getPrimitive_shouldWork() throws Exception { 465 KeysetHandle handle = KeysetHandle.generateNew(KeyTemplates.get("AES128_EAX")); 466 byte[] message = Random.randBytes(20); 467 byte[] aad = Random.randBytes(20); 468 469 Aead aead = handle.getPrimitive(Aead.class); 470 471 assertThat(aead.decrypt(aead.encrypt(message, aad), aad)).isEqualTo(message); 472 } 473 474 // Tests that getPrimitive does correct wrapping and not just return the primary. For this, we 475 // simply add a raw, non-primary key and encrypt directly with it. 476 @Test getPrimitive_wrappingDoneCorrectly()477 public void getPrimitive_wrappingDoneCorrectly() throws Exception { 478 KeyData rawKeyData = Registry.newKeyData(KeyTemplates.get("AES128_EAX")); 479 Keyset keyset = 480 TestUtil.createKeyset( 481 TestUtil.createKey( 482 Registry.newKeyData(KeyTemplates.get("AES128_EAX").getProto()), 483 42, 484 KeyStatusType.ENABLED, 485 OutputPrefixType.TINK), 486 TestUtil.createKey(rawKeyData, 43, KeyStatusType.ENABLED, OutputPrefixType.RAW)); 487 KeysetHandle handle = KeysetHandle.fromKeyset(keyset); 488 byte[] message = Random.randBytes(20); 489 byte[] aad = Random.randBytes(20); 490 Aead aeadToEncrypt = Registry.getPrimitive(rawKeyData, Aead.class); 491 492 Aead aead = handle.getPrimitive(Aead.class); 493 494 assertThat(aead.decrypt(aeadToEncrypt.encrypt(message, aad), aad)).isEqualTo(message); 495 } 496 497 @Test getPrimitive_differentPrimitive_shouldWork()498 public void getPrimitive_differentPrimitive_shouldWork() throws Exception { 499 // We use RAW because the EncryptOnly wrapper wraps everything RAW. 500 KeysetHandle handle = KeysetHandle.generateNew(AesEaxKeyManager.rawAes128EaxTemplate()); 501 byte[] message = Random.randBytes(20); 502 503 EncryptOnly encryptOnly = handle.getPrimitive(EncryptOnly.class); 504 505 Aead aead = handle.getPrimitive(Aead.class); 506 assertThat(aead.decrypt(encryptOnly.encrypt(message), new byte[0])).isEqualTo(message); 507 } 508 509 @Test noBuilderSetMonitoringAnnotations_monitoringClientGetsAnnotationsWithKeysetInfo()510 public void noBuilderSetMonitoringAnnotations_monitoringClientGetsAnnotationsWithKeysetInfo() 511 throws Exception { 512 MutableMonitoringRegistry.globalInstance().clear(); 513 FakeMonitoringClient fakeMonitoringClient = new FakeMonitoringClient(); 514 MutableMonitoringRegistry.globalInstance().registerMonitoringClient(fakeMonitoringClient); 515 516 Keyset keyset = 517 TestUtil.createKeyset( 518 TestUtil.createKey( 519 TestUtil.createAesGcmKeyData(Hex.decode("000102030405060708090a0b0c0d0e0f")), 520 42, 521 KeyStatusType.ENABLED, 522 OutputPrefixType.TINK)); 523 byte[] message = Random.randBytes(123); 524 MonitoringAnnotations annotations = 525 MonitoringAnnotations.newBuilder().add("annotation_name", "annotation_value").build(); 526 KeysetHandle handleWithAnnotations = KeysetHandle.fromKeysetAndAnnotations(keyset, annotations); 527 EncryptOnly encryptOnlyWithAnnotations = handleWithAnnotations.getPrimitive(EncryptOnly.class); 528 Object unused = encryptOnlyWithAnnotations.encrypt(message); 529 List<FakeMonitoringClient.LogEntry> entries = fakeMonitoringClient.getLogEntries(); 530 assertThat(entries).hasSize(1); 531 assertThat(entries.get(0).getKeysetInfo().getAnnotations()).isEqualTo(annotations); 532 } 533 534 @Test builderSetMonitoringAnnotations_works()535 public void builderSetMonitoringAnnotations_works() throws Exception { 536 FakeMonitoringClient fakeMonitoringClient = new FakeMonitoringClient(); 537 MutableMonitoringRegistry.globalInstance().clear(); 538 MutableMonitoringRegistry.globalInstance().registerMonitoringClient(fakeMonitoringClient); 539 MonitoringAnnotations annotations = 540 MonitoringAnnotations.newBuilder().add("annotation_name", "annotation_value").build(); 541 KeysetHandle keysetHandleWithAnnotations = 542 KeysetHandle.newBuilder() 543 .addEntry( 544 KeysetHandle.generateEntryFromParameters( 545 AesCmacParameters.builder() 546 .setVariant(Variant.TINK) 547 .setKeySizeBytes(32) 548 .setTagSizeBytes(16) 549 .build()) 550 .withFixedId(42) 551 .makePrimary()) 552 .setMonitoringAnnotations(annotations) 553 .build(); 554 byte[] plaintext = "plaintext".getBytes(UTF_8); 555 Mac mac = keysetHandleWithAnnotations.getPrimitive(Mac.class); 556 557 // Work triggering various code paths. 558 byte[] tag = mac.computeMac(plaintext); 559 mac.verifyMac(tag, plaintext); 560 assertThrows(GeneralSecurityException.class, () -> mac.verifyMac(tag, new byte[0])); 561 assertThrows(GeneralSecurityException.class, () -> mac.verifyMac(new byte[0], plaintext)); 562 563 // With annotations set, the events get logged. 564 List<FakeMonitoringClient.LogEntry> logEntries = fakeMonitoringClient.getLogEntries(); 565 System.out.println(logEntries); 566 assertThat(logEntries).hasSize(2); 567 568 FakeMonitoringClient.LogEntry tinkComputeEntry = logEntries.get(0); 569 assertThat(tinkComputeEntry.getKeyId()).isEqualTo(42); 570 assertThat(tinkComputeEntry.getPrimitive()).isEqualTo("mac"); 571 assertThat(tinkComputeEntry.getApi()).isEqualTo("compute"); 572 assertThat(tinkComputeEntry.getNumBytesAsInput()).isEqualTo(plaintext.length); 573 assertThat(tinkComputeEntry.getKeysetInfo().getAnnotations()).isEqualTo(annotations); 574 575 FakeMonitoringClient.LogEntry rawComputeEntry = logEntries.get(1); 576 assertThat(rawComputeEntry.getKeyId()).isEqualTo(42); 577 assertThat(rawComputeEntry.getPrimitive()).isEqualTo("mac"); 578 assertThat(rawComputeEntry.getApi()).isEqualTo("verify"); 579 assertThat(rawComputeEntry.getNumBytesAsInput()).isEqualTo(plaintext.length); 580 assertThat(rawComputeEntry.getKeysetInfo().getAnnotations()).isEqualTo(annotations); 581 } 582 583 @Test builderNotSetMonitoringAnnotations_setsEmptyAnnotations()584 public void builderNotSetMonitoringAnnotations_setsEmptyAnnotations() throws Exception { 585 FakeMonitoringClient fakeMonitoringClient = new FakeMonitoringClient(); 586 MutableMonitoringRegistry.globalInstance().clear(); 587 MutableMonitoringRegistry.globalInstance().registerMonitoringClient(fakeMonitoringClient); 588 KeysetHandle keysetHandleWithAnnotations = 589 KeysetHandle.newBuilder() 590 .addEntry( 591 KeysetHandle.generateEntryFromParameters( 592 AesCmacParameters.builder() 593 .setVariant(Variant.TINK) 594 .setKeySizeBytes(32) 595 .setTagSizeBytes(16) 596 .build()) 597 .withRandomId() 598 .makePrimary()) 599 .build(); 600 byte[] plaintext = "plaintext".getBytes(UTF_8); 601 Mac mac = keysetHandleWithAnnotations.getPrimitive(Mac.class); 602 603 // Work triggering various code paths. 604 byte[] tag = mac.computeMac(plaintext); 605 mac.verifyMac(tag, plaintext); 606 607 // Without annotations, nothing gets logged. 608 assertThat(fakeMonitoringClient.getLogEntries()).isEmpty(); 609 assertThat(fakeMonitoringClient.getLogFailureEntries()).isEmpty(); 610 } 611 612 @SuppressWarnings("deprecation") // This is a test for the deprecated function 613 @Test deprecated_readNoSecretWithBytesInput_sameAs_parseKeysetWithoutSecret()614 public void deprecated_readNoSecretWithBytesInput_sameAs_parseKeysetWithoutSecret() 615 throws Exception { 616 // Public keyset should have the same output 617 KeysetHandle privateHandle = KeysetHandle.generateNew(KeyTemplates.get("ECDSA_P256")); 618 byte[] serializedPublicKeyset = privateHandle.getPublicKeysetHandle().getKeyset().toByteArray(); 619 620 KeysetHandle readNoSecretOutput = KeysetHandle.readNoSecret(serializedPublicKeyset); 621 KeysetHandle parseKeysetWithoutSecretOutput = 622 TinkProtoKeysetFormat.parseKeysetWithoutSecret(serializedPublicKeyset); 623 expect 624 .that(readNoSecretOutput.getKeyset()) 625 .isEqualTo(parseKeysetWithoutSecretOutput.getKeyset()); 626 627 // Symmetric Keyset should fail 628 byte[] serializedSymmetricKeyset = 629 TestUtil.createKeyset( 630 TestUtil.createKey( 631 TestUtil.createHmacKeyData("01234567890123456".getBytes(UTF_8), 16), 632 42, 633 KeyStatusType.ENABLED, 634 OutputPrefixType.TINK)) 635 .toByteArray(); 636 assertThrows( 637 GeneralSecurityException.class, () -> KeysetHandle.readNoSecret(serializedSymmetricKeyset)); 638 assertThrows( 639 GeneralSecurityException.class, 640 () -> TinkProtoKeysetFormat.parseKeysetWithoutSecret(serializedSymmetricKeyset)); 641 642 // Private Keyset should fail 643 byte[] serializedPrivateKeyset = privateHandle.getKeyset().toByteArray(); 644 assertThrows( 645 GeneralSecurityException.class, () -> KeysetHandle.readNoSecret(serializedPrivateKeyset)); 646 assertThrows( 647 GeneralSecurityException.class, 648 () -> TinkProtoKeysetFormat.parseKeysetWithoutSecret(serializedPrivateKeyset)); 649 650 // Empty Keyset should fail 651 assertThrows(GeneralSecurityException.class, () -> KeysetHandle.readNoSecret(new byte[0])); 652 assertThrows( 653 GeneralSecurityException.class, 654 () -> TinkProtoKeysetFormat.parseKeysetWithoutSecret(new byte[0])); 655 656 // Invalid Keyset should fail 657 byte[] proto = new byte[] {0x00, 0x01, 0x02}; 658 assertThrows(GeneralSecurityException.class, () -> KeysetHandle.readNoSecret(proto)); 659 assertThrows( 660 GeneralSecurityException.class, 661 () -> TinkProtoKeysetFormat.parseKeysetWithoutSecret(proto)); 662 } 663 664 @Test readNoSecretWithBinaryKeysetReader_shouldWork()665 public void readNoSecretWithBinaryKeysetReader_shouldWork() throws Exception { 666 KeysetHandle privateHandle = KeysetHandle.generateNew(KeyTemplates.get("ECDSA_P256")); 667 Keyset keyset = privateHandle.getPublicKeysetHandle().getKeyset(); 668 byte[] serializedKeyset = keyset.toByteArray(); 669 670 Keyset readKeyset = 671 KeysetHandle.readNoSecret(BinaryKeysetReader.withBytes(serializedKeyset)).getKeyset(); 672 673 expect.that(readKeyset).isEqualTo(keyset); 674 } 675 676 @Test readNoSecretWithBinaryKeysetReader_withTypeSymmetric_shouldThrow()677 public void readNoSecretWithBinaryKeysetReader_withTypeSymmetric_shouldThrow() throws Exception { 678 String keyValue = "01234567890123456"; 679 byte[] serializedKeyset = 680 TestUtil.createKeyset( 681 TestUtil.createKey( 682 TestUtil.createHmacKeyData(keyValue.getBytes(UTF_8), 16), 683 42, 684 KeyStatusType.ENABLED, 685 OutputPrefixType.TINK)).toByteArray(); 686 687 assertThrows( 688 GeneralSecurityException.class, 689 () -> KeysetHandle.readNoSecret(BinaryKeysetReader.withBytes(serializedKeyset))); 690 } 691 692 @Test readNoSecretWithBinaryKeysetReader_withTypeAsymmetricPrivate_shouldThrow()693 public void readNoSecretWithBinaryKeysetReader_withTypeAsymmetricPrivate_shouldThrow() 694 throws Exception { 695 byte[] serializedKeyset = 696 KeysetHandle.generateNew(KeyTemplates.get("ECDSA_P256")).getKeyset().toByteArray(); 697 698 assertThrows( 699 GeneralSecurityException.class, 700 () -> KeysetHandle.readNoSecret(BinaryKeysetReader.withBytes(serializedKeyset))); 701 } 702 703 @Test readNoSecretWithBinaryKeysetReader_withEmptyKeyset_shouldThrow()704 public void readNoSecretWithBinaryKeysetReader_withEmptyKeyset_shouldThrow() throws Exception { 705 byte[] emptySerializedKeyset = new byte[0]; 706 assertThrows( 707 GeneralSecurityException.class, 708 () -> KeysetHandle.readNoSecret(BinaryKeysetReader.withBytes(emptySerializedKeyset))); 709 } 710 711 @Test readNoSecretWithBinaryKeysetReader_withInvalidKeyset_shouldThrow()712 public void readNoSecretWithBinaryKeysetReader_withInvalidKeyset_shouldThrow() throws Exception { 713 byte[] invalidSerializedKeyset = new byte[] {0x00, 0x01, 0x02}; 714 assertThrows( 715 GeneralSecurityException.class, 716 () -> KeysetHandle.readNoSecret(BinaryKeysetReader.withBytes(invalidSerializedKeyset))); 717 } 718 719 @Test writeNoSecretThenReadNoSecret_returnsSameKeyset()720 public void writeNoSecretThenReadNoSecret_returnsSameKeyset() throws Exception { 721 KeysetHandle privateHandle = KeysetHandle.generateNew(KeyTemplates.get("ECDSA_P256")); 722 KeysetHandle publicHandle = privateHandle.getPublicKeysetHandle(); 723 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 724 KeysetWriter writer = BinaryKeysetWriter.withOutputStream(outputStream); 725 Keyset keyset = publicHandle.getKeyset(); 726 727 publicHandle.writeNoSecret(writer); 728 ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); 729 KeysetReader reader = BinaryKeysetReader.withInputStream(inputStream); 730 Keyset keyset2 = KeysetHandle.readNoSecret(reader).getKeyset(); 731 732 assertThat(keyset).isEqualTo(keyset2); 733 } 734 735 @Test writeNoSecret_withTypeSymmetric_shouldThrow()736 public void writeNoSecret_withTypeSymmetric_shouldThrow() throws Exception { 737 String keyValue = "01234567890123456"; 738 Keyset keyset = 739 TestUtil.createKeyset( 740 TestUtil.createKey( 741 TestUtil.createHmacKeyData(keyValue.getBytes(UTF_8), 16), 742 42, 743 KeyStatusType.ENABLED, 744 OutputPrefixType.TINK)); 745 KeysetHandle handle = KeysetHandle.fromKeyset(keyset); 746 747 assertThrows(GeneralSecurityException.class, () -> handle.writeNoSecret(/* writer= */ null)); 748 } 749 750 @Test writeNoSecret_withTypeAsymmetricPrivate_shouldThrow()751 public void writeNoSecret_withTypeAsymmetricPrivate_shouldThrow() throws Exception { 752 KeysetHandle handle = KeysetHandle.generateNew(KeyTemplates.get("ECDSA_P256")); 753 754 assertThrows(GeneralSecurityException.class, () -> handle.writeNoSecret(/* writer= */ null)); 755 } 756 757 @SuppressWarnings("deprecation") // This is a test for the deprecated function 758 @Test deprecated_primaryKey_shouldWork()759 public void deprecated_primaryKey_shouldWork() throws Exception { 760 KeysetHandle handle = 761 KeysetHandle.newBuilder() 762 .addEntry( 763 KeysetHandle.generateEntryFromParametersName("AES128_EAX").withFixedId(123)) 764 .addEntry( 765 KeysetHandle.generateEntryFromParametersName("HMAC_SHA256_256BITTAG") 766 .withFixedId(234).makePrimary()) 767 .build(); 768 769 KeyHandle keyHandle = handle.primaryKey(); 770 assertThat(keyHandle.getId()).isEqualTo(234); 771 } 772 773 @SuppressWarnings("deprecation") // This is a test for the deprecated function 774 @Test deprecated_primaryKey_primaryNotPresent_shouldThrow()775 public void deprecated_primaryKey_primaryNotPresent_shouldThrow() throws Exception { 776 Keyset keyset = 777 TestUtil.createKeyset( 778 TestUtil.createKey( 779 TestUtil.createHmacKeyData("01234567890123456".getBytes(UTF_8), 16), 780 42, 781 KeyStatusType.ENABLED, 782 OutputPrefixType.TINK)); 783 KeysetHandle handle = 784 KeysetHandle.fromKeyset(Keyset.newBuilder(keyset).setPrimaryKeyId(77).build()); 785 786 assertThrows(GeneralSecurityException.class, handle::primaryKey); 787 } 788 789 @Test testGetAt_singleKeyWithRegisteredProtoSerialization_works()790 public void testGetAt_singleKeyWithRegisteredProtoSerialization_works() throws Exception { 791 // HmacKey's proto serialization HmacProtoSerialization is registed in HmacKeyManager. 792 Keyset keyset = 793 TestUtil.createKeyset( 794 TestUtil.createKey( 795 TestUtil.createHmacKeyData("01234567890123456".getBytes(UTF_8), 16), 796 42, 797 KeyStatusType.ENABLED, 798 OutputPrefixType.TINK)); 799 KeysetHandle handle = KeysetHandle.fromKeyset(keyset); 800 assertThat(handle.size()).isEqualTo(1); 801 KeysetHandle.Entry entry = handle.getAt(0); 802 assertThat(entry.getId()).isEqualTo(42); 803 assertThat(entry.getStatus()).isEqualTo(KeyStatus.ENABLED); 804 assertThat(entry.isPrimary()).isTrue(); 805 assertThat(entry.getKey().getClass()).isEqualTo(HmacKey.class); 806 } 807 808 @Test getAt_invalidKeyWithRegisteredProtoSerialization_throwsIllegalStateException()809 public void getAt_invalidKeyWithRegisteredProtoSerialization_throwsIllegalStateException() 810 throws Exception { 811 // HmacKey's proto serialization HmacProtoSerialization is registed in HmacKeyManager. 812 com.google.crypto.tink.proto.HmacKey invalidProtoHmacKey = 813 com.google.crypto.tink.proto.HmacKey.newBuilder() 814 .setVersion(999) 815 .setKeyValue(ByteString.copyFromUtf8("01234567890123456")) 816 .setParams(HmacParams.newBuilder().setHash(HashType.UNKNOWN_HASH).setTagSize(0)) 817 .build(); 818 Keyset keyset = 819 TestUtil.createKeyset( 820 TestUtil.createKey( 821 TestUtil.createKeyData( 822 invalidProtoHmacKey, 823 "type.googleapis.com/google.crypto.tink.HmacKey", 824 KeyData.KeyMaterialType.SYMMETRIC), 825 42, 826 KeyStatusType.ENABLED, 827 OutputPrefixType.TINK)); 828 KeysetHandle handle = KeysetHandle.fromKeyset(keyset); 829 assertThat(handle.size()).isEqualTo(1); 830 assertThrows(IllegalStateException.class, () -> handle.getAt(0)); 831 } 832 833 @Test testGetAt_singleKeyWithoutRegisteredProtoSerialization_wrapsToLegacyProtoKey()834 public void testGetAt_singleKeyWithoutRegisteredProtoSerialization_wrapsToLegacyProtoKey() 835 throws Exception { 836 HmacPrfKey key = 837 HmacPrfKey.newBuilder() 838 .setParams(HmacPrfParams.newBuilder().setHash(HashType.SHA256).build()) 839 .setKeyValue(ByteString.copyFromUtf8("01234567890123456")) 840 .build(); 841 Keyset keyset = 842 TestUtil.createKeyset( 843 TestUtil.createKey( 844 TestUtil.createKeyData( 845 key, "i.am.an.unregistered.key.type", KeyData.KeyMaterialType.SYMMETRIC), 846 42, 847 KeyStatusType.ENABLED, 848 OutputPrefixType.RAW)); 849 KeysetHandle handle = KeysetHandle.fromKeyset(keyset); 850 assertThat(handle.size()).isEqualTo(1); 851 KeysetHandle.Entry entry = handle.getAt(0); 852 assertThat(entry.getId()).isEqualTo(42); 853 assertThat(entry.getStatus()).isEqualTo(KeyStatus.ENABLED); 854 assertThat(entry.isPrimary()).isTrue(); 855 assertThat(entry.getKey().getClass()).isEqualTo(LegacyProtoKey.class); 856 } 857 858 @Test testGetAt_multipleKeys_works()859 public void testGetAt_multipleKeys_works() throws Exception { 860 Keyset.Key key1 = 861 TestUtil.createKey( 862 TestUtil.createHmacKeyData("01234567890123456".getBytes(UTF_8), 16), 863 42, 864 KeyStatusType.DISABLED, 865 OutputPrefixType.TINK); 866 Keyset.Key key2 = 867 TestUtil.createKey( 868 TestUtil.createHmacKeyData("abcdefghijklmnopq".getBytes(UTF_8), 32), 869 44, 870 KeyStatusType.ENABLED, 871 OutputPrefixType.CRUNCHY); 872 Keyset.Key key3 = 873 TestUtil.createKey( 874 TestUtil.createHmacKeyData("ABCDEFGHIJKLMNOPQ".getBytes(UTF_8), 32), 875 46, 876 KeyStatusType.DESTROYED, 877 OutputPrefixType.TINK); 878 Keyset keyset = TestUtil.createKeyset(key1, key2, key3); 879 KeysetHandle handle = 880 KeysetHandle.fromKeyset(Keyset.newBuilder(keyset).setPrimaryKeyId(44).build()); 881 882 assertThat(handle.size()).isEqualTo(3); 883 assertThat(handle.getAt(0).getId()).isEqualTo(42); 884 assertThat(handle.getAt(0).getStatus()).isEqualTo(KeyStatus.DISABLED); 885 assertThat(handle.getAt(0).isPrimary()).isFalse(); 886 887 assertThat(handle.getAt(1).getId()).isEqualTo(44); 888 assertThat(handle.getAt(1).getStatus()).isEqualTo(KeyStatus.ENABLED); 889 assertThat(handle.getAt(1).isPrimary()).isTrue(); 890 891 assertThat(handle.getAt(2).getId()).isEqualTo(46); 892 assertThat(handle.getAt(2).getStatus()).isEqualTo(KeyStatus.DESTROYED); 893 assertThat(handle.getAt(2).isPrimary()).isFalse(); 894 } 895 896 @Test testPrimary_multipleKeys_works()897 public void testPrimary_multipleKeys_works() throws Exception { 898 Keyset.Key key1 = 899 TestUtil.createKey( 900 TestUtil.createHmacKeyData("01234567890123456".getBytes(UTF_8), 16), 901 42, 902 KeyStatusType.ENABLED, 903 OutputPrefixType.TINK); 904 Keyset.Key key2 = 905 TestUtil.createKey( 906 TestUtil.createHmacKeyData("abcdefghijklmnopq".getBytes(UTF_8), 32), 907 44, 908 KeyStatusType.ENABLED, 909 OutputPrefixType.CRUNCHY); 910 Keyset.Key key3 = 911 TestUtil.createKey( 912 TestUtil.createHmacKeyData("ABCDEFGHIJKLMNOPQ".getBytes(UTF_8), 32), 913 46, 914 KeyStatusType.ENABLED, 915 OutputPrefixType.TINK); 916 Keyset keyset = TestUtil.createKeyset(key1, key2, key3); 917 KeysetHandle handle = 918 KeysetHandle.fromKeyset(Keyset.newBuilder(keyset).setPrimaryKeyId(44).build()); 919 KeysetHandle.Entry primary = handle.getPrimary(); 920 assertThat(primary.getId()).isEqualTo(44); 921 assertThat(primary.getStatus()).isEqualTo(KeyStatus.ENABLED); 922 assertThat(primary.isPrimary()).isTrue(); 923 } 924 925 @Test testGetPrimary_noPrimary_throws()926 public void testGetPrimary_noPrimary_throws() throws Exception { 927 Keyset.Key key1 = 928 TestUtil.createKey( 929 TestUtil.createHmacKeyData("01234567890123456".getBytes(UTF_8), 16), 930 42, 931 KeyStatusType.ENABLED, 932 OutputPrefixType.TINK); 933 Keyset keyset = TestUtil.createKeyset(key1); 934 KeysetHandle handle = 935 KeysetHandle.fromKeyset(Keyset.newBuilder(keyset).setPrimaryKeyId(77).build()); 936 937 assertThrows(IllegalStateException.class, handle::getPrimary); 938 } 939 940 @Test testGetPrimary_disabledPrimary_throws()941 public void testGetPrimary_disabledPrimary_throws() throws Exception { 942 Keyset.Key key1 = 943 TestUtil.createKey( 944 TestUtil.createHmacKeyData("01234567890123456".getBytes(UTF_8), 16), 945 42, 946 KeyStatusType.DISABLED, 947 OutputPrefixType.TINK); 948 Keyset keyset = TestUtil.createKeyset(key1); 949 KeysetHandle handle = 950 KeysetHandle.fromKeyset(Keyset.newBuilder(keyset).setPrimaryKeyId(16).build()); 951 952 assertThrows(IllegalStateException.class, handle::getPrimary); 953 } 954 955 @Test testGetAt_indexOutOfBounds_throws()956 public void testGetAt_indexOutOfBounds_throws() throws Exception { 957 Keyset.Key key1 = 958 TestUtil.createKey( 959 TestUtil.createHmacKeyData("01234567890123456".getBytes(UTF_8), 16), 960 42, 961 KeyStatusType.ENABLED, 962 OutputPrefixType.TINK); 963 KeysetHandle handle = KeysetHandle.fromKeyset(TestUtil.createKeyset(key1)); 964 965 assertThrows(IndexOutOfBoundsException.class, () -> handle.getAt(-1)); 966 assertThrows(IndexOutOfBoundsException.class, () -> handle.getAt(1)); 967 } 968 969 @Test testGetAt_wrongStatus_throws()970 public void testGetAt_wrongStatus_throws() throws Exception { 971 Keyset.Key key1 = 972 TestUtil.createKey( 973 TestUtil.createHmacKeyData("01234567890123456".getBytes(UTF_8), 16), 974 42, 975 KeyStatusType.UNKNOWN_STATUS, 976 OutputPrefixType.TINK); 977 KeysetHandle handle = KeysetHandle.fromKeyset(TestUtil.createKeyset(key1)); 978 979 assertThrows(IllegalStateException.class, () -> handle.getAt(0)); 980 } 981 982 @Immutable 983 private static final class TestKey extends Key { 984 private final ByteString keymaterial; 985 TestKey(ByteString keymaterial)986 public TestKey(ByteString keymaterial) { 987 this.keymaterial = keymaterial; 988 } 989 990 @Override getParameters()991 public Parameters getParameters() { 992 throw new UnsupportedOperationException("Not needed in test"); 993 } 994 995 @Override 996 @Nullable getIdRequirementOrNull()997 public Integer getIdRequirementOrNull() { 998 throw new UnsupportedOperationException("Not needed in test"); 999 } 1000 1001 @Override equalsKey(Key other)1002 public boolean equalsKey(Key other) { 1003 throw new UnsupportedOperationException("Not needed in test"); 1004 } 1005 getKeyMaterial()1006 public ByteString getKeyMaterial() { 1007 return keymaterial; 1008 } 1009 } 1010 parseTestKey( ProtoKeySerialization serialization, @Nullable com.google.crypto.tink.SecretKeyAccess access)1011 private static TestKey parseTestKey( 1012 ProtoKeySerialization serialization, 1013 @Nullable com.google.crypto.tink.SecretKeyAccess access) { 1014 return new TestKey(serialization.getValue()); 1015 } 1016 1017 /** 1018 * Tests that key parsing via the serialization registry works as expected. 1019 * 1020 * <p>NOTE: This adds a parser to the MutableSerializationRegistry, which no other test uses. 1021 */ 1022 @Test testKeysAreParsed()1023 public void testKeysAreParsed() throws Exception { 1024 ByteString value = ByteString.copyFromUtf8("some value"); 1025 // NOTE: This adds a parser to the MutableSerializationRegistry, which no other test uses. 1026 MutableSerializationRegistry.globalInstance() 1027 .registerKeyParser( 1028 KeyParser.create( 1029 KeysetHandleTest::parseTestKey, 1030 Bytes.copyFrom("testKeyTypeUrl".getBytes(UTF_8)), 1031 ProtoKeySerialization.class)); 1032 Keyset keyset = 1033 Keyset.newBuilder() 1034 .setPrimaryKeyId(1) 1035 .addKey( 1036 Keyset.Key.newBuilder() 1037 .setKeyId(1) 1038 .setStatus(KeyStatusType.ENABLED) 1039 .setKeyData(KeyData.newBuilder().setTypeUrl("testKeyTypeUrl").setValue(value))) 1040 .build(); 1041 KeysetHandle handle = KeysetHandle.fromKeyset(keyset); 1042 assertThat(((TestKey) handle.getPrimary().getKey()).getKeyMaterial()).isEqualTo(value); 1043 } 1044 1045 @Test testBuilder_basic()1046 public void testBuilder_basic() throws Exception { 1047 KeysetHandle keysetHandle = 1048 KeysetHandle.newBuilder() 1049 .addEntry( 1050 KeysetHandle.generateEntryFromParametersName("AES256_CMAC_RAW") 1051 .withRandomId() 1052 .makePrimary()) 1053 .build(); 1054 1055 assertThat(keysetHandle.size()).isEqualTo(1); 1056 assertThat(keysetHandle.getAt(0).getKey().getParameters()) 1057 .isEqualTo(AesCmacParameters.builder().setKeySizeBytes(32).setTagSizeBytes(16).build()); 1058 } 1059 1060 @Test keysetRotationWithBuilder_works()1061 public void keysetRotationWithBuilder_works() throws Exception { 1062 KeysetHandle oldKeyset = 1063 KeysetHandle.newBuilder() 1064 .addEntry( 1065 KeysetHandle.generateEntryFromParametersName("AES256_CMAC_RAW") 1066 .withRandomId() 1067 .makePrimary()) 1068 .build(); 1069 1070 // Add new key. 1071 KeysetHandle keysetWithNewKey = 1072 KeysetHandle.newBuilder(oldKeyset) 1073 .addEntry( 1074 KeysetHandle.generateEntryFromParametersName("AES256_CMAC_RAW").withRandomId()) 1075 .build(); 1076 1077 // Make latest key primary. 1078 KeysetHandle.Builder builder = KeysetHandle.newBuilder(keysetWithNewKey); 1079 builder.getAt(builder.size() - 1).makePrimary(); 1080 KeysetHandle keysetWithNewPrimary = builder.build(); 1081 1082 assertThat(oldKeyset.size()).isEqualTo(1); 1083 1084 assertThat(keysetWithNewKey.size()).isEqualTo(2); 1085 assertThat(keysetWithNewKey.getAt(0).isPrimary()).isTrue(); 1086 assertThat(keysetWithNewKey.getAt(1).isPrimary()).isFalse(); 1087 1088 assertThat(keysetWithNewPrimary.size()).isEqualTo(2); 1089 assertThat(keysetWithNewPrimary.getAt(0).isPrimary()).isFalse(); 1090 assertThat(keysetWithNewPrimary.getAt(1).isPrimary()).isTrue(); 1091 } 1092 1093 @Test testBuilder_multipleKeys()1094 public void testBuilder_multipleKeys() throws Exception { 1095 KeysetHandle keysetHandle = 1096 KeysetHandle.newBuilder() 1097 .addEntry( 1098 KeysetHandle.generateEntryFromParametersName("AES256_CMAC_RAW") 1099 .withRandomId() 1100 .setStatus(KeyStatus.DISABLED)) 1101 .addEntry( 1102 KeysetHandle.generateEntryFromParameters( 1103 AesCmacParameters.builder().setKeySizeBytes(32).setTagSizeBytes(10) 1104 .setVariant(Variant.CRUNCHY).build()) 1105 .withRandomId() 1106 .makePrimary()) 1107 .addEntry( 1108 KeysetHandle.generateEntryFromParameters( 1109 AesCmacParameters.builder().setKeySizeBytes(32).setTagSizeBytes(13) 1110 .setVariant(Variant.LEGACY).build()) 1111 .withRandomId()) 1112 .build(); 1113 assertThat(keysetHandle.size()).isEqualTo(3); 1114 KeysetHandle.Entry entry0 = keysetHandle.getAt(0); 1115 assertThat(entry0.getKey().getParameters()) 1116 .isEqualTo(AesCmacParameters.builder().setKeySizeBytes(32).setTagSizeBytes(16).build()); 1117 assertThat(entry0.isPrimary()).isFalse(); 1118 assertThat(entry0.getStatus()).isEqualTo(KeyStatus.DISABLED); 1119 1120 KeysetHandle.Entry entry1 = keysetHandle.getAt(1); 1121 assertThat(entry1.isPrimary()).isTrue(); 1122 assertThat(entry1.getStatus()).isEqualTo(KeyStatus.ENABLED); 1123 assertThat(entry1.getKey().getParameters()) 1124 .isEqualTo( 1125 AesCmacParameters.builder().setKeySizeBytes(32).setTagSizeBytes(10) 1126 .setVariant(Variant.CRUNCHY).build()); 1127 1128 KeysetHandle.Entry entry2 = keysetHandle.getAt(2); 1129 assertThat(entry2.isPrimary()).isFalse(); 1130 assertThat(entry2.getStatus()).isEqualTo(KeyStatus.ENABLED); 1131 assertThat(keysetHandle.getAt(2).getKey().getParameters()) 1132 .isEqualTo( 1133 AesCmacParameters.builder().setKeySizeBytes(32).setTagSizeBytes(13) 1134 .setVariant(Variant.LEGACY).build()); 1135 } 1136 1137 @Test testBuilder_isPrimary_works()1138 public void testBuilder_isPrimary_works() throws Exception { 1139 KeysetHandle.Builder builder = KeysetHandle.newBuilder(); 1140 builder.addEntry(KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId()); 1141 assertThat(builder.getAt(0).isPrimary()).isFalse(); 1142 builder.getAt(0).makePrimary(); 1143 assertThat(builder.getAt(0).isPrimary()).isTrue(); 1144 } 1145 1146 @Test testBuilder_setStatus_getStatus_works()1147 public void testBuilder_setStatus_getStatus_works() throws Exception { 1148 KeysetHandle.Builder.Entry entry = 1149 KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId(); 1150 assertThat(entry.getStatus()).isEqualTo(KeyStatus.ENABLED); 1151 entry.setStatus(KeyStatus.DISABLED); 1152 assertThat(entry.getStatus()).isEqualTo(KeyStatus.DISABLED); 1153 entry.setStatus(KeyStatus.DESTROYED); 1154 assertThat(entry.getStatus()).isEqualTo(KeyStatus.DESTROYED); 1155 } 1156 1157 @Test 1158 // Tests that withRandomId avoids collisions. We use 2^16 keys to make collision likely. The test 1159 // is about 4 seconds like this. testBuilder_withRandomId_doesNotHaveCollisions()1160 public void testBuilder_withRandomId_doesNotHaveCollisions() throws Exception { 1161 // Test takes longer on Android; and a simple Java test suffices. 1162 assumeFalse(TestUtil.isAndroid()); 1163 int numNonPrimaryKeys = 1 << 16; 1164 KeysetHandle.Builder builder = KeysetHandle.newBuilder(); 1165 builder.addEntry( 1166 KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId().makePrimary()); 1167 for (int i = 0; i < numNonPrimaryKeys; i++) { 1168 builder.addEntry(KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId()); 1169 } 1170 KeysetHandle handle = builder.build(); 1171 Set<Integer> idSet = new HashSet<>(); 1172 for (int i = 0; i < handle.size(); ++i) { 1173 idSet.add(handle.getAt(i).getId()); 1174 } 1175 assertThat(idSet).hasSize(numNonPrimaryKeys + 1); 1176 } 1177 1178 @Test testBuilder_randomIdAfterFixedId_works()1179 public void testBuilder_randomIdAfterFixedId_works() throws Exception { 1180 KeysetHandle handle = 1181 KeysetHandle.newBuilder() 1182 .addEntry(KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withFixedId(777)) 1183 .addEntry( 1184 KeysetHandle.generateEntryFromParametersName("AES256_CMAC") 1185 .withRandomId() 1186 .makePrimary()) 1187 .build(); 1188 assertThat(handle.size()).isEqualTo(2); 1189 assertThat(handle.getAt(0).getId()).isEqualTo(777); 1190 } 1191 1192 @Test testBuilder_fixedIdAfterRandomId_throws()1193 public void testBuilder_fixedIdAfterRandomId_throws() throws Exception { 1194 KeysetHandle.Builder builder = KeysetHandle.newBuilder(); 1195 builder.addEntry( 1196 KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId().makePrimary()); 1197 builder.addEntry(KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withFixedId(777)); 1198 assertThrows(GeneralSecurityException.class, builder::build); 1199 } 1200 1201 @Test testBuilder_deprecated_removeAt_works()1202 public void testBuilder_deprecated_removeAt_works() throws Exception { 1203 KeysetHandle.Builder builder = KeysetHandle.newBuilder(); 1204 builder.addEntry( 1205 KeysetHandle.generateEntryFromParametersName("AES256_CMAC") 1206 .withRandomId() 1207 .setStatus(KeyStatus.DISABLED)); 1208 builder.addEntry( 1209 KeysetHandle.generateEntryFromParameters( 1210 AesCmacParameters.builder().setKeySizeBytes(32).setTagSizeBytes(13).build()) 1211 .withRandomId() 1212 .makePrimary() 1213 .setStatus(KeyStatus.ENABLED)); 1214 KeysetHandle.Builder.Entry removedEntry = builder.removeAt(0); 1215 assertThat(removedEntry.getStatus()).isEqualTo(KeyStatus.DISABLED); 1216 KeysetHandle handle = builder.build(); 1217 assertThat(handle.size()).isEqualTo(1); 1218 assertThat(handle.getAt(0).getKey().getParameters()) 1219 .isEqualTo(AesCmacParameters.builder().setKeySizeBytes(32).setTagSizeBytes(13).build()); 1220 } 1221 1222 @Test testBuilder_deprecated_removeAtInvalidIndex_throws()1223 public void testBuilder_deprecated_removeAtInvalidIndex_throws() throws Exception { 1224 KeysetHandle.Builder builder = KeysetHandle.newBuilder(); 1225 builder.addEntry(KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId()); 1226 builder.addEntry( 1227 KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId().makePrimary()); 1228 assertThrows(IndexOutOfBoundsException.class, () -> builder.removeAt(2)); 1229 } 1230 1231 @Test testBuilder_deleteAt_works()1232 public void testBuilder_deleteAt_works() throws Exception { 1233 KeysetHandle handle = 1234 KeysetHandle.newBuilder() 1235 .addEntry(KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId()) 1236 .addEntry( 1237 KeysetHandle.generateEntryFromParameters( 1238 AesCmacParameters.builder().setKeySizeBytes(32).setTagSizeBytes(13).build()) 1239 .withRandomId() 1240 .makePrimary()) 1241 .build(); 1242 assertThat(handle.size()).isEqualTo(2); 1243 1244 KeysetHandle handle2 = KeysetHandle.newBuilder(handle).deleteAt(0).build(); 1245 1246 assertThat(handle2.size()).isEqualTo(1); 1247 assertThat(handle2.getAt(0).getKey().getParameters()) 1248 .isEqualTo(AesCmacParameters.builder().setKeySizeBytes(32).setTagSizeBytes(13).build()); 1249 } 1250 1251 @Test testBuilder_deleteAtInvalidIndex_works()1252 public void testBuilder_deleteAtInvalidIndex_works() throws Exception { 1253 KeysetHandle handle = 1254 KeysetHandle.newBuilder() 1255 .addEntry(KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId()) 1256 .addEntry( 1257 KeysetHandle.generateEntryFromParametersName("AES256_CMAC") 1258 .withRandomId() 1259 .makePrimary()) 1260 .build(); 1261 assertThat(handle.size()).isEqualTo(2); 1262 1263 assertThrows( 1264 IndexOutOfBoundsException.class, () -> KeysetHandle.newBuilder(handle).deleteAt(2)); 1265 } 1266 1267 @Test testBuilder_size_works()1268 public void testBuilder_size_works() throws Exception { 1269 KeysetHandle.Builder builder = KeysetHandle.newBuilder(); 1270 assertThat(builder.size()).isEqualTo(0); 1271 builder.addEntry( 1272 KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId().makePrimary()); 1273 assertThat(builder.size()).isEqualTo(1); 1274 builder.addEntry(KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId()); 1275 assertThat(builder.size()).isEqualTo(2); 1276 } 1277 1278 @Test testBuilder_noPrimary_throws()1279 public void testBuilder_noPrimary_throws() throws Exception { 1280 KeysetHandle.Builder builder = KeysetHandle.newBuilder(); 1281 builder.addEntry(KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId()); 1282 builder.addEntry(KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId()); 1283 assertThrows(GeneralSecurityException.class, builder::build); 1284 } 1285 1286 @Test testBuilder_removedPrimary_throws()1287 public void testBuilder_removedPrimary_throws() throws Exception { 1288 KeysetHandle.Builder builder = KeysetHandle.newBuilder(); 1289 builder.addEntry( 1290 KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId().makePrimary()); 1291 builder.addEntry(KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId()); 1292 builder.removeAt(0); 1293 assertThrows(GeneralSecurityException.class, builder::build); 1294 } 1295 1296 @Test testBuilder_deletedPrimary_throws()1297 public void testBuilder_deletedPrimary_throws() throws Exception { 1298 KeysetHandle.Builder builder = 1299 KeysetHandle.newBuilder() 1300 .addEntry( 1301 KeysetHandle.generateEntryFromParametersName("AES256_CMAC") 1302 .withRandomId() 1303 .makePrimary()) 1304 .addEntry(KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId()) 1305 .deleteAt(0); 1306 assertThrows(GeneralSecurityException.class, builder::build); 1307 } 1308 1309 @Test testBuilder_addPrimary_clearsOtherPrimary()1310 public void testBuilder_addPrimary_clearsOtherPrimary() throws Exception { 1311 KeysetHandle.Builder builder = KeysetHandle.newBuilder(); 1312 builder.addEntry( 1313 KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId().makePrimary()); 1314 builder.addEntry( 1315 KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId().makePrimary()); 1316 assertThat(builder.getAt(0).isPrimary()).isFalse(); 1317 } 1318 1319 @Test testBuilder_setPrimary_clearsOtherPrimary()1320 public void testBuilder_setPrimary_clearsOtherPrimary() throws Exception { 1321 KeysetHandle.Builder builder = KeysetHandle.newBuilder(); 1322 builder.addEntry( 1323 KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId().makePrimary()); 1324 builder.addEntry(KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId()); 1325 builder.getAt(1).makePrimary(); 1326 assertThat(builder.getAt(0).isPrimary()).isFalse(); 1327 } 1328 1329 @Test testBuilder_noIdSet_throws()1330 public void testBuilder_noIdSet_throws() throws Exception { 1331 KeysetHandle.Builder builder = KeysetHandle.newBuilder(); 1332 builder.addEntry(KeysetHandle.generateEntryFromParametersName("AES256_CMAC").makePrimary()); 1333 assertThrows(GeneralSecurityException.class, builder::build); 1334 } 1335 1336 @Test testBuilder_doubleId_throws()1337 public void testBuilder_doubleId_throws() throws Exception { 1338 KeysetHandle.Builder builder = KeysetHandle.newBuilder(); 1339 builder.addEntry( 1340 KeysetHandle.generateEntryFromParametersName("AES256_CMAC").makePrimary().withFixedId(777)); 1341 builder.addEntry(KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withFixedId(777)); 1342 assertThrows(GeneralSecurityException.class, builder::build); 1343 } 1344 1345 @Test testBuilder_createFromKeysetHandle_works()1346 public void testBuilder_createFromKeysetHandle_works() throws Exception { 1347 KeysetHandle.Builder builder = KeysetHandle.newBuilder(); 1348 builder.addEntry( 1349 KeysetHandle.generateEntryFromParametersName("AES256_CMAC").makePrimary().withRandomId()); 1350 builder.addEntry(KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withRandomId()); 1351 KeysetHandle originalKeyset = builder.build(); 1352 1353 builder = KeysetHandle.newBuilder(originalKeyset); 1354 KeysetHandle secondKeyset = builder.build(); 1355 1356 assertThat(secondKeyset.size()).isEqualTo(2); 1357 assertThat(secondKeyset.getAt(0).getKey().equalsKey(originalKeyset.getAt(0).getKey())).isTrue(); 1358 assertThat(secondKeyset.getAt(1).getKey().equalsKey(originalKeyset.getAt(1).getKey())).isTrue(); 1359 assertThat(secondKeyset.getAt(0).getStatus()).isEqualTo(originalKeyset.getAt(0).getStatus()); 1360 assertThat(secondKeyset.getAt(1).getStatus()).isEqualTo(originalKeyset.getAt(1).getStatus()); 1361 assertThat(secondKeyset.getAt(0).isPrimary()).isTrue(); 1362 } 1363 1364 @Test testBuilder_copyKeyset_works()1365 public void testBuilder_copyKeyset_works() throws Exception { 1366 KeysetHandle original = 1367 KeysetHandle.newBuilder() 1368 .addEntry(KeysetHandle.generateEntryFromParametersName("AES256_CMAC").withFixedId(777)) 1369 .addEntry( 1370 KeysetHandle.generateEntryFromParametersName("AES256_CMAC") 1371 .makePrimary() 1372 .withFixedId(778)) 1373 .build(); 1374 KeysetHandle copy = KeysetHandle.newBuilder(original).build(); 1375 assertThat(copy.size()).isEqualTo(2); 1376 assertThat(copy.getAt(0).getId()).isEqualTo(777); 1377 assertThat(copy.getAt(0).getKey().equalsKey(original.getAt(0).getKey())).isTrue(); 1378 assertThat(copy.getAt(0).getStatus()).isEqualTo(original.getAt(0).getStatus()); 1379 assertThat(copy.getAt(1).getId()).isEqualTo(778); 1380 assertThat(copy.getAt(1).getKey().equalsKey(original.getAt(1).getKey())).isTrue(); 1381 assertThat(copy.getAt(1).getStatus()).isEqualTo(original.getAt(1).getStatus()); 1382 } 1383 1384 @Test testBuilder_copyKeyset_originalHasInvalidKey_throws()1385 public void testBuilder_copyKeyset_originalHasInvalidKey_throws() throws Exception { 1386 Keyset keyset = 1387 Keyset.newBuilder() 1388 .setPrimaryKeyId(1) 1389 .addKey( 1390 Keyset.Key.newBuilder() 1391 .setKeyId(1) 1392 .setStatus(KeyStatusType.ENABLED) 1393 .setKeyData( 1394 KeyData.newBuilder() 1395 .setTypeUrl("type.googleapis.com/google.crypto.tink.AesGcmKey") 1396 .setValue(ByteString.EMPTY))) 1397 .build(); 1398 KeysetHandle.Builder builder = KeysetHandle.newBuilder(KeysetHandle.fromKeyset(keyset)); 1399 GeneralSecurityException thrown = assertThrows(GeneralSecurityException.class, builder::build); 1400 assertThat(thrown) 1401 .hasCauseThat() 1402 .hasMessageThat() 1403 .contains("wrong status or key parsing failed"); 1404 } 1405 1406 @Test testBuilder_copyKeyset_originalHasNoPrimary_throws()1407 public void testBuilder_copyKeyset_originalHasNoPrimary_throws() throws Exception { 1408 KeysetHandle original = 1409 KeysetHandle.newBuilder() 1410 .addEntry( 1411 KeysetHandle.generateEntryFromParametersName("AES256_CMAC") 1412 .makePrimary() 1413 .withFixedId(778)) 1414 .build(); 1415 Keyset keyset = original.getKeyset(); 1416 Keyset keysetWithoutPrimary = keyset.toBuilder().setPrimaryKeyId(3843).build(); 1417 1418 KeysetHandle.Builder builder = 1419 KeysetHandle.newBuilder(KeysetHandle.fromKeyset(keysetWithoutPrimary)); 1420 GeneralSecurityException thrown = assertThrows(GeneralSecurityException.class, builder::build); 1421 assertThat(thrown).hasMessageThat().contains("No primary was set"); 1422 } 1423 1424 @Test testBuilder_buildTwice_fails()1425 public void testBuilder_buildTwice_fails() throws Exception { 1426 KeysetHandle.Builder builder = 1427 KeysetHandle.newBuilder() 1428 .addEntry( 1429 KeysetHandle.generateEntryFromParametersName("AES256_CMAC_RAW") 1430 .withRandomId() 1431 .makePrimary()); 1432 1433 Object unused = builder.build(); 1434 // We disallow calling build on the same builder twice. The reason is that build assigns IDs 1435 // which were marked with "withRandomId()". Doing this twice results in incompatible keysets, 1436 // which would be confusing. 1437 assertThrows(GeneralSecurityException.class, builder::build); 1438 } 1439 1440 @Test testImportKey_withoutIdRequirement_withFixedId_works()1441 public void testImportKey_withoutIdRequirement_withFixedId_works() throws Exception { 1442 AesCmacParameters params = AesCmacParameters.builder().setKeySizeBytes(32).setTagSizeBytes(10) 1443 .build(); 1444 AesCmacKey key = AesCmacKey.builder().setParameters(params) 1445 .setAesKeyBytes(SecretBytes.randomBytes(32)).build(); 1446 KeysetHandle handle = 1447 KeysetHandle.newBuilder() 1448 .addEntry(KeysetHandle.importKey(key).withFixedId(102).makePrimary()) 1449 .build(); 1450 assertThat(handle.size()).isEqualTo(1); 1451 assertThat(handle.getAt(0).getId()).isEqualTo(102); 1452 assertThat(handle.getAt(0).getKey().equalsKey(key)).isTrue(); 1453 } 1454 1455 @Test testImportKey_withoutIdRequirement_noIdAssigned_throws()1456 public void testImportKey_withoutIdRequirement_noIdAssigned_throws() throws Exception { 1457 AesCmacParameters params = AesCmacParameters.builder().setKeySizeBytes(32).setTagSizeBytes(10) 1458 .build(); 1459 AesCmacKey key = AesCmacKey.builder().setParameters(params) 1460 .setAesKeyBytes(SecretBytes.randomBytes(32)).build(); 1461 KeysetHandle.Builder builder = 1462 KeysetHandle.newBuilder().addEntry(KeysetHandle.importKey(key).makePrimary()); 1463 assertThrows(GeneralSecurityException.class, builder::build); 1464 } 1465 1466 @Test testImportKey_withoutIdRequirement_withRandomId_works()1467 public void testImportKey_withoutIdRequirement_withRandomId_works() throws Exception { 1468 AesCmacParameters params = AesCmacParameters.builder().setKeySizeBytes(32).setTagSizeBytes(10) 1469 .build(); 1470 AesCmacKey key = AesCmacKey.builder().setParameters(params) 1471 .setAesKeyBytes(SecretBytes.randomBytes(32)).build(); 1472 KeysetHandle handle = 1473 KeysetHandle.newBuilder() 1474 .addEntry(KeysetHandle.importKey(key).withRandomId().makePrimary()) 1475 .build(); 1476 assertThat(handle.size()).isEqualTo(1); 1477 assertThat(handle.getAt(0).getKey().equalsKey(key)).isTrue(); 1478 } 1479 1480 @Test testImportKey_withIdRequirement_noId_works()1481 public void testImportKey_withIdRequirement_noId_works() throws Exception { 1482 AesCmacParameters params = 1483 AesCmacParameters.builder().setKeySizeBytes(32).setTagSizeBytes(10).setVariant(Variant.TINK) 1484 .build(); 1485 AesCmacKey key = 1486 AesCmacKey.builder() 1487 .setParameters(params) 1488 .setAesKeyBytes(SecretBytes.randomBytes(32)) 1489 .setIdRequirement(105) 1490 .build(); 1491 KeysetHandle handle = 1492 KeysetHandle.newBuilder().addEntry(KeysetHandle.importKey(key).makePrimary()).build(); 1493 assertThat(handle.size()).isEqualTo(1); 1494 assertThat(handle.getAt(0).getId()).isEqualTo(105); 1495 assertThat(handle.getAt(0).getKey().equalsKey(key)).isTrue(); 1496 } 1497 1498 @Test testImportKey_withIdRequirement_randomId_throws()1499 public void testImportKey_withIdRequirement_randomId_throws() throws Exception { 1500 AesCmacParameters params = 1501 AesCmacParameters.builder().setKeySizeBytes(32).setTagSizeBytes(10).setVariant(Variant.TINK) 1502 .build(); 1503 AesCmacKey key = 1504 AesCmacKey.builder() 1505 .setParameters(params) 1506 .setAesKeyBytes(SecretBytes.randomBytes(32)) 1507 .setIdRequirement(105) 1508 .build(); 1509 KeysetHandle.Builder builder = 1510 KeysetHandle.newBuilder() 1511 .addEntry(KeysetHandle.importKey(key).withRandomId().makePrimary()); 1512 assertThrows(GeneralSecurityException.class, builder::build); 1513 } 1514 1515 @Test testImportKey_withIdRequirement_explicitlySetToCorrectId_works()1516 public void testImportKey_withIdRequirement_explicitlySetToCorrectId_works() throws Exception { 1517 AesCmacParameters params = 1518 AesCmacParameters.builder().setKeySizeBytes(32).setTagSizeBytes(10).setVariant(Variant.TINK) 1519 .build(); 1520 AesCmacKey key = 1521 AesCmacKey.builder() 1522 .setParameters(params) 1523 .setAesKeyBytes(SecretBytes.randomBytes(32)) 1524 .setIdRequirement(105) 1525 .build(); 1526 KeysetHandle handle = 1527 KeysetHandle.newBuilder() 1528 .addEntry(KeysetHandle.importKey(key).withFixedId(105).makePrimary()) 1529 .build(); 1530 assertThat(handle.size()).isEqualTo(1); 1531 assertThat(handle.getAt(0).getId()).isEqualTo(105); 1532 assertThat(handle.getAt(0).getKey().equalsKey(key)).isTrue(); 1533 } 1534 1535 @Test testImportKey_withIdRequirement_explicitlySetToWrongId_throws()1536 public void testImportKey_withIdRequirement_explicitlySetToWrongId_throws() throws Exception { 1537 AesCmacParameters params = 1538 AesCmacParameters.builder().setKeySizeBytes(32).setTagSizeBytes(10).setVariant(Variant.TINK) 1539 .build(); 1540 AesCmacKey key = 1541 AesCmacKey.builder() 1542 .setParameters(params) 1543 .setAesKeyBytes(SecretBytes.randomBytes(32)) 1544 .setIdRequirement(105) 1545 .build(); 1546 KeysetHandle.Builder builder = 1547 KeysetHandle.newBuilder() 1548 .addEntry(KeysetHandle.importKey(key).withFixedId(106).makePrimary()); 1549 assertThrows(GeneralSecurityException.class, builder::build); 1550 } 1551 1552 @Test testAddEntry_addTwice_throws()1553 public void testAddEntry_addTwice_throws() throws Exception { 1554 KeysetHandle.Builder builder = KeysetHandle.newBuilder(); 1555 KeysetHandle.Builder.Entry entry = 1556 KeysetHandle.generateEntryFromParametersName("AES256_CMAC").makePrimary().withRandomId(); 1557 builder.addEntry(entry); 1558 assertThrows(IllegalStateException.class, () -> builder.addEntry(entry)); 1559 } 1560 1561 @Test testSetStatusNull_throws()1562 public void testSetStatusNull_throws() throws Exception { 1563 KeysetHandle.Builder builder = KeysetHandle.newBuilder(); 1564 builder.addEntry( 1565 KeysetHandle.generateEntryFromParametersName("AES256_CMAC") 1566 .makePrimary() 1567 .withRandomId() 1568 .setStatus(null)); 1569 assertThrows(GeneralSecurityException.class, builder::build); 1570 } 1571 1572 @Test testStatusNotSet_getPrimitive_throws()1573 public void testStatusNotSet_getPrimitive_throws() throws Exception { 1574 Keyset keyset = 1575 Keyset.newBuilder() 1576 .setPrimaryKeyId(1) 1577 .addKey( 1578 Keyset.Key.newBuilder() 1579 .setKeyId(1) 1580 .setStatus(KeyStatusType.ENABLED) 1581 .setOutputPrefixType(OutputPrefixType.TINK) 1582 .setKeyData(KeyData.newBuilder().setTypeUrl("unregisteredTypeUrl"))) 1583 .build(); 1584 KeysetHandle handle = KeysetHandle.fromKeyset(keyset); 1585 GeneralSecurityException e = 1586 assertThrows(GeneralSecurityException.class, () -> handle.getPrimitive(Aead.class)); 1587 assertThat(e).hasMessageThat().contains("Unable to get primitive"); 1588 assertThat(e).hasMessageThat().contains("unregisteredTypeUrl"); 1589 } 1590 1591 @Immutable 1592 private static final class TestPrimitiveA { TestPrimitiveA()1593 public TestPrimitiveA() {} 1594 } 1595 1596 @Immutable 1597 private static final class TestPrimitiveB { TestPrimitiveB()1598 public TestPrimitiveB() {} 1599 } 1600 1601 @Immutable 1602 private static final class TestWrapperA 1603 implements PrimitiveWrapper<TestPrimitiveA, TestPrimitiveB> { 1604 1605 @Override wrap(final PrimitiveSet<TestPrimitiveA> primitives)1606 public TestPrimitiveB wrap(final PrimitiveSet<TestPrimitiveA> primitives) { 1607 return new TestPrimitiveB(); 1608 } 1609 1610 @Override getPrimitiveClass()1611 public Class<TestPrimitiveB> getPrimitiveClass() { 1612 return TestPrimitiveB.class; 1613 } 1614 1615 @Override getInputPrimitiveClass()1616 public Class<TestPrimitiveA> getInputPrimitiveClass() { 1617 return TestPrimitiveA.class; 1618 } 1619 } 1620 getPrimitiveAHmacKey(HmacKey key)1621 private static TestPrimitiveA getPrimitiveAHmacKey(HmacKey key) { 1622 return new TestPrimitiveA(); 1623 } 1624 1625 @Test getPrimitive_usesProvidedConfigurationWhenProvided()1626 public void getPrimitive_usesProvidedConfigurationWhenProvided() throws Exception { 1627 PrimitiveRegistry registry = 1628 PrimitiveRegistry.builder() 1629 .registerPrimitiveConstructor( 1630 PrimitiveConstructor.create( 1631 KeysetHandleTest::getPrimitiveAHmacKey, 1632 HmacKey.class, 1633 TestPrimitiveA.class)) 1634 .registerPrimitiveWrapper(new TestWrapperA()) 1635 .build(); 1636 InternalConfiguration configuration = 1637 InternalConfiguration.createFromPrimitiveRegistry(registry); 1638 HmacKey hmacKey = 1639 HmacKey.builder() 1640 .setParameters( 1641 HmacParameters.builder() 1642 .setKeySizeBytes(20) 1643 .setTagSizeBytes(10) 1644 .setVariant(HmacParameters.Variant.NO_PREFIX) 1645 .setHashType(HmacParameters.HashType.SHA256) 1646 .build()) 1647 .setKeyBytes(SecretBytes.randomBytes(20)) 1648 .setIdRequirement(null) 1649 .build(); 1650 KeysetHandle keysetHandle = 1651 KeysetHandle.newBuilder() 1652 .addEntry(KeysetHandle.importKey(hmacKey).withRandomId().makePrimary()) 1653 .build(); 1654 1655 assertThrows( 1656 GeneralSecurityException.class, () -> keysetHandle.getPrimitive(TestPrimitiveB.class)); 1657 assertThat(keysetHandle.getPrimitive(configuration, TestPrimitiveB.class)).isNotNull(); 1658 } 1659 1660 @Test getPrimitive_usesRegistryWhenNoConfigurationProvided()1661 public void getPrimitive_usesRegistryWhenNoConfigurationProvided() throws Exception { 1662 KeysetHandle keysetHandle = 1663 KeysetHandle.newBuilder() 1664 .addEntry(KeysetHandle.importKey(rawKey).withRandomId().makePrimary()) 1665 .build(); 1666 byte[] plaintext = "plaintext".getBytes(UTF_8); 1667 1668 ChunkedMac registryMac = 1669 MutablePrimitiveRegistry.globalInstance().getPrimitive(rawKey, ChunkedMac.class); 1670 ChunkedMacComputation registryMacComputation = registryMac.createComputation(); 1671 registryMacComputation.update(ByteBuffer.wrap(plaintext)); 1672 ChunkedMac keysetHandleMac = keysetHandle.getPrimitive(ChunkedMac.class); 1673 ChunkedMacComputation keysetHandleMacComputation = keysetHandleMac.createComputation(); 1674 keysetHandleMacComputation.update(ByteBuffer.wrap(plaintext)); 1675 1676 assertThat(keysetHandleMacComputation.computeMac()) 1677 .isEqualTo(registryMacComputation.computeMac()); 1678 } 1679 1680 @Test getLegacyPrimitive_usesRegistryWhenNoConfigurationProvided()1681 public void getLegacyPrimitive_usesRegistryWhenNoConfigurationProvided() 1682 throws Exception { 1683 KeysetHandle keysetHandle = 1684 KeysetHandle.newBuilder() 1685 .addEntry(KeysetHandle.importKey(rawKey).withRandomId().makePrimary()) 1686 .build(); 1687 KeyData rawKeyData = 1688 KeyData.newBuilder() 1689 .setValue( 1690 com.google.crypto.tink.proto.HmacKey.newBuilder() 1691 .setParams( 1692 HmacParams.newBuilder() 1693 .setHash(com.google.crypto.tink.proto.HashType.SHA256) 1694 .setTagSize(HMAC_TAG_SIZE) 1695 .build()) 1696 .setKeyValue( 1697 ByteString.copyFrom( 1698 rawKey.getKeyBytes().toByteArray(InsecureSecretKeyAccess.get()))) 1699 .build() 1700 .toByteString()) 1701 .setTypeUrl(keysetHandle.getKeysetInfo().getKeyInfo(0).getTypeUrl()) 1702 .setKeyMaterialType(KeyMaterialType.SYMMETRIC) 1703 .build(); 1704 1705 byte[] plaintext = "plaintext".getBytes(UTF_8); 1706 1707 Mac registryMac = Registry.getPrimitive(rawKeyData, Mac.class); 1708 Mac keysetHandleMac = keysetHandle.getPrimitive(Mac.class); 1709 1710 assertThat(keysetHandleMac.computeMac(plaintext)).isEqualTo(registryMac.computeMac(plaintext)); 1711 } 1712 1713 @Test keysetEquality_singleKeyEquals_returnsTrue()1714 public void keysetEquality_singleKeyEquals_returnsTrue() throws Exception { 1715 SecretBytes bytes = SecretBytes.randomBytes(32); 1716 1717 KeysetHandle keysetHandle1 = 1718 KeysetHandle.newBuilder() 1719 .addEntry( 1720 KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes)) 1721 .withFixedId(101) 1722 .makePrimary()) 1723 .build(); 1724 KeysetHandle keysetHandle2 = 1725 KeysetHandle.newBuilder() 1726 .addEntry( 1727 KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes)) 1728 .withFixedId(101) 1729 .makePrimary()) 1730 .build(); 1731 1732 assertTrue(keysetHandle1.equalsKeyset(keysetHandle2)); 1733 } 1734 1735 @Test keysetEquality_singleKeyDifferentKeys_returnsFalse()1736 public void keysetEquality_singleKeyDifferentKeys_returnsFalse() throws Exception { 1737 SecretBytes bytes = SecretBytes.randomBytes(32); 1738 1739 KeysetHandle keysetHandle1 = 1740 KeysetHandle.newBuilder() 1741 .addEntry( 1742 KeysetHandle.importKey( 1743 XChaCha20Poly1305Key.create( 1744 XChaCha20Poly1305Parameters.Variant.TINK, bytes, 101)) 1745 .withFixedId(101) 1746 .makePrimary()) 1747 .build(); 1748 KeysetHandle keysetHandle2 = 1749 KeysetHandle.newBuilder() 1750 .addEntry( 1751 KeysetHandle.importKey( 1752 XChaCha20Poly1305Key.create( 1753 XChaCha20Poly1305Parameters.Variant.CRUNCHY, bytes, 101)) 1754 .withFixedId(101) 1755 .makePrimary()) 1756 .build(); 1757 1758 assertFalse(keysetHandle1.equalsKeyset(keysetHandle2)); 1759 } 1760 1761 @Test keysetEquality_singleKeyDifferentId_returnsFalse()1762 public void keysetEquality_singleKeyDifferentId_returnsFalse() throws Exception { 1763 SecretBytes bytes = SecretBytes.randomBytes(32); 1764 1765 KeysetHandle keysetHandle1 = 1766 KeysetHandle.newBuilder() 1767 .addEntry( 1768 KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes)) 1769 .withFixedId(102) 1770 .makePrimary()) 1771 .build(); 1772 KeysetHandle keysetHandle2 = 1773 KeysetHandle.newBuilder() 1774 .addEntry( 1775 KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes)) 1776 .withFixedId(103) 1777 .makePrimary()) 1778 .build(); 1779 1780 assertFalse(keysetHandle1.equalsKeyset(keysetHandle2)); 1781 } 1782 1783 @Test keysetEquality_twoKeysEquals_returnsTrue()1784 public void keysetEquality_twoKeysEquals_returnsTrue() throws Exception { 1785 SecretBytes bytes1 = SecretBytes.randomBytes(32); 1786 SecretBytes bytes2 = SecretBytes.randomBytes(32); 1787 1788 KeysetHandle keysetHandle1 = 1789 KeysetHandle.newBuilder() 1790 .addEntry( 1791 KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes1)) 1792 .withFixedId(101) 1793 .makePrimary()) 1794 .addEntry(KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes2)).withFixedId(102)) 1795 .build(); 1796 KeysetHandle keysetHandle2 = 1797 KeysetHandle.newBuilder() 1798 .addEntry( 1799 KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes1)) 1800 .withFixedId(101) 1801 .makePrimary()) 1802 .addEntry(KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes2)).withFixedId(102)) 1803 .build(); 1804 1805 assertTrue(keysetHandle1.equalsKeyset(keysetHandle2)); 1806 } 1807 1808 @Test keysetEquality_twoKeysDifferentPrimaries_returnsFalse()1809 public void keysetEquality_twoKeysDifferentPrimaries_returnsFalse() throws Exception { 1810 SecretBytes bytes1 = SecretBytes.randomBytes(32); 1811 SecretBytes bytes2 = SecretBytes.randomBytes(32); 1812 1813 KeysetHandle keysetHandle1 = 1814 KeysetHandle.newBuilder() 1815 .addEntry(KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes1)).withFixedId(101)) 1816 .addEntry( 1817 KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes2)) 1818 .withFixedId(102) 1819 .makePrimary()) 1820 .build(); 1821 KeysetHandle keysetHandle2 = 1822 KeysetHandle.newBuilder() 1823 .addEntry( 1824 KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes1)) 1825 .withFixedId(101) 1826 .makePrimary()) 1827 .addEntry(KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes2)).withFixedId(102)) 1828 .build(); 1829 1830 assertFalse(keysetHandle1.equalsKeyset(keysetHandle2)); 1831 } 1832 1833 @Test keysetEquality_twoKeysDifferentOrder_returnsFalse()1834 public void keysetEquality_twoKeysDifferentOrder_returnsFalse() throws Exception { 1835 SecretBytes bytes1 = SecretBytes.randomBytes(32); 1836 SecretBytes bytes2 = SecretBytes.randomBytes(32); 1837 1838 KeysetHandle keysetHandle1 = 1839 KeysetHandle.newBuilder() 1840 .addEntry( 1841 KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes1)) 1842 .withFixedId(101) 1843 .makePrimary()) 1844 .addEntry(KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes2)).withFixedId(102)) 1845 .build(); 1846 KeysetHandle keysetHandle2 = 1847 KeysetHandle.newBuilder() 1848 .addEntry(KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes2)).withFixedId(102)) 1849 .addEntry( 1850 KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes1)) 1851 .withFixedId(101) 1852 .makePrimary()) 1853 .build(); 1854 1855 assertFalse(keysetHandle1.equalsKeyset(keysetHandle2)); 1856 } 1857 1858 @Test keysetEquality_twoKeysDifferentStatuses_returnsFalse()1859 public void keysetEquality_twoKeysDifferentStatuses_returnsFalse() throws Exception { 1860 SecretBytes bytes1 = SecretBytes.randomBytes(32); 1861 SecretBytes bytes2 = SecretBytes.randomBytes(32); 1862 1863 KeysetHandle keysetHandle1 = 1864 KeysetHandle.newBuilder() 1865 .addEntry( 1866 KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes1)) 1867 .withFixedId(101) 1868 .makePrimary()) 1869 .addEntry( 1870 KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes2)) 1871 .withFixedId(102) 1872 .setStatus(KeyStatus.DISABLED)) 1873 .build(); 1874 KeysetHandle keysetHandle2 = 1875 KeysetHandle.newBuilder() 1876 .addEntry( 1877 KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes1)) 1878 .withFixedId(101) 1879 .makePrimary()) 1880 .addEntry(KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes2)).withFixedId(102)) 1881 .build(); 1882 1883 assertFalse(keysetHandle1.equalsKeyset(keysetHandle2)); 1884 } 1885 1886 @Test keysetEquality_twoKeysDifferentSizes_returnsFalse()1887 public void keysetEquality_twoKeysDifferentSizes_returnsFalse() throws Exception { 1888 SecretBytes bytes1 = SecretBytes.randomBytes(32); 1889 SecretBytes bytes2 = SecretBytes.randomBytes(32); 1890 1891 KeysetHandle keysetHandle1 = 1892 KeysetHandle.newBuilder() 1893 .addEntry( 1894 KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes1)) 1895 .withFixedId(101) 1896 .makePrimary()) 1897 .addEntry(KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes2)).withFixedId(102)) 1898 .build(); 1899 KeysetHandle keysetHandle2 = 1900 KeysetHandle.newBuilder() 1901 .addEntry( 1902 KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes1)) 1903 .withFixedId(101) 1904 .makePrimary()) 1905 .build(); 1906 1907 assertFalse(keysetHandle1.equalsKeyset(keysetHandle2)); 1908 } 1909 1910 @Test keysetEquality_unparseableStatus_returnsFalse()1911 public void keysetEquality_unparseableStatus_returnsFalse() throws Exception { 1912 Keyset.Key key1 = 1913 TestUtil.createKey( 1914 TestUtil.createHmacKeyData("01234567890123456".getBytes(UTF_8), 16), 1915 42, 1916 KeyStatusType.UNKNOWN_STATUS, 1917 OutputPrefixType.TINK); 1918 KeysetHandle badKeyset = KeysetHandle.fromKeyset(TestUtil.createKeyset(key1)); 1919 assertFalse(badKeyset.equalsKeyset(badKeyset)); 1920 } 1921 1922 @Test keysetEquality_noPrimary_returnsFalse()1923 public void keysetEquality_noPrimary_returnsFalse() throws Exception { 1924 Keyset.Key key1 = 1925 TestUtil.createKey( 1926 TestUtil.createHmacKeyData("01234567890123456".getBytes(UTF_8), 16), 1927 42, 1928 KeyStatusType.ENABLED, 1929 OutputPrefixType.TINK); 1930 Keyset keyset = TestUtil.createKeyset(key1); 1931 KeysetHandle badKeyset = 1932 KeysetHandle.fromKeyset(Keyset.newBuilder(keyset).setPrimaryKeyId(77).build()); 1933 assertFalse(badKeyset.equalsKeyset(badKeyset)); 1934 } 1935 1936 @Test keysetEquality_monitoringAnnotationIgnored_returnsTrue()1937 public void keysetEquality_monitoringAnnotationIgnored_returnsTrue() throws Exception { 1938 SecretBytes bytes = SecretBytes.randomBytes(32); 1939 1940 KeysetHandle keysetHandle1 = 1941 KeysetHandle.newBuilder() 1942 .addEntry( 1943 KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes)) 1944 .withFixedId(101) 1945 .makePrimary()) 1946 .setMonitoringAnnotations(MonitoringAnnotations.newBuilder().add("k1", "v1").build()) 1947 .build(); 1948 KeysetHandle keysetHandle2 = 1949 KeysetHandle.newBuilder() 1950 .addEntry( 1951 KeysetHandle.importKey(XChaCha20Poly1305Key.create(bytes)) 1952 .withFixedId(101) 1953 .makePrimary()) 1954 .setMonitoringAnnotations(MonitoringAnnotations.newBuilder().add("k2", "v2").build()) 1955 .build(); 1956 1957 assertTrue(keysetHandle1.equalsKeyset(keysetHandle2)); 1958 } 1959 } 1960