blob: 641371fe3522f6d0b9eecd37186240ed535df504 [file] [log] [blame]
// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package com.google.crypto.tink;
import static com.google.common.truth.Truth.assertThat;
import static com.google.crypto.tink.TestUtil.assertExceptionContains;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.fail;
import com.google.crypto.tink.TestUtil.DummyAead;
import com.google.crypto.tink.aead.AeadConfig;
import com.google.crypto.tink.aead.AeadKeyTemplates;
import com.google.crypto.tink.config.TinkConfig;
import com.google.crypto.tink.mac.MacConfig;
import com.google.crypto.tink.mac.MacKeyTemplates;
import com.google.crypto.tink.proto.AesEaxKey;
import com.google.crypto.tink.proto.AesGcmKey;
import com.google.crypto.tink.proto.AesGcmKeyFormat;
import com.google.crypto.tink.proto.Ed25519PrivateKey;
import com.google.crypto.tink.proto.Ed25519PublicKey;
import com.google.crypto.tink.proto.HashType;
import com.google.crypto.tink.proto.HmacKey;
import com.google.crypto.tink.proto.KeyData;
import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
import com.google.crypto.tink.proto.KeyStatusType;
import com.google.crypto.tink.proto.KeyTemplate;
import com.google.crypto.tink.proto.Keyset;
import com.google.crypto.tink.proto.OutputPrefixType;
import com.google.crypto.tink.signature.SignatureKeyTemplates;
import com.google.crypto.tink.subtle.AesEaxJce;
import com.google.crypto.tink.subtle.AesGcmJce;
import com.google.crypto.tink.subtle.EncryptThenAuthenticate;
import com.google.crypto.tink.subtle.MacJce;
import com.google.crypto.tink.subtle.Random;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.MessageLite;
import java.security.GeneralSecurityException;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Tests for Registry. */
@RunWith(JUnit4.class)
public class RegistryTest {
private static class CustomAeadKeyManager implements KeyManager<Aead> {
public CustomAeadKeyManager(String typeUrl) {
this.typeUrl = typeUrl;
}
private final String typeUrl;
@Override
public Aead getPrimitive(ByteString proto) throws GeneralSecurityException {
return new DummyAead();
}
@Override
public Aead getPrimitive(MessageLite proto) throws GeneralSecurityException {
return new DummyAead();
}
@Override
public MessageLite newKey(ByteString template) throws GeneralSecurityException {
throw new GeneralSecurityException("Not Implemented");
}
@Override
public MessageLite newKey(MessageLite template) throws GeneralSecurityException {
throw new GeneralSecurityException("Not Implemented");
}
@Override
public KeyData newKeyData(ByteString serialized) throws GeneralSecurityException {
throw new GeneralSecurityException("Not Implemented");
}
@Override
public boolean doesSupport(String typeUrl) {
return typeUrl.equals(this.typeUrl);
}
@Override
public String getKeyType() {
return this.typeUrl;
}
@Override
public int getVersion() {
return 0;
}
@Override
public Class<Aead> getPrimitiveClass() {
return Aead.class;
}
}
@Before
public void setUp() throws GeneralSecurityException {
Registry.reset();
TinkConfig.register();
}
private void testGetKeyManager_shouldWork(String typeUrl, String className) throws Exception {
assertThat(Registry.getKeyManager(typeUrl).getClass().toString()).contains(className);
}
@Test
public void testGetKeyManager_legacy_shouldWork() throws Exception {
testGetKeyManager_shouldWork(AeadConfig.AES_CTR_HMAC_AEAD_TYPE_URL, "KeyManagerImpl");
testGetKeyManager_shouldWork(AeadConfig.AES_EAX_TYPE_URL, "KeyManagerImpl");
testGetKeyManager_shouldWork(MacConfig.HMAC_TYPE_URL, "KeyManagerImpl");
}
@Test
public void testGetKeyManager_shouldWorkAesEax() throws Exception {
assertThat(
Registry.getKeyManager(AeadConfig.AES_EAX_TYPE_URL, Aead.class).getClass().toString())
.contains("KeyManagerImpl");
}
@Test
public void testGetKeyManager_shouldWorkHmac() throws Exception {
assertThat(Registry.getKeyManager(MacConfig.HMAC_TYPE_URL, Mac.class).getClass().toString())
.contains("KeyManagerImpl");
}
@Test
public void testGetKeyManager_legacy_wrongType_shouldThrowException() throws Exception {
KeyManager<Aead> wrongType = Registry.getKeyManager(MacConfig.HMAC_TYPE_URL);
KeyTemplate template = MacKeyTemplates.HMAC_SHA256_128BITTAG;
HmacKey hmacKey = (HmacKey) Registry.newKey(template);
try {
Aead unused = wrongType.getPrimitive(hmacKey);
fail("Expected ClassCastException");
} catch (ClassCastException e) {
assertExceptionContains(e, "MacJce cannot be cast to com.google.crypto.tink.Aead");
}
}
@Test
public void testGetKeyManager_wrongType_shouldThrowException() throws Exception {
try {
Registry.getKeyManager(MacConfig.HMAC_TYPE_URL, Aead.class);
fail("Expected GeneralSecurityException");
} catch (GeneralSecurityException e) {
assertExceptionContains(e, "com.google.crypto.tink.Mac");
assertExceptionContains(e, "com.google.crypto.tink.Aead not supported");
}
}
@Test
public void testGetKeyManager_legacy_badTypeUrl_shouldThrowException() throws Exception {
String badTypeUrl = "bad type URL";
try {
Registry.getKeyManager(badTypeUrl);
fail("Expected GeneralSecurityException.");
} catch (GeneralSecurityException e) {
assertExceptionContains(e, "No key manager found");
assertExceptionContains(e, badTypeUrl);
}
}
@Test
public void testGetKeyManager_badTypeUrl_shouldThrowException() throws Exception {
String badTypeUrl = "bad type URL";
try {
Registry.getKeyManager(badTypeUrl, Aead.class);
fail("Expected GeneralSecurityException.");
} catch (GeneralSecurityException e) {
assertExceptionContains(e, "No key manager found");
assertExceptionContains(e, badTypeUrl);
}
}
@Test
public void testGetUntypedKeyManager_shouldWorkHmac() throws Exception {
assertThat(Registry.getUntypedKeyManager(MacConfig.HMAC_TYPE_URL).getClass().toString())
.contains("KeyManagerImpl");
}
@Test
public void testRegisterKeyManager_keyManagerIsNull_shouldThrowException() throws Exception {
try {
Registry.registerKeyManager(null);
fail("Expected IllegalArgumentException.");
} catch (IllegalArgumentException e) {
assertThat(e.toString()).contains("must be non-null");
}
}
@Test
public void testRegisterKeyManager_MoreRestrictedNewKeyAllowed_shouldWork() throws Exception {
String typeUrl = "someTypeUrl";
Registry.registerKeyManager(new CustomAeadKeyManager(typeUrl));
Registry.registerKeyManager(new CustomAeadKeyManager(typeUrl), false);
}
@Test
public void testRegisterKeyManager_SameNewKeyAllowed_shouldWork() throws Exception {
String typeUrl = "someOtherTypeUrl";
Registry.registerKeyManager(new CustomAeadKeyManager(typeUrl));
Registry.registerKeyManager(new CustomAeadKeyManager(typeUrl), true);
}
@Test
public void testRegisterKeyManager_LessRestrictedNewKeyAllowed_shouldThrowException()
throws Exception {
String typeUrl = "yetAnotherTypeUrl";
Registry.registerKeyManager(new CustomAeadKeyManager(typeUrl), false);
try {
Registry.registerKeyManager(new CustomAeadKeyManager(typeUrl), true);
fail("Expected GeneralSecurityException");
} catch (GeneralSecurityException e) {
// expected
}
}
@Test
public void testRegisterKeyManager_keyManagerFromAnotherClass_shouldThrowException()
throws Exception {
// This should not overwrite the existing manager.
try {
Registry.registerKeyManager(new CustomAeadKeyManager(AeadConfig.AES_CTR_HMAC_AEAD_TYPE_URL));
fail("Expected GeneralSecurityException.");
} catch (GeneralSecurityException e) {
assertThat(e.toString()).contains("already registered");
}
KeyManager<Aead> manager = Registry.getKeyManager(AeadConfig.AES_CTR_HMAC_AEAD_TYPE_URL);
assertThat(manager.getClass().toString()).contains("KeyManagerImpl");
}
@Test
public void testRegisterKeyManager_deprecated_keyManagerIsNull_shouldThrowException()
throws Exception {
try {
Registry.registerKeyManager(AeadConfig.AES_CTR_HMAC_AEAD_TYPE_URL, null);
fail("Expected IllegalArgumentException.");
} catch (IllegalArgumentException e) {
assertThat(e.toString()).contains("must be non-null");
}
}
@Test
public void testRegisterKeyManager_deprecated_WithKeyTypeNotSupported_shouldThrowException()
throws Exception {
String typeUrl = "yetSomeOtherTypeUrl";
String differentTypeUrl = "differentTypeUrl";
try {
Registry.registerKeyManager(differentTypeUrl, new CustomAeadKeyManager(typeUrl));
fail("Should throw an exception.");
} catch (GeneralSecurityException e) {
assertExceptionContains(e,
"Manager does not support key type " + differentTypeUrl);
}
}
@Test
public void testRegisterKeyManager_deprecated_MoreRestrictedNewKeyAllowed_shouldWork()
throws Exception {
String typeUrl = "typeUrl";
Registry.registerKeyManager(typeUrl, new CustomAeadKeyManager(typeUrl));
try {
Registry.registerKeyManager(typeUrl, new CustomAeadKeyManager(typeUrl), false);
} catch (GeneralSecurityException e) {
fail("repeated registrations of the same key manager should work");
}
}
@Test
public void testRegisterKeyManager_deprecated_LessRestrictedNewKeyAllowed_shouldThrowException()
throws Exception {
String typeUrl = "totallyDifferentTypeUrl";
Registry.registerKeyManager(typeUrl, new CustomAeadKeyManager(typeUrl), false);
try {
Registry.registerKeyManager(typeUrl, new CustomAeadKeyManager(typeUrl), true);
fail("Expected GeneralSecurityException");
} catch (GeneralSecurityException e) {
// expected
}
}
@Test
public void testRegisterKeyManager_deprecated_keyManagerFromAnotherClass_shouldThrowException()
throws Exception {
// This should not overwrite the existing manager.
try {
Registry.registerKeyManager(AeadConfig.AES_CTR_HMAC_AEAD_TYPE_URL,
new CustomAeadKeyManager(AeadConfig.AES_CTR_HMAC_AEAD_TYPE_URL));
fail("Expected GeneralSecurityException.");
} catch (GeneralSecurityException e) {
assertThat(e.toString()).contains("already registered");
}
KeyManager<Aead> manager = Registry.getKeyManager(AeadConfig.AES_CTR_HMAC_AEAD_TYPE_URL);
assertThat(manager.getClass().toString()).contains("KeyManagerImpl");
}
@Test
public void testGetPublicKeyData_shouldWork() throws Exception {
KeyData privateKeyData = Registry.newKeyData(SignatureKeyTemplates.ECDSA_P256);
KeyData publicKeyData = Registry.getPublicKeyData(privateKeyData.getTypeUrl(),
privateKeyData.getValue());
PublicKeyVerify verifier = Registry.<PublicKeyVerify>getPrimitive(publicKeyData);
PublicKeySign signer = Registry.<PublicKeySign>getPrimitive(privateKeyData);
byte[] message = "Nice test message".getBytes(UTF_8);
verifier.verify(signer.sign(message), message);
}
@Test
public void testGetPublicKeyData_shouldThrow() throws Exception {
KeyData keyData = Registry.newKeyData(MacKeyTemplates.HMAC_SHA256_128BITTAG);
try {
Registry.getPublicKeyData(keyData.getTypeUrl(), keyData.getValue());
fail("Expected GeneralSecurityException.");
} catch (GeneralSecurityException e) {
assertThat(e.toString()).contains("not a PrivateKeyManager");
}
}
@Test
public void testGetPrimitive_legacy_AesGcm_shouldWork() throws Exception {
KeyTemplate template = AeadKeyTemplates.AES128_EAX;
AesEaxKey aesEaxKey = (AesEaxKey) Registry.newKey(template);
KeyData aesEaxKeyData = Registry.newKeyData(template);
Aead aead = Registry.getPrimitive(aesEaxKeyData);
assertThat(aesEaxKey.getKeyValue().size()).isEqualTo(16);
assertThat(aesEaxKeyData.getTypeUrl()).isEqualTo(AeadConfig.AES_EAX_TYPE_URL);
// This might break when we add native implementations.
assertThat(aead.getClass()).isEqualTo(AesEaxJce.class);
}
@Test
public void testGetPrimitive_AesGcm_shouldWork() throws Exception {
KeyTemplate template = AeadKeyTemplates.AES128_EAX;
AesEaxKey aesEaxKey = (AesEaxKey) Registry.newKey(template);
KeyData aesEaxKeyData = Registry.newKeyData(template);
Aead aead = Registry.getPrimitive(aesEaxKeyData, Aead.class);
assertThat(aesEaxKey.getKeyValue().size()).isEqualTo(16);
assertThat(aesEaxKeyData.getTypeUrl()).isEqualTo(AeadConfig.AES_EAX_TYPE_URL);
// This might break when we add native implementations.
assertThat(aead.getClass()).isEqualTo(AesEaxJce.class);
}
@Test
public void testGetPrimitive_legacy_Hmac_shouldWork() throws Exception {
KeyTemplate template = MacKeyTemplates.HMAC_SHA256_128BITTAG;
HmacKey hmacKey = (HmacKey) Registry.newKey(template);
KeyData hmacKeyData = Registry.newKeyData(template);
Mac mac = Registry.getPrimitive(hmacKeyData);
assertThat(hmacKey.getKeyValue().size()).isEqualTo(32);
assertThat(hmacKey.getParams().getTagSize()).isEqualTo(16);
assertThat(hmacKey.getParams().getHash()).isEqualTo(HashType.SHA256);
assertThat(hmacKeyData.getTypeUrl()).isEqualTo(MacConfig.HMAC_TYPE_URL);
// This might break when we add native implementations.
assertThat(mac.getClass()).isEqualTo(MacJce.class);
}
@Test
public void testGetPrimitive_Hmac_shouldWork() throws Exception {
KeyTemplate template = MacKeyTemplates.HMAC_SHA256_128BITTAG;
HmacKey hmacKey = (HmacKey) Registry.newKey(template);
KeyData hmacKeyData = Registry.newKeyData(template);
Mac mac = Registry.getPrimitive(hmacKeyData, Mac.class);
assertThat(hmacKey.getKeyValue().size()).isEqualTo(32);
assertThat(hmacKey.getParams().getTagSize()).isEqualTo(16);
assertThat(hmacKey.getParams().getHash()).isEqualTo(HashType.SHA256);
assertThat(hmacKeyData.getTypeUrl()).isEqualTo(MacConfig.HMAC_TYPE_URL);
// This might break when we add native implementations.
assertThat(mac.getClass()).isEqualTo(MacJce.class);
}
@Test
public void testGetPrimitives_legacy_shouldWork() throws Exception {
// Create a keyset, and get a PrimitiveSet.
KeyTemplate template1 = AeadKeyTemplates.AES128_EAX;
KeyTemplate template2 = AeadKeyTemplates.AES128_CTR_HMAC_SHA256;
KeyData key1 = Registry.newKeyData(template1);
KeyData key2 = Registry.newKeyData(template1);
KeyData key3 = Registry.newKeyData(template2);
KeysetHandle keysetHandle =
KeysetHandle.fromKeyset(
Keyset.newBuilder()
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key1)
.setKeyId(1)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key2)
.setKeyId(2)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key3)
.setKeyId(3)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.setPrimaryKeyId(2)
.build());
PrimitiveSet<Aead> aeadSet = Registry.getPrimitives(keysetHandle, Aead.class);
assertThat(aeadSet.getPrimary().getPrimitive().getClass()).isEqualTo(AesEaxJce.class);
}
@Test
public void testGetPrimitives_shouldWork() throws Exception {
// Create a keyset, and get a PrimitiveSet.
KeyTemplate template1 = AeadKeyTemplates.AES128_EAX;
KeyTemplate template2 = AeadKeyTemplates.AES128_CTR_HMAC_SHA256;
KeyData key1 = Registry.newKeyData(template1);
KeyData key2 = Registry.newKeyData(template1);
KeyData key3 = Registry.newKeyData(template2);
KeysetHandle keysetHandle =
KeysetHandle.fromKeyset(
Keyset.newBuilder()
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key1)
.setKeyId(1)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key2)
.setKeyId(2)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key3)
.setKeyId(3)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.setPrimaryKeyId(2)
.build());
PrimitiveSet<Aead> aeadSet = Registry.getPrimitives(keysetHandle, Aead.class);
assertThat(aeadSet.getPrimary().getPrimitive().getClass()).isEqualTo(AesEaxJce.class);
}
@Test
public void testGetPrimitives_WithSomeNonEnabledKeys_shouldWork() throws Exception {
// Try a keyset with some keys non-ENABLED.
KeyTemplate template1 = AeadKeyTemplates.AES128_EAX;
KeyTemplate template2 = AeadKeyTemplates.AES128_CTR_HMAC_SHA256;
KeyData key1 = Registry.newKeyData(template1);
KeyData key2 = Registry.newKeyData(template1);
KeyData key3 = Registry.newKeyData(template2);
KeysetHandle keysetHandle =
KeysetHandle.fromKeyset(
Keyset.newBuilder()
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key1)
.setKeyId(1)
.setStatus(KeyStatusType.DESTROYED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key2)
.setKeyId(2)
.setStatus(KeyStatusType.DISABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key3)
.setKeyId(3)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.setPrimaryKeyId(3)
.build());
PrimitiveSet<Aead> aeadSet = Registry.getPrimitives(keysetHandle, Aead.class);
assertThat(aeadSet.getPrimary().getPrimitive().getClass())
.isEqualTo(EncryptThenAuthenticate.class);
}
@Test
public void testGetPrimitives_legacy_CustomManager_shouldWork() throws Exception {
// Create a keyset.
KeyTemplate template1 = AeadKeyTemplates.AES128_EAX;
KeyTemplate template2 = AeadKeyTemplates.AES128_CTR_HMAC_SHA256;
KeyData key1 = Registry.newKeyData(template1);
KeyData key2 = Registry.newKeyData(template2);
KeysetHandle keysetHandle =
KeysetHandle.fromKeyset(
Keyset.newBuilder()
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key1)
.setKeyId(1)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key2)
.setKeyId(2)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.setPrimaryKeyId(2)
.build());
// Get a PrimitiveSet using a custom key manager for key1.
KeyManager<Aead> customManager = new CustomAeadKeyManager(AeadConfig.AES_EAX_TYPE_URL);
PrimitiveSet<Aead> aeadSet = Registry.getPrimitives(keysetHandle, customManager);
List<PrimitiveSet.Entry<Aead>> aead1List =
aeadSet.getPrimitive(keysetHandle.getKeyset().getKey(0));
List<PrimitiveSet.Entry<Aead>> aead2List =
aeadSet.getPrimitive(keysetHandle.getKeyset().getKey(1));
assertThat(aead1List).hasSize(1);
assertThat(aead1List.get(0).getPrimitive().getClass()).isEqualTo(DummyAead.class);
assertThat(aead2List).hasSize(1);
assertThat(aead2List.get(0).getPrimitive().getClass()).isEqualTo(EncryptThenAuthenticate.class);
}
@Test
public void testGetPrimitives_CustomManager_shouldWork() throws Exception {
// Create a keyset.
KeyTemplate template1 = AeadKeyTemplates.AES128_EAX;
KeyTemplate template2 = AeadKeyTemplates.AES128_CTR_HMAC_SHA256;
KeyData key1 = Registry.newKeyData(template1);
KeyData key2 = Registry.newKeyData(template2);
KeysetHandle keysetHandle =
KeysetHandle.fromKeyset(
Keyset.newBuilder()
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key1)
.setKeyId(1)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key2)
.setKeyId(2)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.setPrimaryKeyId(2)
.build());
// Get a PrimitiveSet using a custom key manager for key1.
KeyManager<Aead> customManager = new CustomAeadKeyManager(AeadConfig.AES_EAX_TYPE_URL);
PrimitiveSet<Aead> aeadSet = Registry.getPrimitives(keysetHandle, customManager, Aead.class);
List<PrimitiveSet.Entry<Aead>> aead1List =
aeadSet.getPrimitive(keysetHandle.getKeyset().getKey(0));
List<PrimitiveSet.Entry<Aead>> aead2List =
aeadSet.getPrimitive(keysetHandle.getKeyset().getKey(1));
assertThat(aead1List.size()).isEqualTo(1);
assertThat(aead1List.get(0).getPrimitive().getClass()).isEqualTo(DummyAead.class);
assertThat(aead2List.size()).isEqualTo(1);
assertThat(aead2List.get(0).getPrimitive().getClass()).isEqualTo(EncryptThenAuthenticate.class);
}
@Test
public void testGetPrimitives_EmptyKeyset_shouldThrowException() throws Exception {
// Empty keyset.
try {
Registry.getPrimitives(KeysetHandle.fromKeyset(Keyset.getDefaultInstance()), Aead.class);
fail("Invalid keyset. Expect GeneralSecurityException");
} catch (GeneralSecurityException e) {
assertExceptionContains(e, "empty keyset");
}
}
@Test
public void testGetPrimitives_KeysetWithNoPrimaryKey_shouldThrowException() throws Exception {
// Create a keyset without a primary key.
KeyData key1 = Registry.newKeyData(MacKeyTemplates.HMAC_SHA256_128BITTAG);
KeysetHandle keysetHandle =
KeysetHandle.fromKeyset(
Keyset.newBuilder()
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key1)
.setKeyId(1)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.build());
// No primary key.
try {
Registry.getPrimitives(keysetHandle, Aead.class);
fail("Invalid keyset. Expect GeneralSecurityException");
} catch (GeneralSecurityException e) {
assertExceptionContains(e, "keyset doesn't contain a valid primary key");
}
}
@Test
public void testGetPrimitives_KeysetWithDisabledPrimaryKey_shouldThrowException()
throws Exception {
// Create a keyset with a disabled primary key.
KeyData key1 = Registry.newKeyData(MacKeyTemplates.HMAC_SHA256_128BITTAG);
KeysetHandle keysetHandle =
KeysetHandle.fromKeyset(
Keyset.newBuilder()
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key1)
.setKeyId(1)
.setStatus(KeyStatusType.DISABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key1)
.setKeyId(2)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.setPrimaryKeyId(1)
.build());
try {
Registry.getPrimitives(keysetHandle, Mac.class);
fail("Invalid keyset. Expect GeneralSecurityException");
} catch (GeneralSecurityException e) {
assertExceptionContains(e, "keyset doesn't contain a valid primary key");
}
}
@Test
public void testGetPrimitives_KeysetWithMultiplePrimaryKeys_shouldThrowException()
throws Exception {
// Multiple primary keys.
KeyData key1 = Registry.newKeyData(MacKeyTemplates.HMAC_SHA256_128BITTAG);
KeysetHandle keysetHandle =
KeysetHandle.fromKeyset(
Keyset.newBuilder()
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key1)
.setKeyId(1)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key1)
.setKeyId(1)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.setPrimaryKeyId(1)
.build());
try {
Registry.getPrimitives(keysetHandle, Mac.class);
fail("Invalid keyset. Expect GeneralSecurityException");
} catch (GeneralSecurityException e) {
assertExceptionContains(e, "keyset contains multiple primary keys");
}
}
@Test
public void testGetPrimitives_KeysetWithKeyForWrongPrimitive_shouldThrowException()
throws Exception {
KeyData key1 = Registry.newKeyData(AeadKeyTemplates.AES128_EAX);
// This MAC key should cause an exception.
KeyData key2 = Registry.newKeyData(MacKeyTemplates.HMAC_SHA256_128BITTAG);
KeyData key3 = Registry.newKeyData(AeadKeyTemplates.AES128_EAX);
KeysetHandle keysetHandle =
KeysetHandle.fromKeyset(
Keyset.newBuilder()
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key1)
.setKeyId(1)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key2)
.setKeyId(2)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key3)
.setKeyId(3)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.setPrimaryKeyId(3)
.build());
try {
Registry.getPrimitives(keysetHandle, Aead.class);
fail("Non Aead keys. Expected GeneralSecurityException");
} catch (GeneralSecurityException e) {
assertExceptionContains(e, "com.google.crypto.tink.Mac");
assertExceptionContains(e, "com.google.crypto.tink.Aead not supported");
}
}
/** Implementation of a KeyTypeManager for testing. */
private static class TestKeyTypeManager extends KeyTypeManager<AesGcmKey> {
public TestKeyTypeManager() {
super(
AesGcmKey.class,
new PrimitiveFactory<Aead, AesGcmKey>(Aead.class) {
@Override
public Aead getPrimitive(AesGcmKey key) throws GeneralSecurityException {
return new AesGcmJce(key.getKeyValue().toByteArray());
}
},
new PrimitiveFactory<FakeAead, AesGcmKey>(FakeAead.class) {
@Override
public FakeAead getPrimitive(AesGcmKey key) {
return new FakeAead();
}
});
}
@Override
public String getKeyType() {
return "type.googleapis.com/google.crypto.tink.AesGcmKey";
}
@Override
public int getVersion() {
return 1;
}
@Override
public KeyMaterialType keyMaterialType() {
return KeyMaterialType.SYMMETRIC;
}
@Override
public void validateKey(AesGcmKey keyProto) throws GeneralSecurityException {
// Throw by hand so we can verify the exception comes from here.
if (keyProto.getKeyValue().size() != 16) {
throw new GeneralSecurityException("validateKey(AesGcmKey) failed");
}
}
@Override
public AesGcmKey parseKey(ByteString byteString) throws InvalidProtocolBufferException {
return AesGcmKey.parseFrom(byteString);
}
@Override
public KeyFactory<AesGcmKeyFormat, AesGcmKey> keyFactory() {
return new KeyFactory<AesGcmKeyFormat, AesGcmKey>(AesGcmKeyFormat.class) {
@Override
public void validateKeyFormat(AesGcmKeyFormat format) throws GeneralSecurityException {
// Throw by hand so we can verify the exception comes from here.
if (format.getKeySize() != 16) {
throw new GeneralSecurityException("validateKeyFormat(AesGcmKeyFormat) failed");
}
}
@Override
public AesGcmKeyFormat parseKeyFormat(ByteString byteString)
throws InvalidProtocolBufferException {
return AesGcmKeyFormat.parseFrom(byteString);
}
@Override
public AesGcmKey createKey(AesGcmKeyFormat format) throws GeneralSecurityException {
return AesGcmKey.newBuilder()
.setKeyValue(ByteString.copyFrom(Random.randBytes(format.getKeySize())))
.setVersion(getVersion())
.build();
}
};
}
}
@Test
public void testRegisterKeyTypeManager() throws Exception {
Registry.reset();
Registry.registerKeyManager(new TestKeyTypeManager(), true);
}
@Test
public void testRegisterKeyTypeManager_getKeyManagerAead_works() throws Exception {
Registry.reset();
TestKeyTypeManager testKeyTypeManager = new TestKeyTypeManager();
Registry.registerKeyManager(testKeyTypeManager, true);
KeyManager<Aead> km = Registry.getKeyManager(testKeyTypeManager.getKeyType(), Aead.class);
assertThat(km.getKeyType()).isEqualTo(testKeyTypeManager.getKeyType());
}
@Test
public void testRegisterKeyTypeManager_getKeyManagerFakeAead_works() throws Exception {
Registry.reset();
TestKeyTypeManager testKeyTypeManager = new TestKeyTypeManager();
Registry.registerKeyManager(testKeyTypeManager, true);
KeyManager<FakeAead> km =
Registry.getKeyManager(testKeyTypeManager.getKeyType(), FakeAead.class);
assertThat(km.getKeyType()).isEqualTo(testKeyTypeManager.getKeyType());
}
@Test
public void testRegisterKeyTypeManager_getKeyManagerMac_throws() throws Exception {
Registry.reset();
TestKeyTypeManager testKeyTypeManager = new TestKeyTypeManager();
Registry.registerKeyManager(testKeyTypeManager, true);
try {
Registry.getKeyManager(testKeyTypeManager.getKeyType(), Mac.class);
fail();
} catch (GeneralSecurityException e) {
assertExceptionContains(e, "com.google.crypto.tink.Mac");
assertExceptionContains(e, "com.google.crypto.tink.Aead");
assertExceptionContains(e, "com.google.crypto.tink.RegistryTest.FakeAead");
}
}
// Checks that calling getUntypedKeyManager will return the keymanager for the *first* implemented
// class in the constructor.
@Test
public void testRegisterKeyTypeManager_getUntypedKeyManager_returnsAead() throws Exception {
Registry.reset();
TestKeyTypeManager testKeyTypeManager = new TestKeyTypeManager();
Registry.registerKeyManager(testKeyTypeManager, true);
KeyManager<?> km = Registry.getUntypedKeyManager(testKeyTypeManager.getKeyType());
assertThat(km.getPrimitiveClass()).isEqualTo(Aead.class);
}
@Test
public void testRegisterKeyTypeManager_MoreRestrictedNewKeyAllowed_shouldWork() throws Exception {
Registry.reset();
Registry.registerKeyManager(new TestKeyTypeManager(), true);
Registry.registerKeyManager(new TestKeyTypeManager(), false);
}
@Test
public void testRegisterKeyTypeManager_SameNewKeyAllowed_shouldWork() throws Exception {
Registry.reset();
Registry.registerKeyManager(new TestKeyTypeManager(), true);
Registry.registerKeyManager(new TestKeyTypeManager(), true);
Registry.registerKeyManager(new TestKeyTypeManager(), false);
Registry.registerKeyManager(new TestKeyTypeManager(), false);
}
@Test
public void testRegisterKeyTypeManager_LessRestrictedNewKeyAllowed_throws() throws Exception {
Registry.reset();
Registry.registerKeyManager(new TestKeyTypeManager(), false);
try {
Registry.registerKeyManager(new TestKeyTypeManager(), true);
fail("Expected GeneralSecurityException");
} catch (GeneralSecurityException e) {
// expected
}
}
@Test
public void testRegisterKeyTypeManager_DifferentClass_throws() throws Exception {
Registry.reset();
Registry.registerKeyManager(new TestKeyTypeManager(), true);
try {
// Note: due to the {} this is a subclass of TestKeyTypeManager.
Registry.registerKeyManager(new TestKeyTypeManager() {}, true);
fail("Expected GeneralSecurityException");
} catch (GeneralSecurityException e) {
// expected
}
}
@Test
public void testRegisterKeyTypeManager_AfterKeyManager_throws() throws Exception {
Registry.reset();
Registry.registerKeyManager(new CustomAeadKeyManager(new TestKeyTypeManager().getKeyType()));
try {
Registry.registerKeyManager(new TestKeyTypeManager(), true);
fail("Expected GeneralSecurityException");
} catch (GeneralSecurityException e) {
// expected
}
}
@Test
public void testRegisterKeyTypeManager_BeforeKeyManager_throws() throws Exception {
Registry.reset();
Registry.registerKeyManager(new TestKeyTypeManager(), true);
try {
Registry.registerKeyManager(new CustomAeadKeyManager(new TestKeyTypeManager().getKeyType()));
fail("Expected GeneralSecurityException");
} catch (GeneralSecurityException e) {
// expected
}
}
private static class PublicPrimitiveA {}
private static class PublicPrimitiveB {}
private static class TestPublicKeyTypeManager extends KeyTypeManager<Ed25519PublicKey> {
public TestPublicKeyTypeManager() {
super(
Ed25519PublicKey.class,
new PrimitiveFactory<PublicPrimitiveA, Ed25519PublicKey>(PublicPrimitiveA.class) {
@Override
public PublicPrimitiveA getPrimitive(Ed25519PublicKey key) {
return new PublicPrimitiveA();
}
},
new PrimitiveFactory<PublicPrimitiveB, Ed25519PublicKey>(PublicPrimitiveB.class) {
@Override
public PublicPrimitiveB getPrimitive(Ed25519PublicKey key) {
return new PublicPrimitiveB();
}
});
}
@Override
public String getKeyType() {
return "type.googleapis.com/google.crypto.tink.Ed25519PublicKey";
}
@Override
public int getVersion() {
return 1;
}
@Override
public KeyMaterialType keyMaterialType() {
return KeyMaterialType.ASYMMETRIC_PUBLIC;
}
@Override
public void validateKey(Ed25519PublicKey keyProto) throws GeneralSecurityException {
if (keyProto.getKeyValue().size() != 32) {
throw new GeneralSecurityException("validateKey(Ed25519PublicKey) failed");
}
}
@Override
public Ed25519PublicKey parseKey(ByteString byteString) throws InvalidProtocolBufferException {
return Ed25519PublicKey.parseFrom(byteString);
}
}
private static class PrivatePrimitiveA {}
private static class PrivatePrimitiveB {}
private static class TestPrivateKeyTypeManager
extends PrivateKeyTypeManager<Ed25519PrivateKey, Ed25519PublicKey> {
public TestPrivateKeyTypeManager() {
super(
Ed25519PrivateKey.class,
Ed25519PublicKey.class,
new PrimitiveFactory<PrivatePrimitiveA, Ed25519PrivateKey>(PrivatePrimitiveA.class) {
@Override
public PrivatePrimitiveA getPrimitive(Ed25519PrivateKey key) {
return new PrivatePrimitiveA();
}
},
new PrimitiveFactory<PrivatePrimitiveB, Ed25519PrivateKey>(PrivatePrimitiveB.class) {
@Override
public PrivatePrimitiveB getPrimitive(Ed25519PrivateKey key) {
return new PrivatePrimitiveB();
}
});
}
@Override
public String getKeyType() {
return "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey";
}
@Override
public int getVersion() {
return 1;
}
@Override
public KeyMaterialType keyMaterialType() {
return KeyMaterialType.ASYMMETRIC_PRIVATE;
}
@Override
public void validateKey(Ed25519PrivateKey keyProto) throws GeneralSecurityException {
// Throw by hand so we can verify the exception comes from here.
if (keyProto.getKeyValue().size() != 32) {
throw new GeneralSecurityException("validateKey(Ed25519PrivateKey) failed");
}
}
@Override
public Ed25519PrivateKey parseKey(ByteString byteString) throws InvalidProtocolBufferException {
return Ed25519PrivateKey.parseFrom(byteString);
}
@Override
public Ed25519PublicKey getPublicKey(Ed25519PrivateKey privateKey) {
return privateKey.getPublicKey();
}
}
@Test
public void testRegisterAssymmetricKeyManagers() throws Exception {
Registry.reset();
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
}
@Test
public void testRegisterAssymmetricKeyManagers_getPrivateKeyManagerPrimitiveA_works()
throws Exception {
Registry.reset();
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
KeyManager<PrivatePrimitiveA> km =
Registry.getKeyManager(
new TestPrivateKeyTypeManager().getKeyType(), PrivatePrimitiveA.class);
assertThat(km.getKeyType()).isEqualTo(new TestPrivateKeyTypeManager().getKeyType());
}
@Test
public void testRegisterAssymmetricKeyManagers_getPrivateKeyManagerPrimitiveB_works()
throws Exception {
Registry.reset();
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
KeyManager<PrivatePrimitiveB> km =
Registry.getKeyManager(
new TestPrivateKeyTypeManager().getKeyType(), PrivatePrimitiveB.class);
assertThat(km.getKeyType()).isEqualTo(new TestPrivateKeyTypeManager().getKeyType());
}
@Test
public void testRegisterAssymmetricKeyManagers_getPrivateKeyManagerPublicA_works()
throws Exception {
Registry.reset();
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
KeyManager<PublicPrimitiveA> km =
Registry.getKeyManager(new TestPublicKeyTypeManager().getKeyType(), PublicPrimitiveA.class);
assertThat(km.getKeyType()).isEqualTo(new TestPublicKeyTypeManager().getKeyType());
}
@Test
public void testRegisterAssymmetricKeyManagers_getPrivateKeyManagerPublicB_works()
throws Exception {
Registry.reset();
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
KeyManager<PublicPrimitiveB> km =
Registry.getKeyManager(new TestPublicKeyTypeManager().getKeyType(), PublicPrimitiveB.class);
assertThat(km.getKeyType()).isEqualTo(new TestPublicKeyTypeManager().getKeyType());
}
@Test
public void testRegisterAssymmetricKeyManagers_getPrivateKeyManagerWrongPrimitive_throws()
throws Exception {
Registry.reset();
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
try {
Registry.getKeyManager(new TestPrivateKeyTypeManager().getKeyType(), Mac.class);
fail();
} catch (GeneralSecurityException e) {
assertExceptionContains(e, "com.google.crypto.tink.Mac");
assertExceptionContains(e, "PrivatePrimitiveA");
assertExceptionContains(e, "PrivatePrimitiveB");
}
}
@Test
public void testRegisterAssymmetricKeyManagers_getPublicKeyManagerWrongPrimitive_throws()
throws Exception {
Registry.reset();
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
try {
Registry.getKeyManager(new TestPublicKeyTypeManager().getKeyType(), Mac.class);
fail();
} catch (GeneralSecurityException e) {
assertExceptionContains(e, "com.google.crypto.tink.Mac");
assertExceptionContains(e, "PublicPrimitiveA");
assertExceptionContains(e, "PublicPrimitiveB");
}
}
// Checks that calling getUntypedKeyManager will return the keymanager for the *first* implemented
// class in the constructor.
@Test
public void testRegisterAssymmetricKeyManagers_getUntypedPrivateKeyManager_returnsPrimitiveA()
throws Exception {
Registry.reset();
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
KeyManager<?> km = Registry.getUntypedKeyManager(new TestPrivateKeyTypeManager().getKeyType());
assertThat(km.getPrimitiveClass()).isEqualTo(PrivatePrimitiveA.class);
}
// Checks that calling getUntypedKeyManager will return the keymanager for the *first* implemented
// class in the constructor.
@Test
public void testRegisterAssymmetricKeyManagers_getUntypedPublicKeyManager_returnsPrimitiveA()
throws Exception {
Registry.reset();
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
KeyManager<?> km = Registry.getUntypedKeyManager(new TestPublicKeyTypeManager().getKeyType());
assertThat(km.getPrimitiveClass()).isEqualTo(PublicPrimitiveA.class);
}
@Test
public void testRegisterAssymmetricKeyManagers_MoreRestrictedNewKeyAllowed_shouldWork()
throws Exception {
Registry.reset();
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), false);
}
@Test
public void testRegisterAssymmetricKeyManagers_SameNewKeyAllowed_shouldWork() throws Exception {
Registry.reset();
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), false);
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), false);
}
@Test
public void testRegisterAssymmetricKeyManagers_LessRestrictedNewKeyAllowed_throws()
throws Exception {
Registry.reset();
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), false);
try {
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
fail("Expected GeneralSecurityException");
} catch (GeneralSecurityException e) {
// expected
}
}
@Test
public void testRegisterAssymmetricKeyManagers_PublicKeyManagerCanBeRegisteredAlone()
throws Exception {
Registry.reset();
Registry.registerKeyManager(new TestPublicKeyTypeManager(), false);
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
Registry.registerKeyManager(new TestPublicKeyTypeManager(), false);
}
@Test
public void testRegisterAssymmetricKeyManagers_PublicKeyManagerReRegister_getPublicKeyData()
throws Exception {
Registry.reset();
Registry.registerKeyManager(new TestPublicKeyTypeManager(), false);
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
Registry.registerKeyManager(new TestPublicKeyTypeManager(), false);
// Check that getPublicKeyData works now.
Ed25519PrivateKey privateKey =
Ed25519PrivateKey.newBuilder()
.setKeyValue(ByteString.copyFrom(Random.randBytes(32)))
.setPublicKey(
Ed25519PublicKey.newBuilder()
.setKeyValue(ByteString.copyFrom(Random.randBytes(32))))
.build();
KeyData publicKeyData =
Registry.getPublicKeyData(
new TestPrivateKeyTypeManager().getKeyType(), privateKey.toByteString());
assertThat(publicKeyData.getTypeUrl()).isEqualTo(new TestPublicKeyTypeManager().getKeyType());
Ed25519PublicKey publicKey = Ed25519PublicKey.parseFrom(publicKeyData.getValue());
assertThat(publicKey.getKeyValue()).isEqualTo(privateKey.getPublicKey().getKeyValue());
}
@Test
public void testRegisterAssymmetricKeyManagers_DifferentClassPrivateKey_throws()
throws Exception {
Registry.reset();
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
try {
// Note: due to the {} this is a subclass of TestPrivateKeyTypeManager.
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager() {}, new TestPublicKeyTypeManager(), true);
fail("Expected GeneralSecurityException");
} catch (GeneralSecurityException e) {
// expected
}
}
@Test
public void testRegisterAssymmetricKeyManagers_DifferentClassPublicKey_throws()
throws Exception {
Registry.reset();
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
try {
// Note: due to the {} this is a subclass of TestPublicKeyTypeManager.
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager() {}, true);
fail("Expected GeneralSecurityException");
} catch (GeneralSecurityException e) {
// expected
}
}
@Test
public void testRegisterAssymmetricKeyManagers_thenNormalRegister_throws()
throws Exception {
Registry.reset();
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
try {
// Note: due to the {} this is a subclass.
Registry.registerKeyManager(new TestPrivateKeyTypeManager() {}, true);
fail("Expected GeneralSecurityException");
} catch (GeneralSecurityException e) {
// expected
}
}
@Test
public void testRegisterAssymmetricKeyManagers_thenNormalRegisterForPublic_throws()
throws Exception {
Registry.reset();
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
try {
// Note: due to the {} this is a subclass.
Registry.registerKeyManager(new TestPublicKeyTypeManager() {}, true);
fail("Expected GeneralSecurityException");
} catch (GeneralSecurityException e) {
// expected
}
}
@Test
public void testRegisterAssymmetricKeyManagers_ThrowsWithDifferentPublicKeyManager()
throws Exception {
Registry.reset();
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(), new TestPublicKeyTypeManager(), true);
try {
Registry.registerAsymmetricKeyManagers(
new TestPrivateKeyTypeManager(),
new TestPublicKeyTypeManager() {
@Override
public String getKeyType() {
return "bla";
}
},
true);
fail();
} catch (GeneralSecurityException e) {
// Expected.
assertExceptionContains(e, "public key manager corresponding to");
}
}
private static class Catalogue1 implements Catalogue<Aead> {
@Override
public KeyManager<Aead> getKeyManager(String typeUrl, String primitiveName, int minVersion) {
return null;
}
@Override
public PrimitiveWrapper<Aead> getPrimitiveWrapper() {
return null;
}
}
private static class Catalogue2 implements Catalogue<Aead> {
@Override
public KeyManager<Aead> getKeyManager(String typeUrl, String primitiveName, int minVersion) {
return null;
}
@Override
public PrimitiveWrapper<Aead> getPrimitiveWrapper() {
return null;
}
}
private static class Catalogue3 implements Catalogue<Aead> {
@Override
public KeyManager<Aead> getKeyManager(String typeUrl, String primitiveName, int minVersion) {
return null;
}
@Override
public PrimitiveWrapper<Aead> getPrimitiveWrapper() {
return null;
}
}
@Test
public void testAddCatalogue_MultiThreads_shouldWork() throws Exception {
final boolean[] threwException = new boolean[3];
Thread thread1 =
new Thread(
new Runnable() {
@Override
public void run() {
try {
Registry.addCatalogue("catalogue", new Catalogue1());
threwException[0] = false;
} catch (GeneralSecurityException e) {
threwException[0] = true;
}
}
});
Thread thread2 =
new Thread(
new Runnable() {
@Override
public void run() {
try {
Registry.addCatalogue("catalogue", new Catalogue2());
threwException[1] = false;
} catch (GeneralSecurityException e) {
threwException[1] = true;
}
}
});
Thread thread3 =
new Thread(
new Runnable() {
@Override
public void run() {
try {
Registry.addCatalogue("catalogue", new Catalogue3());
threwException[2] = false;
} catch (GeneralSecurityException e) {
threwException[2] = true;
}
}
});
// Start the threads.
thread1.start();
thread2.start();
thread3.start();
// Wait until all threads finished.
thread1.join();
thread2.join();
thread3.join();
// Count threads that threw exception.
int count = 0;
for (int i = 0; i < 3; i++) {
if (threwException[i]) {
count++;
}
}
assertThat(count).isEqualTo(2);
}
// TODO(przydatek): Add more tests for creation of PrimitiveSets.
@Test
public void testWrap_wrapperRegistered() throws Exception {
KeyData key = Registry.newKeyData(AeadKeyTemplates.AES128_EAX);
KeysetHandle keysetHandle =
KeysetHandle.fromKeyset(
Keyset.newBuilder()
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key)
.setKeyId(1)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.setPrimaryKeyId(1)
.build());
// Get a PrimitiveSet using a custom key manager for key1.
KeyManager<Aead> customManager = new CustomAeadKeyManager(AeadConfig.AES_EAX_TYPE_URL);
PrimitiveSet<Aead> aeadSet = Registry.getPrimitives(keysetHandle, customManager, Aead.class);
Registry.wrap(aeadSet);
}
@Test
public void testWrap_noWrapperRegistered_throws() throws Exception {
KeyData key = Registry.newKeyData(AeadKeyTemplates.AES128_EAX);
Registry.reset();
KeysetHandle keysetHandle =
KeysetHandle.fromKeyset(
Keyset.newBuilder()
.addKey(
Keyset.Key.newBuilder()
.setKeyData(key)
.setKeyId(1)
.setStatus(KeyStatusType.ENABLED)
.setOutputPrefixType(OutputPrefixType.TINK)
.build())
.setPrimaryKeyId(1)
.build());
// Get a PrimitiveSet using a custom key manager for key1.
KeyManager<Aead> customManager = new CustomAeadKeyManager(AeadConfig.AES_EAX_TYPE_URL);
PrimitiveSet<Aead> aeadSet = Registry.getPrimitives(keysetHandle, customManager, Aead.class);
try {
Registry.wrap(aeadSet);
fail("Expected GeneralSecurityException.");
} catch (GeneralSecurityException e) {
assertExceptionContains(e, "No wrapper found");
assertExceptionContains(e, "Aead");
}
}
private static class FakeAead {}
}