Skip to content

Commit

Permalink
Add LegacyAesSivTestKeyManager.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 587632165
Change-Id: I5fefc6bdc12963bab0434bf01add20f5fa56760d
  • Loading branch information
ioannanedelcu authored and Copybara-Service committed Dec 4, 2023
1 parent 865c4be commit c70e78c
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
load("@build_bazel_rules_android//android:rules.bzl", "android_library")

licenses(["notice"])

package(
default_testonly = 1,
default_visibility = ["//:__subpackages__"],
)

java_library(
name = "legacy_aes_siv_test_key_manager",
srcs = ["LegacyAesSivTestKeyManager.java"],
deps = [
"//proto:aes_siv_java_proto",
"//proto:tink_java_proto",
"//src/main/java/com/google/crypto/tink:deterministic_aead",
"//src/main/java/com/google/crypto/tink:key_manager",
"//src/main/java/com/google/crypto/tink:registry",
"//src/main/java/com/google/crypto/tink/subtle:aes_siv",
"@maven//:com_google_protobuf_protobuf_java",
],
)

android_library(
name = "legacy_aes_siv_test_key_manager-android",
srcs = ["LegacyAesSivTestKeyManager.java"],
deps = [
"//proto:aes_siv_java_proto_lite",
"//proto:tink_java_proto_lite",
"//src/main/java/com/google/crypto/tink:deterministic_aead-android",
"//src/main/java/com/google/crypto/tink:key_manager-android",
"//src/main/java/com/google/crypto/tink:registry-android",
"//src/main/java/com/google/crypto/tink/subtle:aes_siv-android",
"@maven//:com_google_protobuf_protobuf_javalite",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright 2023 Google LLC
//
// 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.daead.internal.testing;

import com.google.crypto.tink.DeterministicAead;
import com.google.crypto.tink.KeyManager;
import com.google.crypto.tink.Registry;
import com.google.crypto.tink.proto.AesSivKey;
import com.google.crypto.tink.proto.KeyData;
import com.google.crypto.tink.subtle.AesSiv;
import com.google.protobuf.ByteString;
import com.google.protobuf.ExtensionRegistryLite;
import com.google.protobuf.InvalidProtocolBufferException;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;

/**
* Test helper key manager emulating a user that has a custom old KeyManager implementation with a
* custom DeterministicAead primitive. Helps testing our code which handles such cases.
*/
public class LegacyAesSivTestKeyManager implements KeyManager<DeterministicAead> {
/** Custom type url that this manager does support. */
public static final String TYPE_URL = "type.googleapis.com/custom.AesSivKey";

private static final int KEY_SIZE_IN_BYTES = 64;

@Override
public DeterministicAead getPrimitive(ByteString serializedKey) throws GeneralSecurityException {
try {
AesSivKey keyProto =
AesSivKey.parseFrom(serializedKey, ExtensionRegistryLite.getEmptyRegistry());
validateKey(keyProto);
return new AesSiv(keyProto.getKeyValue().toByteArray());
} catch (InvalidProtocolBufferException e) {
throw new GeneralSecurityException("Expected serialized AesSivKey proto", e);
}
}

private void validateKey(AesSivKey key) throws GeneralSecurityException {
if (key.getKeyValue().size() != KEY_SIZE_IN_BYTES) {
throw new InvalidKeyException(
"Invalid key size: "
+ key.getKeyValue().size()
+ ". Valid keys must have "
+ KEY_SIZE_IN_BYTES
+ " bytes.");
}
}

@Override
public String getKeyType() {
return TYPE_URL;
}

@Override
public Class<DeterministicAead> getPrimitiveClass() {
return DeterministicAead.class;
}

@Override
public KeyData newKeyData(ByteString serializedKeyFormat) throws GeneralSecurityException {
throw new UnsupportedOperationException("not needed for tests");
}

public static void register() throws GeneralSecurityException {
Registry.registerKeyManager(new LegacyAesSivTestKeyManager(), true);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
licenses(["notice"])

java_test(
name = "LegacyAesSivTestKeyManagerTest",
size = "small",
srcs = ["LegacyAesSivTestKeyManagerTest.java"],
deps = [
"//proto:aes_siv_java_proto",
"//proto:tink_java_proto",
"//src/main/java/com/google/crypto/tink:deterministic_aead",
"//src/main/java/com/google/crypto/tink:registry",
"//src/main/java/com/google/crypto/tink/daead/internal/testing:legacy_aes_siv_test_key_manager",
"//src/main/java/com/google/crypto/tink/subtle:aes_siv",
"//src/main/java/com/google/crypto/tink/subtle:random",
"@maven//:com_google_protobuf_protobuf_java",
"@maven//:com_google_truth_truth",
"@maven//:junit_junit",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Copyright 2023 Google LLC
//
// 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.daead.internal.testing;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertThrows;

import com.google.crypto.tink.DeterministicAead;
import com.google.crypto.tink.Registry;
import com.google.crypto.tink.proto.AesSivKey;
import com.google.crypto.tink.proto.KeyData;
import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
import com.google.crypto.tink.subtle.AesSiv;
import com.google.crypto.tink.subtle.Random;
import com.google.protobuf.ByteString;
import java.security.GeneralSecurityException;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public class LegacyAesSivTestKeyManagerTest {
/** Type url that this manager supports. */
public static final String TYPE_URL = "type.googleapis.com/custom.AesSivKey";

@BeforeClass
public static void setUp() throws Exception {
LegacyAesSivTestKeyManager.register();
}

@Test
public void getPrimitive_works() throws Exception {
AesSivKey key =
AesSivKey.newBuilder()
.setKeyValue(ByteString.copyFrom(Random.randBytes(64)))
.setVersion(0)
.build();
KeyData keyData =
KeyData.newBuilder()
.setKeyMaterialType(KeyMaterialType.SYMMETRIC)
.setTypeUrl(TYPE_URL)
.setValue(key.toByteString())
.build();

DeterministicAead daead = Registry.getPrimitive(keyData, DeterministicAead.class);

assertThat(daead).isNotNull();
assertThat(daead).isInstanceOf(AesSiv.class);
}

@Test
public void getPrimitive_encryptDecryptDeterministically_works() throws Exception {
AesSivKey key =
AesSivKey.newBuilder()
.setKeyValue(ByteString.copyFrom(Random.randBytes(64)))
.setVersion(0)
.build();
KeyData keyData =
KeyData.newBuilder()
.setKeyMaterialType(KeyMaterialType.SYMMETRIC)
.setTypeUrl(TYPE_URL)
.setValue(key.toByteString())
.build();

DeterministicAead daead = Registry.getPrimitive(keyData, DeterministicAead.class);
byte[] plaintext = Random.randBytes(20);
byte[] associatedData = Random.randBytes(20);
byte[] ciphertext = daead.encryptDeterministically(plaintext, associatedData);
byte[] ciphertext2 = daead.encryptDeterministically(plaintext, associatedData);
byte[] decrypted = daead.decryptDeterministically(ciphertext, associatedData);
byte[] decrypted2 = daead.decryptDeterministically(ciphertext2, associatedData);

assertArrayEquals(ciphertext, ciphertext2);
assertArrayEquals(plaintext, decrypted);
assertArrayEquals(plaintext, decrypted2);
}

@Test
public void getPrimitive_wrongKeySize_throws() throws Exception {
AesSivKey key =
AesSivKey.newBuilder()
.setKeyValue(ByteString.copyFrom(Random.randBytes(32)))
.setVersion(0)
.build();
KeyData keyData =
KeyData.newBuilder()
.setKeyMaterialType(KeyMaterialType.SYMMETRIC)
.setTypeUrl(TYPE_URL)
.setValue(key.toByteString())
.build();

assertThrows(
GeneralSecurityException.class,
() -> Registry.getPrimitive(keyData, DeterministicAead.class));
}
}

0 comments on commit c70e78c

Please sign in to comment.