From e6791ff52e5ea0ca3f824cda06ff1e64279ae1c3 Mon Sep 17 00:00:00 2001
From: tholenst <tholenst@google.com>
Date: Wed, 28 Aug 2019 01:29:15 -0700
Subject: [PATCH] Migrate the HmacKeyManager to a KeyTypeManager.

PiperOrigin-RevId: 265859469
---
 .../crypto/tink/mac/HmacKeyManager.java       | 118 +++++++++---------
 .../com/google/crypto/tink/mac/MacConfig.java |   4 +-
 .../crypto/tink/mac/MacKeyTemplates.java      |   2 +-
 .../com/google/crypto/tink/RegistryTest.java  |   6 +-
 .../crypto/tink/mac/HmacKeyManagerTest.java   |  25 ++--
 .../crypto/tink/mac/MacKeyTemplatesTest.java  |  10 +-
 6 files changed, 87 insertions(+), 78 deletions(-)

diff --git a/java/src/main/java/com/google/crypto/tink/mac/HmacKeyManager.java b/java/src/main/java/com/google/crypto/tink/mac/HmacKeyManager.java
index 12629712c..a7863a0bd 100644
--- a/java/src/main/java/com/google/crypto/tink/mac/HmacKeyManager.java
+++ b/java/src/main/java/com/google/crypto/tink/mac/HmacKeyManager.java
@@ -16,7 +16,7 @@
 
 package com.google.crypto.tink.mac;
 
-import com.google.crypto.tink.KeyManagerBase;
+import com.google.crypto.tink.KeyTypeManager;
 import com.google.crypto.tink.Mac;
 import com.google.crypto.tink.proto.HashType;
 import com.google.crypto.tink.proto.HmacKey;
@@ -34,51 +34,42 @@ import javax.crypto.spec.SecretKeySpec;
 /**
  * This key manager generates new {@code HmacKey} keys and produces new instances of {@code MacJce}.
  */
