aboutsummaryrefslogtreecommitdiff
path: root/java_src
diff options
context:
space:
mode:
authorlizatretyakova <lizatretyakova@google.com>2023-07-19 03:39:10 -0700
committerCopybara-Service <copybara-worker@google.com>2023-07-19 03:40:09 -0700
commit2430b7497cb14db0e861b90e48a197f8a8ff39b0 (patch)
tree643cd1efe955a62dbaf921f26da17666a0bae201 /java_src
parent2e4af940c2ecf072b369180dc4aa6abc49a5314a (diff)
downloadtink-2430b7497cb14db0e861b90e48a197f8a8ff39b0.tar.gz
Add a way to create Macs from LegacyProtoKeys.
PiperOrigin-RevId: 549266939
Diffstat (limited to 'java_src')
-rw-r--r--java_src/BUILD.bazel2
-rw-r--r--java_src/src/main/java/com/google/crypto/tink/mac/internal/BUILD.bazel70
-rw-r--r--java_src/src/main/java/com/google/crypto/tink/mac/internal/LegacyFullMac.java119
-rw-r--r--java_src/src/main/java/com/google/crypto/tink/mac/internal/LegacyHmacTestKeyManager.java238
-rw-r--r--java_src/src/test/java/com/google/crypto/tink/mac/internal/BUILD.bazel19
-rw-r--r--java_src/src/test/java/com/google/crypto/tink/mac/internal/LegacyFullMacTest.java98
6 files changed, 546 insertions, 0 deletions
diff --git a/java_src/BUILD.bazel b/java_src/BUILD.bazel
index c23c622d2..27dd2b3dd 100644
--- a/java_src/BUILD.bazel
+++ b/java_src/BUILD.bazel
@@ -286,6 +286,7 @@ gen_maven_jar_rules(
"//src/main/java/com/google/crypto/tink/mac/internal:chunked_hmac_impl",
"//src/main/java/com/google/crypto/tink/mac/internal:chunked_hmac_verification",
"//src/main/java/com/google/crypto/tink/mac/internal:hmac_proto_serialization",
+ "//src/main/java/com/google/crypto/tink/mac/internal:legacy_full_mac",
"//src/main/java/com/google/crypto/tink/monitoring:monitoring_annotations",
"//src/main/java/com/google/crypto/tink/monitoring:monitoring_client",
"//src/main/java/com/google/crypto/tink/monitoring:monitoring_keyset_info",
@@ -714,6 +715,7 @@ gen_maven_jar_rules(
"//src/main/java/com/google/crypto/tink/mac/internal:chunked_hmac_impl-android",
"//src/main/java/com/google/crypto/tink/mac/internal:chunked_hmac_verification-android",
"//src/main/java/com/google/crypto/tink/mac/internal:hmac_proto_serialization-android",
+ "//src/main/java/com/google/crypto/tink/mac/internal:legacy_full_mac-android",
"//src/main/java/com/google/crypto/tink/monitoring:monitoring_annotations-android",
"//src/main/java/com/google/crypto/tink/monitoring:monitoring_client-android",
"//src/main/java/com/google/crypto/tink/monitoring:monitoring_keyset_info-android",
diff --git a/java_src/src/main/java/com/google/crypto/tink/mac/internal/BUILD.bazel b/java_src/src/main/java/com/google/crypto/tink/mac/internal/BUILD.bazel
index 3b0aa7b7f..634f029cd 100644
--- a/java_src/src/main/java/com/google/crypto/tink/mac/internal/BUILD.bazel
+++ b/java_src/src/main/java/com/google/crypto/tink/mac/internal/BUILD.bazel
@@ -291,3 +291,73 @@ java_library(
"@maven//:com_google_protobuf_protobuf_java",
],
)
+
+java_library(
+ name = "legacy_full_mac",
+ srcs = ["LegacyFullMac.java"],
+ deps = [
+ "//proto:tink_java_proto",
+ "//src/main/java/com/google/crypto/tink:crypto_format",
+ "//src/main/java/com/google/crypto/tink:insecure_secret_key_access",
+ "//src/main/java/com/google/crypto/tink:mac",
+ "//src/main/java/com/google/crypto/tink:registry",
+ "//src/main/java/com/google/crypto/tink/internal:legacy_proto_key",
+ "//src/main/java/com/google/crypto/tink/internal:proto_key_serialization",
+ "//src/main/java/com/google/crypto/tink/subtle:bytes",
+ ],
+)
+
+java_library(
+ name = "legacy_hmac_test_key_manager",
+ testonly = 1,
+ srcs = ["LegacyHmacTestKeyManager.java"],
+ deps = [
+ ":hmac_proto_serialization",
+ "//proto:common_java_proto",
+ "//proto:hmac_java_proto",
+ "//proto:tink_java_proto",
+ "//src/main/java/com/google/crypto/tink:key_manager",
+ "//src/main/java/com/google/crypto/tink:mac",
+ "//src/main/java/com/google/crypto/tink:registry",
+ "//src/main/java/com/google/crypto/tink/subtle:bytes",
+ "//src/main/java/com/google/crypto/tink/subtle:prf_hmac_jce",
+ "//src/main/java/com/google/crypto/tink/subtle:random",
+ "//src/main/java/com/google/crypto/tink/subtle:validators",
+ "@maven//:com_google_protobuf_protobuf_java",
+ ],
+)
+
+android_library(
+ name = "legacy_full_mac-android",
+ srcs = ["LegacyFullMac.java"],
+ deps = [
+ "//proto:tink_java_proto_lite",
+ "//src/main/java/com/google/crypto/tink:crypto_format-android",
+ "//src/main/java/com/google/crypto/tink:insecure_secret_key_access-android",
+ "//src/main/java/com/google/crypto/tink:mac-android",
+ "//src/main/java/com/google/crypto/tink:registry-android",
+ "//src/main/java/com/google/crypto/tink/internal:legacy_proto_key-android",
+ "//src/main/java/com/google/crypto/tink/internal:proto_key_serialization-android",
+ "//src/main/java/com/google/crypto/tink/subtle:bytes-android",
+ ],
+)
+
+android_library(
+ name = "legacy_hmac_test_key_manager-android",
+ testonly = 1,
+ srcs = ["LegacyHmacTestKeyManager.java"],
+ deps = [
+ ":hmac_proto_serialization-android",
+ "//proto:common_java_proto_lite",
+ "//proto:hmac_java_proto_lite",
+ "//proto:tink_java_proto_lite",
+ "//src/main/java/com/google/crypto/tink:key_manager-android",
+ "//src/main/java/com/google/crypto/tink:mac-android",
+ "//src/main/java/com/google/crypto/tink:registry-android",
+ "//src/main/java/com/google/crypto/tink/subtle:bytes-android",
+ "//src/main/java/com/google/crypto/tink/subtle:prf_hmac_jce-android",
+ "//src/main/java/com/google/crypto/tink/subtle:random-android",
+ "//src/main/java/com/google/crypto/tink/subtle:validators-android",
+ "@maven//:com_google_protobuf_protobuf_javalite",
+ ],
+)
diff --git a/java_src/src/main/java/com/google/crypto/tink/mac/internal/LegacyFullMac.java b/java_src/src/main/java/com/google/crypto/tink/mac/internal/LegacyFullMac.java
new file mode 100644
index 000000000..401544fa9
--- /dev/null
+++ b/java_src/src/main/java/com/google/crypto/tink/mac/internal/LegacyFullMac.java
@@ -0,0 +1,119 @@
+// 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.mac.internal;
+
+import com.google.crypto.tink.CryptoFormat;
+import com.google.crypto.tink.InsecureSecretKeyAccess;
+import com.google.crypto.tink.Mac;
+import com.google.crypto.tink.Registry;
+import com.google.crypto.tink.internal.LegacyProtoKey;
+import com.google.crypto.tink.internal.ProtoKeySerialization;
+import com.google.crypto.tink.proto.KeyData;
+import com.google.crypto.tink.proto.OutputPrefixType;
+import com.google.crypto.tink.subtle.Bytes;
+import java.nio.ByteBuffer;
+import java.security.GeneralSecurityException;
+import java.util.Arrays;
+
+/**
+ * Takes an arbitrary raw Mac and makes it a full primitive.
+ * This is a class that helps us transition onto the new Keys and Configurations interface,
+ * by bringing potential user-defined primitives to a common denominator with our primitives over
+ * which we have control.
+ */
+public final class LegacyFullMac implements Mac {
+ // A single byte to be added to the plaintext for the legacy key type.
+ private static final byte[] FORMAT_VERSION = new byte[] {0};
+ static final int MIN_TAG_SIZE_IN_BYTES = 10;
+
+ private final Mac rawMac;
+ private final OutputPrefixType outputPrefixType;
+ private final byte[] identifier;
+
+ /** This method covers the cases where users created their own mac/key classes. */
+ public static Mac create(LegacyProtoKey key) throws GeneralSecurityException {
+ ProtoKeySerialization protoKeySerialization =
+ key.getSerialization(InsecureSecretKeyAccess.get());
+ KeyData keyData =
+ KeyData.newBuilder()
+ .setTypeUrl(protoKeySerialization.getTypeUrl())
+ .setValue(protoKeySerialization.getValue())
+ .setKeyMaterialType(protoKeySerialization.getKeyMaterialType())
+ .build();
+ Mac rawPrimitive = Registry.getPrimitive(keyData, Mac.class);
+
+ OutputPrefixType outputPrefixType = protoKeySerialization.getOutputPrefixType();
+ byte[] outputPrefix;
+ switch (outputPrefixType) {
+ case RAW:
+ outputPrefix = new byte[] {};
+ break;
+ case LEGACY:
+ case CRUNCHY:
+ outputPrefix =
+ ByteBuffer.allocate(5).put((byte) 0).putInt(key.getIdRequirementOrNull()).array();
+ break;
+ case TINK:
+ outputPrefix =
+ ByteBuffer.allocate(5).put((byte) 1).putInt(key.getIdRequirementOrNull()).array();
+ break;
+ default:
+ throw new GeneralSecurityException("unknown output prefix type");
+ }
+ return new LegacyFullMac(rawPrimitive, outputPrefixType, outputPrefix);
+ }
+
+ private LegacyFullMac(Mac rawMac, OutputPrefixType outputPrefixType, byte[] identifier) {
+ this.rawMac = rawMac;
+ this.outputPrefixType = outputPrefixType;
+ this.identifier = identifier;
+ }
+
+ @Override
+ public byte[] computeMac(byte[] data) throws GeneralSecurityException {
+ byte[] data2 = data;
+ if (outputPrefixType.equals(OutputPrefixType.LEGACY)) {
+ data2 = Bytes.concat(data, FORMAT_VERSION);
+ }
+ return Bytes.concat(identifier, rawMac.computeMac(data2));
+ }
+
+ @Override
+ public void verifyMac(byte[] mac, byte[] data) throws GeneralSecurityException {
+ if (mac.length < MIN_TAG_SIZE_IN_BYTES) {
+ throw new GeneralSecurityException("tag too short");
+ }
+
+ byte[] data2 = data;
+ if (outputPrefixType.equals(OutputPrefixType.LEGACY)) {
+ data2 = Bytes.concat(data, FORMAT_VERSION);
+ }
+
+ byte[] prefix = new byte[0];
+ byte[] macNoPrefix = mac;
+ if (!outputPrefixType.equals(OutputPrefixType.RAW)) {
+ prefix = Arrays.copyOf(mac, CryptoFormat.NON_RAW_PREFIX_SIZE);
+ macNoPrefix = Arrays.copyOfRange(mac, CryptoFormat.NON_RAW_PREFIX_SIZE, mac.length);
+ }
+
+ if (!Arrays.equals(identifier, prefix)) {
+ throw new GeneralSecurityException("wrong prefix");
+ }
+
+ rawMac.verifyMac(macNoPrefix, data2);
+ }
+}
diff --git a/java_src/src/main/java/com/google/crypto/tink/mac/internal/LegacyHmacTestKeyManager.java b/java_src/src/main/java/com/google/crypto/tink/mac/internal/LegacyHmacTestKeyManager.java
new file mode 100644
index 000000000..c152037f0
--- /dev/null
+++ b/java_src/src/main/java/com/google/crypto/tink/mac/internal/LegacyHmacTestKeyManager.java
@@ -0,0 +1,238 @@
+// 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.mac.internal;
+
+import com.google.crypto.tink.KeyManager;
+import com.google.crypto.tink.Mac;
+import com.google.crypto.tink.Registry;
+import com.google.crypto.tink.proto.HashType;
+import com.google.crypto.tink.proto.HmacKey;
+import com.google.crypto.tink.proto.HmacKeyFormat;
+import com.google.crypto.tink.proto.HmacParams;
+import com.google.crypto.tink.proto.KeyData;
+import com.google.crypto.tink.subtle.Bytes;
+import com.google.crypto.tink.subtle.PrfHmacJce;
+import com.google.crypto.tink.subtle.Random;
+import com.google.crypto.tink.subtle.Validators;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.ExtensionRegistryLite;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.MessageLite;
+import java.security.GeneralSecurityException;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * Test helper key manager emulating a user that has a custom old KeyManager implementation with
+ * a custom Mac primitive. In order to test our code handling such cases.
+ */
+class LegacyHmacTestKeyManager implements KeyManager<Mac> {
+ /** Type url that this manager does support. */
+ // public static final String TYPE_URL = "type.googleapis.com/google.crypto.tink.HmacKey";
+ public static final String TYPE_URL = "type.googleapis.com/google.crypto.tink.HmacKey";
+ /** Current version of this key manager. Keys with version equal or smaller are supported. */
+ private static final int VERSION = 0;
+
+ /** Minimum key size in bytes. */
+ private static final int MIN_KEY_SIZE_IN_BYTES = 16;
+
+ /** Minimum tag size in bytes. This provides minimum 80-bit security strength. */
+ private static final int MIN_TAG_SIZE_IN_BYTES = 10;
+
+ /** @param serializedKey serialized {@code HmacKey} proto */
+ @Override
+ public Mac getPrimitive(ByteString serializedKey) throws GeneralSecurityException {
+ try {
+ HmacKey keyProto = HmacKey.parseFrom(serializedKey, ExtensionRegistryLite.getEmptyRegistry());
+ return getPrimitive(keyProto);
+ } catch (InvalidProtocolBufferException e) {
+ throw new GeneralSecurityException("expected serialized HmacKey proto", e);
+ }
+ }
+
+ /** @param key {@code HmacKey} proto */
+ @Override
+ public Mac getPrimitive(MessageLite key) throws GeneralSecurityException {
+ if (!(key instanceof HmacKey)) {
+ throw new GeneralSecurityException("expected HmacKey proto");
+ }
+ HmacKey keyProto = (HmacKey) key;
+ validate(keyProto);
+ HashType hash = keyProto.getParams().getHash();
+ byte[] keyValue = keyProto.getKeyValue().toByteArray();
+ SecretKeySpec keySpec = new SecretKeySpec(keyValue, "HMAC");
+ int tagSize = keyProto.getParams().getTagSize();
+ switch (hash) {
+ case SHA1:
+ return new LegacyMacTestImpl(new PrfHmacJce("HMACSHA1", keySpec), tagSize);
+ case SHA224:
+ return new LegacyMacTestImpl(new PrfHmacJce("HMACSHA224", keySpec), tagSize);
+ case SHA256:
+ return new LegacyMacTestImpl(new PrfHmacJce("HMACSHA256", keySpec), tagSize);
+ case SHA384:
+ return new LegacyMacTestImpl(new PrfHmacJce("HMACSHA384", keySpec), tagSize);
+ case SHA512:
+ return new LegacyMacTestImpl(new PrfHmacJce("HMACSHA512", keySpec), tagSize);
+ default:
+ throw new GeneralSecurityException("unknown hash");
+ }
+ }
+
+ /**
+ * @param serializedKeyFormat serialized {@code HmacKeyFormat} proto
+ * @return new {@code HmacKey} proto
+ */
+ @Override
+ public MessageLite newKey(ByteString serializedKeyFormat) throws GeneralSecurityException {
+ try {
+ HmacKeyFormat format =
+ HmacKeyFormat.parseFrom(serializedKeyFormat, ExtensionRegistryLite.getEmptyRegistry());
+ return newKey(format);
+ } catch (InvalidProtocolBufferException e) {
+ throw new GeneralSecurityException("expected serialized HmacKeyFormat proto", e);
+ }
+ }
+
+ /**
+ * @param keyFormat {@code HmacKeyFormat} proto
+ * @return new {@code HmacKey} proto
+ */
+ @Override
+ public MessageLite newKey(MessageLite keyFormat) throws GeneralSecurityException {
+ if (!(keyFormat instanceof HmacKeyFormat)) {
+ throw new GeneralSecurityException("expected HmacKeyFormat proto");
+ }
+ HmacKeyFormat format = (HmacKeyFormat) keyFormat;
+ validate(format);
+ return HmacKey.newBuilder()
+ .setVersion(VERSION)
+ .setParams(format.getParams())
+ .setKeyValue(ByteString.copyFrom(Random.randBytes(format.getKeySize())))
+ .build();
+ }
+
+ /**
+ * @param serializedKeyFormat serialized {@code HmacKeyFormat} proto
+ * @return {@code KeyData} with a new {@code HmacKey} proto
+ */
+ @Override
+ public KeyData newKeyData(ByteString serializedKeyFormat) throws GeneralSecurityException {
+ HmacKey key = (HmacKey) newKey(serializedKeyFormat);
+ return KeyData.newBuilder()
+ .setTypeUrl(TYPE_URL)
+ .setValue(key.toByteString())
+ .setKeyMaterialType(KeyData.KeyMaterialType.SYMMETRIC)
+ .build();
+ }
+
+ @Override
+ public boolean doesSupport(String typeUrl) {
+ return typeUrl.equals(TYPE_URL);
+ }
+
+ @Override
+ public String getKeyType() {
+ return TYPE_URL;
+ }
+
+ @Override
+ public int getVersion() {
+ return VERSION;
+ }
+
+ @Override
+ public Class<Mac> getPrimitiveClass() {
+ return Mac.class;
+ }
+
+ private void validate(HmacKey key) throws GeneralSecurityException {
+ Validators.validateVersion(key.getVersion(), VERSION);
+ if (key.getKeyValue().size() < MIN_KEY_SIZE_IN_BYTES) {
+ throw new GeneralSecurityException("key too short");
+ }
+ validate(key.getParams());
+ }
+
+ private void validate(HmacKeyFormat format) throws GeneralSecurityException {
+ if (format.getKeySize() < MIN_KEY_SIZE_IN_BYTES) {
+ throw new GeneralSecurityException("key too short");
+ }
+ validate(format.getParams());
+ }
+
+ private void validate(HmacParams params) throws GeneralSecurityException {
+ if (params.getTagSize() < MIN_TAG_SIZE_IN_BYTES) {
+ throw new GeneralSecurityException("tag size too small");
+ }
+ switch (params.getHash()) {
+ case SHA1:
+ if (params.getTagSize() > 20) {
+ throw new GeneralSecurityException("tag size too big");
+ }
+ break;
+ case SHA224:
+ if (params.getTagSize() > 28) {
+ throw new GeneralSecurityException("tag size too big");
+ }
+ break;
+ case SHA256:
+ if (params.getTagSize() > 32) {
+ throw new GeneralSecurityException("tag size too big");
+ }
+ break;
+ case SHA384:
+ if (params.getTagSize() > 48) {
+ throw new GeneralSecurityException("tag size too big");
+ }
+ break;
+ case SHA512:
+ if (params.getTagSize() > 64) {
+ throw new GeneralSecurityException("tag size too big");
+ }
+ break;
+ default:
+ throw new GeneralSecurityException("unknown hash type");
+ }
+ }
+
+ static void register() throws GeneralSecurityException {
+ Registry.registerKeyManager(new LegacyHmacTestKeyManager(), true);
+ HmacProtoSerialization.register();
+ }
+
+ private static final class LegacyMacTestImpl implements Mac {
+
+ private final PrfHmacJce prfHmac;
+ private final int outputLength;
+
+ LegacyMacTestImpl(PrfHmacJce prfHmac, int outputLength) {
+ this.prfHmac = prfHmac;
+ this.outputLength = outputLength;
+ }
+
+ @Override
+ public byte[] computeMac(byte[] data) throws GeneralSecurityException {
+ return prfHmac.compute(data, outputLength);
+ }
+
+ @Override
+ public void verifyMac(byte[] mac, byte[] data) throws GeneralSecurityException {
+ if (!Bytes.equal(computeMac(data), mac)) {
+ throw new GeneralSecurityException("invalid MAC");
+ }
+ }
+ }
+}
diff --git a/java_src/src/test/java/com/google/crypto/tink/mac/internal/BUILD.bazel b/java_src/src/test/java/com/google/crypto/tink/mac/internal/BUILD.bazel
index e43888cbb..34660fda5 100644
--- a/java_src/src/test/java/com/google/crypto/tink/mac/internal/BUILD.bazel
+++ b/java_src/src/test/java/com/google/crypto/tink/mac/internal/BUILD.bazel
@@ -65,3 +65,22 @@ java_test(
"@maven//:org_conscrypt_conscrypt_openjdk_uber",
],
)
+
+java_test(
+ name = "LegacyFullMacTest",
+ size = "small",
+ srcs = ["LegacyFullMacTest.java"],
+ deps = [
+ "//src/main/java/com/google/crypto/tink:insecure_secret_key_access",
+ "//src/main/java/com/google/crypto/tink:mac",
+ "//src/main/java/com/google/crypto/tink/internal:legacy_proto_key",
+ "//src/main/java/com/google/crypto/tink/internal:mutable_serialization_registry",
+ "//src/main/java/com/google/crypto/tink/internal:proto_key_serialization",
+ "//src/main/java/com/google/crypto/tink/mac:hmac_key",
+ "//src/main/java/com/google/crypto/tink/mac/internal:hmac_test_util",
+ "//src/main/java/com/google/crypto/tink/mac/internal:legacy_full_mac",
+ "//src/main/java/com/google/crypto/tink/mac/internal:legacy_hmac_test_key_manager",
+ "@maven//:com_google_truth_truth",
+ "@maven//:junit_junit",
+ ],
+)
diff --git a/java_src/src/test/java/com/google/crypto/tink/mac/internal/LegacyFullMacTest.java b/java_src/src/test/java/com/google/crypto/tink/mac/internal/LegacyFullMacTest.java
new file mode 100644
index 000000000..d6730ba7b
--- /dev/null
+++ b/java_src/src/test/java/com/google/crypto/tink/mac/internal/LegacyFullMacTest.java
@@ -0,0 +1,98 @@
+// 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.mac.internal;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
+
+import com.google.crypto.tink.InsecureSecretKeyAccess;
+import com.google.crypto.tink.Mac;
+import com.google.crypto.tink.internal.LegacyProtoKey;
+import com.google.crypto.tink.internal.MutableSerializationRegistry;
+import com.google.crypto.tink.internal.ProtoKeySerialization;
+import com.google.crypto.tink.mac.HmacKey;
+import com.google.crypto.tink.mac.internal.HmacTestUtil.HmacTestVector;
+import java.security.GeneralSecurityException;
+import java.util.Arrays;
+import org.junit.BeforeClass;
+import org.junit.experimental.theories.DataPoints;
+import org.junit.experimental.theories.FromDataPoints;
+import org.junit.experimental.theories.Theories;
+import org.junit.experimental.theories.Theory;
+import org.junit.runner.RunWith;
+
+@RunWith(Theories.class)
+public class LegacyFullMacTest {
+ @BeforeClass
+ public static void setUp() throws Exception {
+ LegacyHmacTestKeyManager.register();
+
+ hmacImplementationTestVectors =
+ Arrays.copyOf(
+ HmacTestUtil.HMAC_TEST_VECTORS,
+ HmacTestUtil.HMAC_TEST_VECTORS.length + HmacTestUtil.PREFIXED_KEY_TYPES.length);
+ System.arraycopy(
+ HmacTestUtil.PREFIXED_KEY_TYPES,
+ 0,
+ hmacImplementationTestVectors,
+ HmacTestUtil.HMAC_TEST_VECTORS.length,
+ HmacTestUtil.PREFIXED_KEY_TYPES.length);
+ }
+
+ @DataPoints("failingHmacTestVectors")
+ public static final HmacTestVector[] HMAC_FAILING_TEST_VECTORS =
+ HmacTestUtil.CREATE_VERIFICATION_FAILS_FAST;
+
+ public static final String TYPE_URL = "LegacyHmacTestKey";
+
+ @DataPoints("allHmacTestVectors")
+ public static HmacTestVector[] hmacImplementationTestVectors;
+
+ @Theory
+ public void computeHmac_isCorrect(@FromDataPoints("allHmacTestVectors") HmacTestVector t)
+ throws Exception {
+ LegacyProtoKey key = getLegacyProtoKey(t.key);
+ Mac hmac = LegacyFullMac.create(key);
+
+ assertThat(hmac.computeMac(t.message)).isEqualTo(t.tag);
+ }
+
+ @Theory
+ public void verifyHmac_isCorrect(@FromDataPoints("allHmacTestVectors") HmacTestVector t)
+ throws Exception {
+ LegacyProtoKey key = getLegacyProtoKey(t.key);
+ Mac hmac = LegacyFullMac.create(key);
+
+ hmac.verifyMac(t.tag, t.message);
+ }
+
+ @Theory
+ public void verifyHmac_throwsOnWrongTag(
+ @FromDataPoints("failingHmacTestVectors") HmacTestVector t) throws Exception {
+ LegacyProtoKey key = getLegacyProtoKey(t.key);
+ Mac hmac = LegacyFullMac.create(key);
+
+ assertThrows(GeneralSecurityException.class, () -> hmac.verifyMac(t.tag, t.message));
+ }
+
+ private static LegacyProtoKey getLegacyProtoKey(HmacKey hmacKey) throws GeneralSecurityException {
+ return new LegacyProtoKey(
+ MutableSerializationRegistry.globalInstance()
+ .serializeKey(hmacKey, ProtoKeySerialization.class, InsecureSecretKeyAccess.get()),
+ InsecureSecretKeyAccess.get());
+ }
+}