From 5541324416df601848bb7b7cd1b8f4b183bbcdfc Mon Sep 17 00:00:00 2001
From: tholenst <tholenst@google.com>
Date: Thu, 29 Aug 2019 06:17:45 -0700
Subject: [PATCH] Migrate the Ed25519 Sign Key Manager.

PiperOrigin-RevId: 266124911
---
 cc/signature/BUILD.bazel                      |  14 +--
 cc/signature/CMakeLists.txt                   |  12 +-
 cc/signature/ed25519_sign_key_manager.cc      | 105 ++++--------------
 cc/signature/ed25519_sign_key_manager.h       |  58 ++++++----
 cc/signature/ed25519_sign_key_manager_test.cc |  65 +++++++----
 cc/signature/ed25519_verify_key_manager.cc    |  36 +-----
 cc/signature/ed25519_verify_key_manager.h     |  46 ++++----
 .../ed25519_verify_key_manager_test.cc        |  52 +++++----
 cc/signature/signature_config.cc              |   6 +-
 cc/signature/signature_key_templates_test.cc  |  11 +-
 10 files changed, 183 insertions(+), 222 deletions(-)

diff --git a/cc/signature/BUILD.bazel b/cc/signature/BUILD.bazel
index e598441cb..75afe81d5 100644
--- a/cc/signature/BUILD.bazel
+++ b/cc/signature/BUILD.bazel
@@ -155,11 +155,11 @@ cc_library(
     strip_include_prefix = "/cc",
     deps = [
         ":ed25519_verify_key_manager",
-        "//cc:key_manager",
-        "//cc:key_manager_base",
+        "//cc:core/private_key_type_manager",
         "//cc:public_key_sign",
         "//cc/subtle:ed25519_sign_boringssl",
         "//cc/subtle:subtle_util_boringssl",
+        "//cc/util:constants",
         "//cc/util:enums",
         "//cc/util:errors",
         "//cc/util:protobuf_helper",
@@ -167,8 +167,6 @@ cc_library(
         "//cc/util:statusor",
         "//cc/util:validation",
         "//proto:ed25519_cc_proto",
-        "//proto:empty_cc_proto",
-        "//proto:tink_cc_proto",
         "@com_google_absl//absl/memory",
         "@com_google_absl//absl/strings",
     ],
@@ -181,11 +179,11 @@ cc_library(
     include_prefix = "tink",
     strip_include_prefix = "/cc",
     deps = [
-        "//cc:key_manager",
-        "//cc:key_manager_base",
+        "//cc:core/key_type_manager",
         "//cc:public_key_verify",
         "//cc/subtle:ed25519_verify_boringssl",
         "//cc/subtle:subtle_util_boringssl",
+        "//cc/util:constants",
         "//cc/util:errors",
         "//cc/util:protobuf_helper",
         "//cc/util:status",
@@ -456,6 +454,7 @@ cc_test(
     deps = [
         ":ed25519_sign_key_manager",
         ":ed25519_verify_key_manager",
+        "//cc:core/key_manager_impl",
         "//cc:public_key_sign",
         "//cc:public_key_verify",
         "//cc:registry",
@@ -544,6 +543,7 @@ cc_test(
         ":ed25519_sign_key_manager",
         ":ed25519_verify_key_manager",
         ":signature_key_templates",
+        "//cc:core/private_key_manager_impl",
         "//cc:public_key_sign",
         "//cc:registry",
         "//cc/aead:aead_key_templates",
@@ -555,7 +555,6 @@ cc_test(
         "//proto:aes_eax_cc_proto",
         "//proto:common_cc_proto",
         "//proto:ed25519_cc_proto",
-        "//proto:empty_cc_proto",
         "//proto:tink_cc_proto",
         "@com_google_googletest//:gtest_main",
     ],
@@ -644,6 +643,7 @@ cc_test(
     deps = [
         ":ecdsa_sign_key_manager",
         ":ed25519_sign_key_manager",
+        ":ed25519_verify_key_manager",
         ":rsa_ssa_pkcs1_sign_key_manager",
         ":rsa_ssa_pss_sign_key_manager",
         ":signature_key_templates",
diff --git a/cc/signature/CMakeLists.txt b/cc/signature/CMakeLists.txt
index 0b6751669..9dd65892d 100644
--- a/cc/signature/CMakeLists.txt
+++ b/cc/signature/CMakeLists.txt
@@ -136,11 +136,11 @@ tink_cc_library(
     ed25519_sign_key_manager.h
   DEPS
     tink::signature::ed25519_verify_key_manager
-    tink::core::key_manager
-    tink::core::key_manager_base
+    tink::core::private_key_type_manager
     tink::core::public_key_sign
     tink::subtle::ed25519_sign_boringssl
     tink::subtle::subtle_util_boringssl
+    tink::util::constants
     tink::util::enums
     tink::util::errors
     tink::util::protobuf_helper
@@ -148,8 +148,6 @@ tink_cc_library(
     tink::util::statusor
     tink::util::validation
     tink::proto::ed25519_cc_proto
-    tink::proto::empty_cc_proto
-    tink::proto::tink_cc_proto
     absl::memory
     absl::strings
 )
@@ -160,11 +158,11 @@ tink_cc_library(
     ed25519_verify_key_manager.cc
     ed25519_verify_key_manager.h
   DEPS
-    tink::core::key_manager
-    tink::core::key_manager_base
+    tink::core::key_type_manager
     tink::core::public_key_verify
     tink::subtle::ed25519_verify_boringssl
     tink::subtle::subtle_util_boringssl
+    tink::util::constants
     tink::util::errors
     tink::util::protobuf_helper
     tink::util::status
@@ -397,6 +395,7 @@ tink_cc_test(
   DEPS
     tink::signature::ed25519_sign_key_manager
     tink::signature::ed25519_verify_key_manager
+    tink::core::key_manager_impl
     tink::core::public_key_sign
     tink::core::public_key_verify
     tink::core::registry
@@ -473,6 +472,7 @@ tink_cc_test(
     tink::signature::ed25519_sign_key_manager
     tink::signature::ed25519_verify_key_manager
     tink::signature::signature_key_templates
+    tink::core::private_key_manager_impl
     tink::core::public_key_sign
     tink::core::registry
     tink::aead::aead_key_templates
diff --git a/cc/signature/ed25519_sign_key_manager.cc b/cc/signature/ed25519_sign_key_manager.cc
index 9b9d27b65..9e78b4ecb 100644
--- a/cc/signature/ed25519_sign_key_manager.cc
+++ b/cc/signature/ed25519_sign_key_manager.cc
@@ -18,8 +18,6 @@
 
 #include "absl/memory/memory.h"
 #include "absl/strings/string_view.h"
-#include "tink/core/key_manager_base.h"
-#include "tink/key_manager.h"
 #include "tink/public_key_sign.h"
 #include "tink/signature/ed25519_verify_key_manager.h"
 #include "tink/subtle/ed25519_sign_boringssl.h"
@@ -31,117 +29,54 @@
 #include "tink/util/statusor.h"
 #include "tink/util/validation.h"
 #include "proto/ed25519.pb.h"
-#include "proto/tink.pb.h"
 
 namespace crypto {
 namespace tink {
 
 using crypto::tink::util::Status;
 using crypto::tink::util::StatusOr;
-using google::crypto::tink::Ed25519PrivateKey;
 using google::crypto::tink::Ed25519KeyFormat;
-using google::crypto::tink::KeyData;
-
-class Ed25519PrivateKeyFactory
-    : public PrivateKeyFactory,
-      public KeyFactoryBase<Ed25519PrivateKey, Ed25519KeyFormat> {
- public:
-  Ed25519PrivateKeyFactory() {}
-
-  KeyData::KeyMaterialType key_material_type() const override {
-    return KeyData::ASYMMETRIC_PRIVATE;
-  }
-
-  // Returns KeyData proto that contains Ed25519PublicKey
-  // extracted from the given serialized_private_key, which must contain
-  // Ed25519PrivateKey-proto.
-  crypto::tink::util::StatusOr<std::unique_ptr<google::crypto::tink::KeyData>>
-  GetPublicKeyData(absl::string_view serialized_private_key) const override;
-
- protected:
-  StatusOr<std::unique_ptr<Ed25519PrivateKey>> NewKeyFromFormat(
-      const Ed25519KeyFormat& unused) const override;
-};
+using google::crypto::tink::Ed25519PrivateKey;
 
-StatusOr<std::unique_ptr<Ed25519PrivateKey>>
-Ed25519PrivateKeyFactory::NewKeyFromFormat(
-    const Ed25519KeyFormat& unused) const {
+StatusOr<Ed25519PrivateKey> Ed25519SignKeyManager::CreateKey(
+    const Ed25519KeyFormat& key_format) const {
   auto key = subtle::SubtleUtilBoringSSL::GetNewEd25519Key();
 
-  // Build Ed25519PrivateKey.
-  std::unique_ptr<Ed25519PrivateKey> ed25519_private_key(
-      new Ed25519PrivateKey());
-  ed25519_private_key->set_version(Ed25519SignKeyManager::kVersion);
-  ed25519_private_key->set_key_value(key->private_key);
+  Ed25519PrivateKey ed25519_private_key;
+  ed25519_private_key.set_version(get_version());
+  ed25519_private_key.set_key_value(key->private_key);
 
   // Build Ed25519PublicKey.
-  auto ed25519_public_key = ed25519_private_key->mutable_public_key();
-  ed25519_public_key->set_version(Ed25519SignKeyManager::kVersion);
+  auto ed25519_public_key = ed25519_private_key.mutable_public_key();
+  ed25519_public_key->set_version(get_version());
   ed25519_public_key->set_key_value(key->public_key);
 
-  return absl::implicit_cast<StatusOr<std::unique_ptr<Ed25519PrivateKey>>>(
-      std::move(ed25519_private_key));
-}
-
-StatusOr<std::unique_ptr<KeyData>> Ed25519PrivateKeyFactory::GetPublicKeyData(
-    absl::string_view serialized_private_key) const {
-  Ed25519PrivateKey private_key;
-  if (!private_key.ParseFromString(std::string(serialized_private_key))) {
-    return Status(
-        util::error::INVALID_ARGUMENT,
-        absl::StrCat("Could not parse the passed string as proto '",
-                     Ed25519VerifyKeyManager::static_key_type(), "'."));
-    return util::Status::OK;
-  }
-  auto status = Ed25519SignKeyManager::Validate(private_key);
-  if (!status.ok()) return status;
-  auto key_data = absl::make_unique<KeyData>();
-  key_data->set_type_url(Ed25519VerifyKeyManager::static_key_type());
-  key_data->set_value(private_key.public_key().SerializeAsString());
-  key_data->set_key_material_type(KeyData::ASYMMETRIC_PUBLIC);
-  return std::move(key_data);
+  return ed25519_private_key;
 }
 
-constexpr uint32_t Ed25519SignKeyManager::kVersion;
-
-Ed25519SignKeyManager::Ed25519SignKeyManager()
-    : key_factory_(absl::make_unique<Ed25519PrivateKeyFactory>()) {}
-
-const KeyFactory& Ed25519SignKeyManager::get_key_factory() const {
-  return *key_factory_;
-}
-
-uint32_t Ed25519SignKeyManager::get_version() const { return kVersion; }
-
 StatusOr<std::unique_ptr<PublicKeySign>>
-Ed25519SignKeyManager::GetPrimitiveFromKey(
-    const Ed25519PrivateKey& ed25519_private_key) const {
-  Status status = Validate(ed25519_private_key);
-  if (!status.ok()) return status;
-
+Ed25519SignKeyManager::PublicKeySignFactory::Create(
+    const Ed25519PrivateKey& private_key) const {
   // BoringSSL expects a 64-byte private key which contains the public key as a
   // suffix.
-  std::string sk = ed25519_private_key.key_value() +
-              ed25519_private_key.public_key().key_value();
-
-  auto ed25519_result = subtle::Ed25519SignBoringSsl::New(sk);
-  if (!ed25519_result.ok()) return ed25519_result.status();
+  std::string sk = private_key.key_value() + private_key.public_key().key_value();
 
-  std::unique_ptr<PublicKeySign> ed25519(ed25519_result.ValueOrDie().release());
-  return std::move(ed25519);
+  return subtle::Ed25519SignBoringSsl::New(sk);
 }
 
-// static
-Status Ed25519SignKeyManager::Validate(const Ed25519PrivateKey& key) {
-  Status status = ValidateVersion(key.version(), kVersion);
+Status Ed25519SignKeyManager::ValidateKey(const Ed25519PrivateKey& key) const {
+  Status status = ValidateVersion(key.version(), get_version());
   if (!status.ok()) return status;
-
   if (key.key_value().length() != 32) {
     return Status(util::error::INVALID_ARGUMENT,
                   "The ED25519 private key must be 32-bytes long.");
   }
+  return Ed25519VerifyKeyManager().ValidateKey(key.public_key());
+}
 
-  return Ed25519VerifyKeyManager::Validate(key.public_key());
+Status Ed25519SignKeyManager::ValidateKeyFormat(
+    const Ed25519KeyFormat& key_format) const {
+  return util::OkStatus();
 }
 
 }  // namespace tink
diff --git a/cc/signature/ed25519_sign_key_manager.h b/cc/signature/ed25519_sign_key_manager.h
index 7e62a1fd6..c94267fa7 100644
--- a/cc/signature/ed25519_sign_key_manager.h
+++ b/cc/signature/ed25519_sign_key_manager.h
@@ -20,48 +20,62 @@
 #include <vector>
 
 #include "absl/strings/string_view.h"
-#include "tink/core/key_manager_base.h"
-#include "tink/key_manager.h"
+#include "tink/core/private_key_type_manager.h"
 #include "tink/public_key_sign.h"
+#include "tink/util/constants.h"
 #include "tink/util/errors.h"
 #include "tink/util/protobuf_helper.h"
 #include "tink/util/status.h"
 #include "tink/util/statusor.h"
 #include "proto/ed25519.pb.h"
-#include "proto/tink.pb.h"
 
 namespace crypto {
 namespace tink {
 
 class Ed25519SignKeyManager
-    : public KeyManagerBase<PublicKeySign,
-                            google::crypto::tink::Ed25519PrivateKey> {
+    : public PrivateKeyTypeManager<google::crypto::tink::Ed25519PrivateKey,
+                                   google::crypto::tink::Ed25519KeyFormat,
+                                   google::crypto::tink::Ed25519PublicKey,
+                                   List<PublicKeySign>> {
  public:
-  static constexpr uint32_t kVersion = 0;
+  class PublicKeySignFactory : public PrimitiveFactory<PublicKeySign> {
+    crypto::tink::util::StatusOr<std::unique_ptr<PublicKeySign>> Create(
+        const google::crypto::tink::Ed25519PrivateKey& private_key)
+        const override;
+  };
 
-  Ed25519SignKeyManager();
+  Ed25519SignKeyManager()
+      : PrivateKeyTypeManager(absl::make_unique<PublicKeySignFactory>()) {}
 
-  // Returns the version of this key manager.
-  uint32_t get_version() const override;
+  uint32_t get_version() const override { return 0; }
 
-  // Returns a factory that generates keys of the key type
-  // handled by this manager.
-  const KeyFactory& get_key_factory() const override;
+  google::crypto::tink::KeyData::KeyMaterialType key_material_type()
+      const override {
+    return google::crypto::tink::KeyData::ASYMMETRIC_PRIVATE;
+  }
 
-  ~Ed25519SignKeyManager() override {}
+  const std::string& get_key_type() const override { return key_type_; }
 
- protected:
-  crypto::tink::util::StatusOr<std::unique_ptr<PublicKeySign>>
-  GetPrimitiveFromKey(const google::crypto::tink::Ed25519PrivateKey&
-                          ed25519_private_key) const override;
+  crypto::tink::util::Status ValidateKey(
+      const google::crypto::tink::Ed25519PrivateKey& key) const override;
 
- private:
-  friend class Ed25519PrivateKeyFactory;
+  crypto::tink::util::Status ValidateKeyFormat(
+      const google::crypto::tink::Ed25519KeyFormat& key_format) const override;
+
+  crypto::tink::util::StatusOr<google::crypto::tink::Ed25519PrivateKey>
+  CreateKey(
+      const google::crypto::tink::Ed25519KeyFormat& key_format) const override;
 
-  std::unique_ptr<KeyFactory> key_factory_;
+  crypto::tink::util::StatusOr<google::crypto::tink::Ed25519PublicKey>
+  GetPublicKey(const google::crypto::tink::Ed25519PrivateKey& private_key)
+      const override {
+    return private_key.public_key();
+  }
 
-  static crypto::tink::util::Status Validate(
-      const google::crypto::tink::Ed25519PrivateKey& key);
+ private:
+  const std::string key_type_ =
+      absl::StrCat(kTypeGoogleapisCom,
+                   google::crypto::tink::Ed25519PrivateKey().GetTypeName());
 };
 
 }  // namespace tink
diff --git a/cc/signature/ed25519_sign_key_manager_test.cc b/cc/signature/ed25519_sign_key_manager_test.cc
index 36c4da86f..35178ac81 100644
--- a/cc/signature/ed25519_sign_key_manager_test.cc
+++ b/cc/signature/ed25519_sign_key_manager_test.cc
@@ -19,6 +19,7 @@
 #include "gtest/gtest.h"
 #include "tink/aead/aead_key_templates.h"
 #include "tink/aead/aes_gcm_key_manager.h"
+#include "tink/core/private_key_manager_impl.h"
 #include "tink/public_key_sign.h"
 #include "tink/registry.h"
 #include "tink/signature/ed25519_verify_key_manager.h"
@@ -50,22 +51,28 @@ class Ed25519SignKeyManagerTest : public ::testing::Test {
 };
 
 TEST_F(Ed25519SignKeyManagerTest, testBasic) {
-  Ed25519SignKeyManager key_manager;
+  Ed25519SignKeyManager sign_key_type_manager;
+  Ed25519VerifyKeyManager verify_key_type_manager;
+  auto key_manager = internal::MakePrivateKeyManager<PublicKeySign>(
+      &sign_key_type_manager, &verify_key_type_manager);
 
-  EXPECT_EQ(0, key_manager.get_version());
+  EXPECT_EQ(0, key_manager->get_version());
   EXPECT_EQ("type.googleapis.com/google.crypto.tink.Ed25519PrivateKey",
-            key_manager.get_key_type());
-  EXPECT_TRUE(key_manager.DoesSupport(key_manager.get_key_type()));
+            key_manager->get_key_type());
+  EXPECT_TRUE(key_manager->DoesSupport(key_manager->get_key_type()));
 }
 
 TEST_F(Ed25519SignKeyManagerTest, testKeyDataErrors) {
-  Ed25519SignKeyManager key_manager;
+  Ed25519SignKeyManager sign_key_type_manager;
+  Ed25519VerifyKeyManager verify_key_type_manager;
+  auto key_manager = internal::MakePrivateKeyManager<PublicKeySign>(
+      &sign_key_type_manager, &verify_key_type_manager);
 
   {  // Bad key type.
     KeyData key_data;
     std::string bad_key_type = "type.googleapis.com/google.crypto.tink.SomeOtherKey";
     key_data.set_type_url(bad_key_type);
-    auto result = key_manager.GetPrimitive(key_data);
+    auto result = key_manager->GetPrimitive(key_data);
     EXPECT_FALSE(result.ok());
     EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code());
     EXPECT_PRED_FORMAT2(testing::IsSubstring, "not supported",
@@ -78,7 +85,7 @@ TEST_F(Ed25519SignKeyManagerTest, testKeyDataErrors) {
     KeyData key_data;
     key_data.set_type_url(ed25519_sign_key_type_);
     key_data.set_value("some bad serialized proto");
-    auto result = key_manager.GetPrimitive(key_data);
+    auto result = key_manager->GetPrimitive(key_data);
     EXPECT_FALSE(result.ok());
     EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code());
     EXPECT_PRED_FORMAT2(testing::IsSubstring, "not parse",
@@ -91,7 +98,7 @@ TEST_F(Ed25519SignKeyManagerTest, testKeyDataErrors) {
     key.set_version(1);
     key_data.set_type_url(ed25519_sign_key_type_);
     key_data.set_value(key.SerializeAsString());
-    auto result = key_manager.GetPrimitive(key_data);
+    auto result = key_manager->GetPrimitive(key_data);
     EXPECT_FALSE(result.ok());
     EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code());
     EXPECT_PRED_FORMAT2(testing::IsSubstring, "version",
@@ -100,11 +107,14 @@ TEST_F(Ed25519SignKeyManagerTest, testKeyDataErrors) {
 }
 
 TEST_F(Ed25519SignKeyManagerTest, testKeyMessageErrors) {
-  Ed25519SignKeyManager key_manager;
+  Ed25519SignKeyManager sign_key_type_manager;
+  Ed25519VerifyKeyManager verify_key_type_manager;
+  auto key_manager = internal::MakePrivateKeyManager<PublicKeySign>(
+      &sign_key_type_manager, &verify_key_type_manager);
 
   {  // Bad protobuffer.
     AesEaxKey key;
-    auto result = key_manager.GetPrimitive(key);
+    auto result = key_manager->GetPrimitive(key);
     EXPECT_FALSE(result.ok());
     EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code());
     EXPECT_PRED_FORMAT2(testing::IsSubstring, "AesEaxKey",
@@ -116,11 +126,17 @@ TEST_F(Ed25519SignKeyManagerTest, testKeyMessageErrors) {
 
 TEST_F(Ed25519SignKeyManagerTest, testPrimitives) {
   std::string message = "some message to sign";
-  Ed25519SignKeyManager sign_key_manager;
+  Ed25519SignKeyManager sign_key_type_manager;
+  Ed25519VerifyKeyManager verify_key_type_manager;
+  auto sign_key_manager = internal::MakePrivateKeyManager<PublicKeySign>(
+      &sign_key_type_manager, &verify_key_type_manager);
+  auto verify_key_manager =
+      internal::MakeKeyManager<PublicKeyVerify>(&verify_key_type_manager);
+
   Ed25519PrivateKey key = test::GetEd25519TestPrivateKey();
 
   {  // Using Key proto.
-    auto result = sign_key_manager.GetPrimitive(key);
+    auto result = sign_key_manager->GetPrimitive(key);
     EXPECT_TRUE(result.ok()) << result.status();
     auto sign = std::move(result.ValueOrDie());
     auto signing_result = sign->Sign(message);
@@ -131,7 +147,7 @@ TEST_F(Ed25519SignKeyManagerTest, testPrimitives) {
     KeyData key_data;
     key_data.set_type_url(ed25519_sign_key_type_);
     key_data.set_value(key.SerializeAsString());
-    auto result = sign_key_manager.GetPrimitive(key_data);
+    auto result = sign_key_manager->GetPrimitive(key_data);
     EXPECT_TRUE(result.ok()) << result.status();
     auto sign = std::move(result.ValueOrDie());
     auto signing_result = sign->Sign(message);
@@ -140,9 +156,12 @@ TEST_F(Ed25519SignKeyManagerTest, testPrimitives) {
 }
 
 TEST_F(Ed25519SignKeyManagerTest, testPublicKeyExtraction) {
-  Ed25519SignKeyManager key_manager;
+  Ed25519SignKeyManager sign_key_type_manager;
+  Ed25519VerifyKeyManager verify_key_type_manager;
+  auto key_manager = internal::MakePrivateKeyManager<PublicKeySign>(
+      &sign_key_type_manager, &verify_key_type_manager);
   auto private_key_factory =
-      dynamic_cast<const PrivateKeyFactory*>(&(key_manager.get_key_factory()));
+      dynamic_cast<const PrivateKeyFactory*>(&(key_manager->get_key_factory()));
   ASSERT_NE(private_key_factory, nullptr);
 
   auto new_key_result =
@@ -154,7 +173,7 @@ TEST_F(Ed25519SignKeyManagerTest, testPublicKeyExtraction) {
       private_key_factory->GetPublicKeyData(new_key->SerializeAsString());
   EXPECT_TRUE(public_key_data_result.ok()) << public_key_data_result.status();
   auto public_key_data = std::move(public_key_data_result.ValueOrDie());
-  EXPECT_EQ(Ed25519VerifyKeyManager::static_key_type(),
+  EXPECT_EQ(Ed25519VerifyKeyManager().get_key_type(),
             public_key_data->type_url());
   EXPECT_EQ(KeyData::ASYMMETRIC_PUBLIC, public_key_data->key_material_type());
   EXPECT_EQ(new_key->public_key().SerializeAsString(),
@@ -162,9 +181,12 @@ TEST_F(Ed25519SignKeyManagerTest, testPublicKeyExtraction) {
 }
 
 TEST_F(Ed25519SignKeyManagerTest, testPublicKeyExtractionErrors) {
-  Ed25519SignKeyManager key_manager;
+  Ed25519SignKeyManager sign_key_type_manager;
+  Ed25519VerifyKeyManager verify_key_type_manager;
+  auto key_manager = internal::MakePrivateKeyManager<PublicKeySign>(
+      &sign_key_type_manager, &verify_key_type_manager);
   auto private_key_factory =
-      dynamic_cast<const PrivateKeyFactory*>(&(key_manager.get_key_factory()));
+      dynamic_cast<const PrivateKeyFactory*>(&(key_manager->get_key_factory()));
   ASSERT_NE(private_key_factory, nullptr);
 
   auto public_key_data_result = private_key_factory->GetPublicKeyData(
@@ -175,8 +197,11 @@ TEST_F(Ed25519SignKeyManagerTest, testPublicKeyExtractionErrors) {
 }
 
 TEST_F(Ed25519SignKeyManagerTest, testNewKey) {
-  Ed25519SignKeyManager key_manager;
-  const KeyFactory& key_factory = key_manager.get_key_factory();
+  Ed25519SignKeyManager sign_key_type_manager;
+  Ed25519VerifyKeyManager verify_key_type_manager;
+  auto key_manager = internal::MakePrivateKeyManager<PublicKeySign>(
+      &sign_key_type_manager, &verify_key_type_manager);
+  const KeyFactory& key_factory = key_manager->get_key_factory();
   Ed25519KeyFormat key_format;
   auto result = key_factory.NewKey(key_format);
   EXPECT_TRUE(result.ok());
diff --git a/cc/signature/ed25519_verify_key_manager.cc b/cc/signature/ed25519_verify_key_manager.cc
index 52abae06a..30b5d9bbc 100644
--- a/cc/signature/ed25519_verify_key_manager.cc
+++ b/cc/signature/ed25519_verify_key_manager.cc
@@ -17,7 +17,6 @@
 #include "tink/signature/ed25519_verify_key_manager.h"
 
 #include "absl/strings/string_view.h"
-#include "tink/key_manager.h"
 #include "tink/public_key_verify.h"
 #include "tink/subtle/ed25519_verify_boringssl.h"
 #include "tink/subtle/subtle_util_boringssl.h"
@@ -35,45 +34,20 @@ using crypto::tink::util::Status;
 using crypto::tink::util::StatusOr;
 using google::crypto::tink::Ed25519PublicKey;
 
-constexpr uint32_t Ed25519VerifyKeyManager::kVersion;
-
-Ed25519VerifyKeyManager::Ed25519VerifyKeyManager()
-    : key_factory_(KeyFactory::AlwaysFailingFactory(
-          util::Status(util::error::UNIMPLEMENTED,
-                       "Operation not supported for public keys, "
-                       "please use the Ed25519SignKeyManager."))) {}
-
-const KeyFactory& Ed25519VerifyKeyManager::get_key_factory() const {
-  return *key_factory_;
-}
-
-uint32_t Ed25519VerifyKeyManager::get_version() const { return kVersion; }
-
 StatusOr<std::unique_ptr<PublicKeyVerify>>
-Ed25519VerifyKeyManager::GetPrimitiveFromKey(
-    const Ed25519PublicKey& ed25519_public_key) const {
-  Status status = Validate(ed25519_public_key);
-  if (!status.ok()) return status;
-
-  auto ed25519_result =
-      subtle::Ed25519VerifyBoringSsl::New(ed25519_public_key.key_value());
-  if (!ed25519_result.ok()) return ed25519_result.status();
-
-  std::unique_ptr<PublicKeyVerify> ed25519(
-      ed25519_result.ValueOrDie().release());
-  return std::move(ed25519);
+Ed25519VerifyKeyManager::PublicKeyVerifyFactory::Create(
+    const Ed25519PublicKey& public_key) const {
+  return subtle::Ed25519VerifyBoringSsl::New(public_key.key_value());
 }
 
-// static
-Status Ed25519VerifyKeyManager::Validate(const Ed25519PublicKey& key) {
-  Status status = ValidateVersion(key.version(), kVersion);
+Status Ed25519VerifyKeyManager::ValidateKey(const Ed25519PublicKey& key) const {
+  Status status = ValidateVersion(key.version(), get_version());
   if (!status.ok()) return status;
 
   if (key.key_value().length() != 32) {
     return Status(util::error::INVALID_ARGUMENT,
                   "The ED25519 public key must be 32-bytes long.");
   }
-
   return Status::OK;
 }
 
diff --git a/cc/signature/ed25519_verify_key_manager.h b/cc/signature/ed25519_verify_key_manager.h
index 3cacbec9c..2fbaf6a81 100644
--- a/cc/signature/ed25519_verify_key_manager.h
+++ b/cc/signature/ed25519_verify_key_manager.h
@@ -20,9 +20,9 @@
 #include <vector>
 
 #include "absl/strings/string_view.h"
-#include "tink/core/key_manager_base.h"
-#include "tink/key_manager.h"
+#include "tink/core/key_type_manager.h"
 #include "tink/public_key_verify.h"
+#include "tink/util/constants.h"
 #include "tink/util/errors.h"
 #include "tink/util/protobuf_helper.h"
 #include "tink/util/status.h"
@@ -33,36 +33,34 @@ namespace crypto {
 namespace tink {
 
 class Ed25519VerifyKeyManager
-    : public KeyManagerBase<PublicKeyVerify,
-                            google::crypto::tink::Ed25519PublicKey> {
+    : public KeyTypeManager<google::crypto::tink::Ed25519PublicKey, void,
+                            List<PublicKeyVerify>> {
  public:
-  static constexpr uint32_t kVersion = 0;
+  class PublicKeyVerifyFactory : public PrimitiveFactory<PublicKeyVerify> {
+    crypto::tink::util::StatusOr<std::unique_ptr<PublicKeyVerify>> Create(
+        const google::crypto::tink::Ed25519PublicKey& ecdsa_public_key)
+        const override;
+  };
 
-  Ed25519VerifyKeyManager();
+  Ed25519VerifyKeyManager()
+      : KeyTypeManager(absl::make_unique<PublicKeyVerifyFactory>()) {}
 
-  // Returns the version of this key manager.
-  uint32_t get_version() const override;
+  uint32_t get_version() const override { return 0; }
 
-  // Returns a factory that generates keys of the key type
-  // handled by this manager.
-  const KeyFactory& get_key_factory() const override;
+  google::crypto::tink::KeyData::KeyMaterialType key_material_type()
+      const override {
+    return google::crypto::tink::KeyData::ASYMMETRIC_PUBLIC;
+  }
 
-  ~Ed25519VerifyKeyManager() override {}
+  const std::string& get_key_type() const override { return key_type_; }
 
- protected:
-  crypto::tink::util::StatusOr<std::unique_ptr<PublicKeyVerify>>
-  GetPrimitiveFromKey(const google::crypto::tink::Ed25519PublicKey&
-                          ed25519_public_key) const override;
+  crypto::tink::util::Status ValidateKey(
+      const google::crypto::tink::Ed25519PublicKey& key) const override;
 
  private:
-  // Friends that re-use proto validation helpers.
-  friend class Ed25519PrivateKeyFactory;
-  friend class Ed25519SignKeyManager;
-
-  std::unique_ptr<KeyFactory> key_factory_;
-
-  static crypto::tink::util::Status Validate(
-      const google::crypto::tink::Ed25519PublicKey& key);
+  const std::string key_type_ =
+      absl::StrCat(kTypeGoogleapisCom,
+                   google::crypto::tink::Ed25519PublicKey().GetTypeName());
 };
 
 }  // namespace tink
diff --git a/cc/signature/ed25519_verify_key_manager_test.cc b/cc/signature/ed25519_verify_key_manager_test.cc
index 1629be082..b5d50aee5 100644
--- a/cc/signature/ed25519_verify_key_manager_test.cc
+++ b/cc/signature/ed25519_verify_key_manager_test.cc
@@ -17,6 +17,7 @@
 #include "tink/signature/ed25519_verify_key_manager.h"
 
 #include "gtest/gtest.h"
+#include "tink/core/key_manager_impl.h"
 #include "tink/public_key_sign.h"
 #include "tink/public_key_verify.h"
 #include "tink/registry.h"
@@ -48,22 +49,26 @@ class Ed25519VerifyKeyManagerTest : public ::testing::Test {
 };
 
 TEST_F(Ed25519VerifyKeyManagerTest, testBasic) {
-  Ed25519VerifyKeyManager key_manager;
+  Ed25519VerifyKeyManager key_type_manager;
+  auto key_manager =
+      internal::MakeKeyManager<PublicKeyVerify>(&key_type_manager);
 
-  EXPECT_EQ(0, key_manager.get_version());
+  EXPECT_EQ(0, key_manager->get_version());
   EXPECT_EQ("type.googleapis.com/google.crypto.tink.Ed25519PublicKey",
-            key_manager.get_key_type());
-  EXPECT_TRUE(key_manager.DoesSupport(key_manager.get_key_type()));
+            key_manager->get_key_type());
+  EXPECT_TRUE(key_manager->DoesSupport(key_manager->get_key_type()));
 }
 
 TEST_F(Ed25519VerifyKeyManagerTest, testKeyDataErrors) {
-  Ed25519VerifyKeyManager key_manager;
+  Ed25519VerifyKeyManager verify_key_type_manager;
+  auto key_manager =
+      internal::MakeKeyManager<PublicKeyVerify>(&verify_key_type_manager);
 
   {  // Bad key type.
     KeyData key_data;
     std::string bad_key_type = "type.googleapis.com/google.crypto.tink.SomeOtherKey";
     key_data.set_type_url(bad_key_type);
-    auto result = key_manager.GetPrimitive(key_data);
+    auto result = key_manager->GetPrimitive(key_data);
     EXPECT_FALSE(result.ok());
     EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code());
     EXPECT_PRED_FORMAT2(testing::IsSubstring, "not supported",
@@ -76,7 +81,7 @@ TEST_F(Ed25519VerifyKeyManagerTest, testKeyDataErrors) {
     KeyData key_data;
     key_data.set_type_url(ed25519_verify_key_type_);
     key_data.set_value("some bad serialized proto");
-    auto result = key_manager.GetPrimitive(key_data);
+    auto result = key_manager->GetPrimitive(key_data);
     EXPECT_FALSE(result.ok());
     EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code());
     EXPECT_PRED_FORMAT2(testing::IsSubstring, "not parse",
@@ -89,7 +94,7 @@ TEST_F(Ed25519VerifyKeyManagerTest, testKeyDataErrors) {
     key.set_version(1);
     key_data.set_type_url(ed25519_verify_key_type_);
     key_data.set_value(key.SerializeAsString());
-    auto result = key_manager.GetPrimitive(key_data);
+    auto result = key_manager->GetPrimitive(key_data);
     EXPECT_FALSE(result.ok());
     EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code());
     EXPECT_PRED_FORMAT2(testing::IsSubstring, "version",
@@ -98,11 +103,13 @@ TEST_F(Ed25519VerifyKeyManagerTest, testKeyDataErrors) {
 }
 
 TEST_F(Ed25519VerifyKeyManagerTest, testKeyMessageErrors) {
-  Ed25519VerifyKeyManager key_manager;
+  Ed25519VerifyKeyManager key_type_manager;
+  auto key_manager =
+      internal::MakeKeyManager<PublicKeyVerify>(&key_type_manager);
 
   {  // Bad protobuffer.
     AesEaxKey key;
-    auto result = key_manager.GetPrimitive(key);
+    auto result = key_manager->GetPrimitive(key);
     EXPECT_FALSE(result.ok());
     EXPECT_EQ(util::error::INVALID_ARGUMENT, result.status().error_code());
     EXPECT_PRED_FORMAT2(testing::IsSubstring, "AesEaxKey",
@@ -114,16 +121,21 @@ TEST_F(Ed25519VerifyKeyManagerTest, testKeyMessageErrors) {
 
 TEST_F(Ed25519VerifyKeyManagerTest, testPrimitives) {
   std::string message = "some message to sign";
-  Ed25519SignKeyManager sign_key_manager;
-  Ed25519VerifyKeyManager verify_key_manager;
+  Ed25519SignKeyManager sign_key_type_manager;
+  Ed25519VerifyKeyManager verify_key_type_manager;
+  auto sign_key_manager = internal::MakePrivateKeyManager<PublicKeySign>(
+      &sign_key_type_manager, &verify_key_type_manager);
+  auto verify_key_manager = internal::MakeKeyManager<PublicKeyVerify>(
+      &verify_key_type_manager);
+
   Ed25519PrivateKey private_key = test::GetEd25519TestPrivateKey();
   Ed25519PublicKey key = private_key.public_key();
   auto sign =
-      std::move(sign_key_manager.GetPrimitive(private_key).ValueOrDie());
+      std::move(sign_key_manager->GetPrimitive(private_key).ValueOrDie());
   std::string signature = sign->Sign(message).ValueOrDie();
 
   {  // Using Key proto.
-    auto result = verify_key_manager.GetPrimitive(key);
+    auto result = verify_key_manager->GetPrimitive(key);
     EXPECT_TRUE(result.ok()) << result.status();
     auto verify = std::move(result.ValueOrDie());
     auto verify_status = verify->Verify(signature, message);
@@ -134,7 +146,7 @@ TEST_F(Ed25519VerifyKeyManagerTest, testPrimitives) {
     KeyData key_data;
     key_data.set_type_url(ed25519_verify_key_type_);
     key_data.set_value(key.SerializeAsString());
-    auto result = verify_key_manager.GetPrimitive(key_data);
+    auto result = verify_key_manager->GetPrimitive(key_data);
     EXPECT_TRUE(result.ok()) << result.status();
     auto verify = std::move(result.ValueOrDie());
     auto verify_status = verify->Verify(signature, message);
@@ -143,14 +155,14 @@ TEST_F(Ed25519VerifyKeyManagerTest, testPrimitives) {
 }
 
 TEST_F(Ed25519VerifyKeyManagerTest, testNewKey) {
-  Ed25519VerifyKeyManager key_manager;
-  const KeyFactory& key_factory = key_manager.get_key_factory();
+  Ed25519VerifyKeyManager key_type_manager;
+  auto key_manager =
+      internal::MakeKeyManager<PublicKeyVerify>(&key_type_manager);
+  const KeyFactory& key_factory = key_manager->get_key_factory();
   Ed25519KeyFormat key_format;
   auto result = key_factory.NewKey(key_format);
   EXPECT_FALSE(result.ok());
-  EXPECT_PRED_FORMAT2(testing::IsSubstring,
-                      "Operation not supported for public keys, please use the "
-                      "Ed25519SignKeyManager.",
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "not supported",
                       result.status().error_message());
 }
 
diff --git a/cc/signature/signature_config.cc b/cc/signature/signature_config.cc
index 8ada0f648..70351cef6 100644
--- a/cc/signature/signature_config.cc
+++ b/cc/signature/signature_config.cc
@@ -53,10 +53,8 @@ util::Status SignatureConfig::Register() {
   if (!status.ok()) return status;
 
   // ED25519
-  status = Registry::RegisterKeyManager(
-      absl::make_unique<Ed25519SignKeyManager>(), true);
-  if (!status.ok()) return status;
-  status = Registry::RegisterKeyManager(
+  status = Registry::RegisterAsymmetricKeyManagers(
+      absl::make_unique<Ed25519SignKeyManager>(),
       absl::make_unique<Ed25519VerifyKeyManager>(), true);
   if (!status.ok()) return status;
 
diff --git a/cc/signature/signature_key_templates_test.cc b/cc/signature/signature_key_templates_test.cc
index 7499dfa9e..9d8cd5769 100644
--- a/cc/signature/signature_key_templates_test.cc
+++ b/cc/signature/signature_key_templates_test.cc
@@ -24,6 +24,7 @@
 #include "tink/signature/ecdsa_sign_key_manager.h"
 #include "tink/signature/ecdsa_verify_key_manager.h"
 #include "tink/signature/ed25519_sign_key_manager.h"
+#include "tink/signature/ed25519_verify_key_manager.h"
 #include "tink/signature/rsa_ssa_pkcs1_sign_key_manager.h"
 #include "tink/signature/rsa_ssa_pss_sign_key_manager.h"
 #include "tink/subtle/subtle_util_boringssl.h"
@@ -351,10 +352,14 @@ TEST(SignatureKeyTemplatesTest, KeyTemplatesWithEd25519) {
   EXPECT_EQ(&key_template, &key_template_2);
 
   // Check that the key manager works with the template.
-  Ed25519SignKeyManager key_manager;
-  EXPECT_EQ(key_manager.get_key_type(), key_template.type_url());
+  Ed25519SignKeyManager sign_key_type_manager;
+  Ed25519VerifyKeyManager verify_key_type_manager;
+  auto key_manager = internal::MakePrivateKeyManager<PublicKeySign>(
+      &sign_key_type_manager, &verify_key_type_manager);
+
+  EXPECT_EQ(key_manager->get_key_type(), key_template.type_url());
   Ed25519KeyFormat key_format;
-  auto new_key_result = key_manager.get_key_factory().NewKey(key_format);
+  auto new_key_result = key_manager->get_key_factory().NewKey(key_format);
   EXPECT_TRUE(new_key_result.ok()) << new_key_result.status();
 }
 
-- 
GitLab