-class HmacKeyManager extends KeyManagerBase<Mac, HmacKey, HmacKeyFormat> {
+class HmacKeyManager extends KeyTypeManager<HmacKey> {
   public HmacKeyManager() {
-    super(Mac.class, HmacKey.class, HmacKeyFormat.class, TYPE_URL);
+    super(
+        HmacKey.class,
+        new PrimitiveFactory<Mac, HmacKey>(Mac.class) {
+          @Override
+          public Mac getPrimitive(HmacKey key) throws GeneralSecurityException {
+            HashType hash = key.getParams().getHash();
+            byte[] keyValue = key.getKeyValue().toByteArray();
+            SecretKeySpec keySpec = new SecretKeySpec(keyValue, "HMAC");
+            int tagSize = key.getParams().getTagSize();
+            switch (hash) {
+              case SHA1:
+                return new MacJce("HMACSHA1", keySpec, tagSize);
+              case SHA256:
+                return new MacJce("HMACSHA256", keySpec, tagSize);
+              case SHA512:
+                return new MacJce("HMACSHA512", keySpec, tagSize);
+              default:
+                throw new GeneralSecurityException("unknown hash");
+            }
+          }
+        });
   }
-  /** Type url that this manager does support. */
-  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;
 
+  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 getPrimitiveFromKey(HmacKey keyProto) throws GeneralSecurityException {
-    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 MacJce("HMACSHA1", keySpec, tagSize);
-      case SHA256:
-        return new MacJce("HMACSHA256", keySpec, tagSize);
-      case SHA512:
-        return new MacJce("HMACSHA512", keySpec, tagSize);
-      default:
-        throw new GeneralSecurityException("unknown hash");
-    }
-  }
-
-  /**
-   * @param serializedKeyFormat serialized {@code HmacKeyFormat} proto
-   * @return new {@code HmacKey} proto
-   */
-  @Override
-  public HmacKey newKeyFromFormat(HmacKeyFormat format) throws GeneralSecurityException {
-    return HmacKey.newBuilder()
-        .setVersion(VERSION)
-        .setParams(format.getParams())
-        .setKeyValue(ByteString.copyFrom(Random.randBytes(format.getKeySize())))
-        .build();
+  public String getKeyType() {
+    return "type.googleapis.com/google.crypto.tink.HmacKey";
   }
 
   @Override
@@ -87,40 +78,25 @@ class HmacKeyManager extends KeyManagerBase<Mac, HmacKey, HmacKeyFormat> {
   }
 
   @Override
-  protected KeyMaterialType keyMaterialType() {
+  public KeyMaterialType keyMaterialType() {
     return KeyMaterialType.SYMMETRIC;
   }
 
   @Override
-  protected HmacKey parseKeyProto(ByteString byteString)
-      throws InvalidProtocolBufferException {
-    return HmacKey.parseFrom(byteString);
-  }
-
-  @Override
-  protected HmacKeyFormat parseKeyFormatProto(ByteString byteString)
-      throws InvalidProtocolBufferException {
-    return HmacKeyFormat.parseFrom(byteString);
-  }
-
-  @Override
-  protected void validateKey(HmacKey key) throws GeneralSecurityException {
+  public void validateKey(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());
+    validateParams(key.getParams());
   }
 
   @Override
-  protected void validateKeyFormat(HmacKeyFormat format) throws GeneralSecurityException {
-    if (format.getKeySize() < MIN_KEY_SIZE_IN_BYTES) {
-      throw new GeneralSecurityException("key too short");
-    }
-    validate(format.getParams());
+  public HmacKey parseKey(ByteString byteString) throws InvalidProtocolBufferException {
+    return HmacKey.parseFrom(byteString);
   }
 
-  private void validate(HmacParams params) throws GeneralSecurityException {
+  private static void validateParams(HmacParams params) throws GeneralSecurityException {
     if (params.getTagSize() < MIN_TAG_SIZE_IN_BYTES) {
       throw new GeneralSecurityException("tag size too small");
     }
@@ -144,4 +120,32 @@ class HmacKeyManager extends KeyManagerBase<Mac, HmacKey, HmacKeyFormat> {
         throw new GeneralSecurityException("unknown hash type");
     }
   }
+
+  @Override
+  public KeyFactory<HmacKeyFormat, HmacKey> keyFactory() {
+    return new KeyFactory<HmacKeyFormat, HmacKey>(HmacKeyFormat.class) {
+      @Override
+      public void validateKeyFormat(HmacKeyFormat format) throws GeneralSecurityException {
+        if (format.getKeySize() < MIN_KEY_SIZE_IN_BYTES) {
+          throw new GeneralSecurityException("key too short");
+        }
+        validateParams(format.getParams());
+      }
+
+      @Override
+      public HmacKeyFormat parseKeyFormat(ByteString byteString)
+          throws InvalidProtocolBufferException {
+        return HmacKeyFormat.parseFrom(byteString);
+      }
+
+      @Override
+      public HmacKey createKey(HmacKeyFormat format) throws GeneralSecurityException {
+        return HmacKey.newBuilder()
+            .setVersion(VERSION)
+            .setParams(format.getParams())
+            .setKeyValue(ByteString.copyFrom(Random.randBytes(format.getKeySize())))
+            .build();
+      }
+    };
+  }
 }
diff --git a/java/src/main/java/com/google/crypto/tink/mac/MacConfig.java b/java/src/main/java/com/google/crypto/tink/mac/MacConfig.java
index e02de636a..29fd052eb 100644
--- a/java/src/main/java/com/google/crypto/tink/mac/MacConfig.java
+++ b/java/src/main/java/com/google/crypto/tink/mac/MacConfig.java
@@ -35,7 +35,7 @@ import java.security.GeneralSecurityException;
  * @since 1.0.0
  */
 public final class MacConfig {
-  public static final String HMAC_TYPE_URL = HmacKeyManager.TYPE_URL;
+  public static final String HMAC_TYPE_URL = new HmacKeyManager().getKeyType();
 
   /** @deprecated */
   @Deprecated
@@ -83,7 +83,7 @@ public final class MacConfig {
    * @since 1.2.0
    */
   public static void register() throws GeneralSecurityException {
-    Registry.registerKeyManager(new HmacKeyManager());
+    Registry.registerKeyManager(new HmacKeyManager(), true);
     Registry.registerKeyManager(new AesCmacKeyManager(), true);
     Registry.registerPrimitiveWrapper(new MacWrapper());
   }
diff --git a/java/src/main/java/com/google/crypto/tink/mac/MacKeyTemplates.java b/java/src/main/java/com/google/crypto/tink/mac/MacKeyTemplates.java
index 8e28f5a13..7bfeceafa 100644
--- a/java/src/main/java/com/google/crypto/tink/mac/MacKeyTemplates.java
+++ b/java/src/main/java/com/google/crypto/tink/mac/MacKeyTemplates.java
@@ -132,7 +132,7 @@ public final class MacKeyTemplates {
         .build();
     return KeyTemplate.newBuilder()
         .setValue(format.toByteString())
-        .setTypeUrl(HmacKeyManager.TYPE_URL)
+        .setTypeUrl(new HmacKeyManager().getKeyType())
         .setOutputPrefixType(OutputPrefixType.TINK)
         .build();
   }
diff --git a/java/src/test/java/com/google/crypto/tink/RegistryTest.java b/java/src/test/java/com/google/crypto/tink/RegistryTest.java
index 985cb66dc..0c16ab7dc 100644
--- a/java/src/test/java/com/google/crypto/tink/RegistryTest.java
+++ b/java/src/test/java/com/google/crypto/tink/RegistryTest.java
@@ -126,7 +126,7 @@ public class RegistryTest {
   public void testGetKeyManager_legacy_shouldWork() throws Exception {
     testGetKeyManager_shouldWork(AeadConfig.AES_CTR_HMAC_AEAD_TYPE_URL, "AesCtrHmacAeadKeyManager");
     testGetKeyManager_shouldWork(AeadConfig.AES_EAX_TYPE_URL, "AesEaxKeyManager");
-    testGetKeyManager_shouldWork(MacConfig.HMAC_TYPE_URL, "HmacKeyManager");
+    testGetKeyManager_shouldWork(MacConfig.HMAC_TYPE_URL, "KeyManagerImpl");
   }
 
   @Test
@@ -139,7 +139,7 @@ public class RegistryTest {
   @Test
   public void testGetKeyManager_shouldWorkHmac() throws Exception {
     assertThat(Registry.getKeyManager(MacConfig.HMAC_TYPE_URL, Mac.class).getClass().toString())
-        .contains("HmacKeyManager");
+        .contains("KeyManagerImpl");
   }
 
   @Test
@@ -196,7 +196,7 @@ public class RegistryTest {
   @Test
   public void testGetUntypedKeyManager_shouldWorkHmac() throws Exception {
     assertThat(Registry.getUntypedKeyManager(MacConfig.HMAC_TYPE_URL).getClass().toString())
-        .contains("HmacKeyManager");
+        .contains("KeyManagerImpl");
   }
 
   @Test
diff --git a/java/src/test/java/com/google/crypto/tink/mac/HmacKeyManagerTest.java b/java/src/test/java/com/google/crypto/tink/mac/HmacKeyManagerTest.java
index 69c78871b..fb1d28205 100644
--- a/java/src/test/java/com/google/crypto/tink/mac/HmacKeyManagerTest.java
+++ b/java/src/test/java/com/google/crypto/tink/mac/HmacKeyManagerTest.java
@@ -19,6 +19,9 @@ package com.google.crypto.tink.mac;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
+import com.google.crypto.tink.KeyManager;
+import com.google.crypto.tink.KeyManagerImpl;
+import com.google.crypto.tink.Mac;
 import com.google.crypto.tink.TestUtil;
 import com.google.crypto.tink.proto.HashType;
 import com.google.crypto.tink.proto.HmacKey;
@@ -38,16 +41,17 @@ import org.junit.runners.JUnit4;
 public class HmacKeyManagerTest {
   @Test
   public void testNewKeyMultipleTimes() throws Exception {
-    HmacKeyManager keyManager = new HmacKeyManager();
+    KeyManager<Mac> keyManager = new KeyManagerImpl<>(new HmacKeyManager(), Mac.class);
     HmacKeyFormat hmacKeyFormat = HmacKeyFormat.newBuilder()
         .setParams(HmacParams.newBuilder().setHash(HashType.SHA256).setTagSize(16).build())
         .setKeySize(32)
         .build();
     ByteString serialized = ByteString.copyFrom(hmacKeyFormat.toByteArray());
-    KeyTemplate keyTemplate = KeyTemplate.newBuilder()
-        .setTypeUrl(HmacKeyManager.TYPE_URL)
-        .setValue(serialized)
-        .build();
+    KeyTemplate keyTemplate =
+        KeyTemplate.newBuilder()
+            .setTypeUrl(new HmacKeyManager().getKeyType())
+            .setValue(serialized)
+            .build();
     // Calls newKey multiple times and make sure that we get different HmacKey each time.
     Set<String> keys = new TreeSet<String>();
     int numTests = 27;
@@ -69,12 +73,13 @@ public class HmacKeyManagerTest {
 
   @Test
   public void testNewKeyCorruptedFormat() throws Exception {
-    HmacKeyManager keyManager = new HmacKeyManager();
+    KeyManager<Mac> keyManager = new KeyManagerImpl<>(new HmacKeyManager(), Mac.class);
     ByteString serialized = ByteString.copyFrom(new byte[128]);
-    KeyTemplate keyTemplate = KeyTemplate.newBuilder()
-        .setTypeUrl(HmacKeyManager.TYPE_URL)
-        .setValue(serialized)
-        .build();
+    KeyTemplate keyTemplate =
+        KeyTemplate.newBuilder()
+            .setTypeUrl(new HmacKeyManager().getKeyType())
+            .setValue(serialized)
+            .build();
     try {
       keyManager.newKey(serialized);
       fail("Corrupted format, should have thrown exception");
diff --git a/java/src/test/java/com/google/crypto/tink/mac/MacKeyTemplatesTest.java b/java/src/test/java/com/google/crypto/tink/mac/MacKeyTemplatesTest.java
index 97c1d2647..be6976391 100644
--- a/java/src/test/java/com/google/crypto/tink/mac/MacKeyTemplatesTest.java
+++ b/java/src/test/java/com/google/crypto/tink/mac/MacKeyTemplatesTest.java
@@ -32,7 +32,7 @@ public class MacKeyTemplatesTest {
   @Test
   public void testHMAC_SHA256_128BITTAG() throws Exception {
     KeyTemplate template = MacKeyTemplates.HMAC_SHA256_128BITTAG;
-    assertEquals(HmacKeyManager.TYPE_URL, template.getTypeUrl());
+    assertEquals(new HmacKeyManager().getKeyType(), template.getTypeUrl());
     assertEquals(OutputPrefixType.TINK, template.getOutputPrefixType());
     HmacKeyFormat format = HmacKeyFormat.parseFrom(template.getValue());
 
@@ -44,7 +44,7 @@ public class MacKeyTemplatesTest {
   @Test
   public void testHMAC_SHA256_256BITTAG() throws Exception {
     KeyTemplate template = MacKeyTemplates.HMAC_SHA256_256BITTAG;
-    assertEquals(HmacKeyManager.TYPE_URL, template.getTypeUrl());
+    assertEquals(new HmacKeyManager().getKeyType(), template.getTypeUrl());
     assertEquals(OutputPrefixType.TINK, template.getOutputPrefixType());
     HmacKeyFormat format = HmacKeyFormat.parseFrom(template.getValue());
 
@@ -56,7 +56,7 @@ public class MacKeyTemplatesTest {
   @Test
   public void testHMAC_SHA512_256BITTAG() throws Exception {
     KeyTemplate template = MacKeyTemplates.HMAC_SHA512_256BITTAG;
-    assertEquals(HmacKeyManager.TYPE_URL, template.getTypeUrl());
+    assertEquals(new HmacKeyManager().getKeyType(), template.getTypeUrl());
     assertEquals(OutputPrefixType.TINK, template.getOutputPrefixType());
     HmacKeyFormat format = HmacKeyFormat.parseFrom(template.getValue());
 
@@ -68,7 +68,7 @@ public class MacKeyTemplatesTest {
   @Test
   public void testHMAC_SHA512_512BITTAG() throws Exception {
     KeyTemplate template = MacKeyTemplates.HMAC_SHA512_512BITTAG;
-    assertEquals(HmacKeyManager.TYPE_URL, template.getTypeUrl());
+    assertEquals(new HmacKeyManager().getKeyType(), template.getTypeUrl());
     assertEquals(OutputPrefixType.TINK, template.getOutputPrefixType());
     HmacKeyFormat format = HmacKeyFormat.parseFrom(template.getValue());
 
@@ -85,7 +85,7 @@ public class MacKeyTemplatesTest {
     int tagSize = 24;
     HashType hashType = HashType.SHA512;
     KeyTemplate template = MacKeyTemplates.createHmacKeyTemplate(keySize, tagSize, hashType);
-    assertEquals(HmacKeyManager.TYPE_URL, template.getTypeUrl());
+    assertEquals(new HmacKeyManager().getKeyType(), template.getTypeUrl());
     assertEquals(OutputPrefixType.TINK, template.getOutputPrefixType());
 
     HmacKeyFormat format = HmacKeyFormat.parseFrom(template.getValue());
-- 
GitLab