Remove the "KeyManager" part of the implementation in EcdsaSign/VerifyKeyManager and register a LegacyKeyManagerImpl instead.

PiperOrigin-RevId: 592199947
Change-Id: I9b52d304a1e65438cf7b103e098210063a5867aa
diff --git a/src/main/java/com/google/crypto/tink/signature/BUILD.bazel b/src/main/java/com/google/crypto/tink/signature/BUILD.bazel
index f164cc6..3f2b11e 100644
--- a/src/main/java/com/google/crypto/tink/signature/BUILD.bazel
+++ b/src/main/java/com/google/crypto/tink/signature/BUILD.bazel
@@ -24,24 +24,6 @@
 )
 
 java_library(
-    name = "ecdsa_verify_key_manager",
-    srcs = ["EcdsaVerifyKeyManager.java"],
-    deps = [
-        "//proto:ecdsa_java_proto",
-        "//proto:tink_java_proto",
-        "//src/main/java/com/google/crypto/tink:public_key_verify",
-        "//src/main/java/com/google/crypto/tink/config/internal:tink_fips_util",
-        "//src/main/java/com/google/crypto/tink/internal:key_type_manager",
-        "//src/main/java/com/google/crypto/tink/internal:primitive_factory",
-        "//src/main/java/com/google/crypto/tink/signature/internal:sig_util",
-        "//src/main/java/com/google/crypto/tink/subtle:ecdsa_verify_jce",
-        "//src/main/java/com/google/crypto/tink/subtle:elliptic_curves",
-        "//src/main/java/com/google/crypto/tink/subtle:validators",
-        "@maven//:com_google_protobuf_protobuf_java",
-    ],
-)
-
-java_library(
     name = "signature_pem_keyset_reader",
     srcs = ["SignaturePemKeysetReader.java"],
     deps = [
@@ -85,27 +67,34 @@
     srcs = ["EcdsaSignKeyManager.java"],
     deps = [
         ":ecdsa_parameters",
+        ":ecdsa_private_key",
+        ":ecdsa_public_key",
         ":ecdsa_verify_key_manager",
         ":predefined_signature_parameters",
         "//proto:ecdsa_java_proto",
         "//proto:tink_java_proto",
+        "//src/main/java/com/google/crypto/tink:accesses_partial_key",
+        "//src/main/java/com/google/crypto/tink:insecure_secret_key_access",
+        "//src/main/java/com/google/crypto/tink:key_manager",
         "//src/main/java/com/google/crypto/tink:key_template",
         "//src/main/java/com/google/crypto/tink:parameters",
+        "//src/main/java/com/google/crypto/tink:private_key_manager",
         "//src/main/java/com/google/crypto/tink:public_key_sign",
-        "//src/main/java/com/google/crypto/tink:registry",
+        "//src/main/java/com/google/crypto/tink:public_key_verify",
         "//src/main/java/com/google/crypto/tink/config/internal:tink_fips_util",
-        "//src/main/java/com/google/crypto/tink/internal:key_type_manager",
+        "//src/main/java/com/google/crypto/tink/internal:key_manager_registry",
+        "//src/main/java/com/google/crypto/tink/internal:legacy_key_manager_impl",
+        "//src/main/java/com/google/crypto/tink/internal:mutable_key_creation_registry",
         "//src/main/java/com/google/crypto/tink/internal:mutable_parameters_registry",
-        "//src/main/java/com/google/crypto/tink/internal:primitive_factory",
-        "//src/main/java/com/google/crypto/tink/internal:private_key_type_manager",
+        "//src/main/java/com/google/crypto/tink/internal:mutable_primitive_registry",
+        "//src/main/java/com/google/crypto/tink/internal:primitive_constructor",
         "//src/main/java/com/google/crypto/tink/internal:tink_bug_exception",
         "//src/main/java/com/google/crypto/tink/signature/internal:ecdsa_proto_serialization",
-        "//src/main/java/com/google/crypto/tink/signature/internal:sig_util",
         "//src/main/java/com/google/crypto/tink/subtle:ecdsa_sign_jce",
+        "//src/main/java/com/google/crypto/tink/subtle:ecdsa_verify_jce",
         "//src/main/java/com/google/crypto/tink/subtle:elliptic_curves",
-        "//src/main/java/com/google/crypto/tink/subtle:selfkeytests_validators",
-        "//src/main/java/com/google/crypto/tink/subtle:validators",
-        "@maven//:com_google_protobuf_protobuf_java",
+        "//src/main/java/com/google/crypto/tink/util:secret_big_integer",
+        "@maven//:com_google_code_findbugs_jsr305",
     ],
 )
 
@@ -637,24 +626,6 @@
 )
 
 android_library(
-    name = "ecdsa_verify_key_manager-android",
-    srcs = ["EcdsaVerifyKeyManager.java"],
-    deps = [
-        "//proto:ecdsa_java_proto_lite",
-        "//proto:tink_java_proto_lite",
-        "//src/main/java/com/google/crypto/tink:public_key_verify-android",
-        "//src/main/java/com/google/crypto/tink/config/internal:tink_fips_util-android",
-        "//src/main/java/com/google/crypto/tink/internal:key_type_manager-android",
-        "//src/main/java/com/google/crypto/tink/internal:primitive_factory-android",
-        "//src/main/java/com/google/crypto/tink/signature/internal:sig_util-android",
-        "//src/main/java/com/google/crypto/tink/subtle:ecdsa_verify_jce-android",
-        "//src/main/java/com/google/crypto/tink/subtle:elliptic_curves-android",
-        "//src/main/java/com/google/crypto/tink/subtle:validators-android",
-        "@maven//:com_google_protobuf_protobuf_javalite",
-    ],
-)
-
-android_library(
     name = "signature_pem_keyset_reader-android",
     srcs = ["SignaturePemKeysetReader.java"],
     deps = [
@@ -698,27 +669,34 @@
     srcs = ["EcdsaSignKeyManager.java"],
     deps = [
         ":ecdsa_parameters-android",
+        ":ecdsa_private_key-android",
+        ":ecdsa_public_key-android",
         ":ecdsa_verify_key_manager-android",
         ":predefined_signature_parameters-android",
         "//proto:ecdsa_java_proto_lite",
         "//proto:tink_java_proto_lite",
+        "//src/main/java/com/google/crypto/tink:accesses_partial_key-android",
+        "//src/main/java/com/google/crypto/tink:insecure_secret_key_access-android",
+        "//src/main/java/com/google/crypto/tink:key_manager-android",
         "//src/main/java/com/google/crypto/tink:key_template-android",
         "//src/main/java/com/google/crypto/tink:parameters-android",
+        "//src/main/java/com/google/crypto/tink:private_key_manager-android",
         "//src/main/java/com/google/crypto/tink:public_key_sign-android",
-        "//src/main/java/com/google/crypto/tink:registry-android",
+        "//src/main/java/com/google/crypto/tink:public_key_verify-android",
         "//src/main/java/com/google/crypto/tink/config/internal:tink_fips_util-android",
-        "//src/main/java/com/google/crypto/tink/internal:key_type_manager-android",
+        "//src/main/java/com/google/crypto/tink/internal:key_manager_registry-android",
+        "//src/main/java/com/google/crypto/tink/internal:legacy_key_manager_impl-android",
+        "//src/main/java/com/google/crypto/tink/internal:mutable_key_creation_registry-android",
         "//src/main/java/com/google/crypto/tink/internal:mutable_parameters_registry-android",
-        "//src/main/java/com/google/crypto/tink/internal:primitive_factory-android",
-        "//src/main/java/com/google/crypto/tink/internal:private_key_type_manager-android",
+        "//src/main/java/com/google/crypto/tink/internal:mutable_primitive_registry-android",
+        "//src/main/java/com/google/crypto/tink/internal:primitive_constructor-android",
         "//src/main/java/com/google/crypto/tink/internal:tink_bug_exception-android",
         "//src/main/java/com/google/crypto/tink/signature/internal:ecdsa_proto_serialization-android",
-        "//src/main/java/com/google/crypto/tink/signature/internal:sig_util-android",
         "//src/main/java/com/google/crypto/tink/subtle:ecdsa_sign_jce-android",
+        "//src/main/java/com/google/crypto/tink/subtle:ecdsa_verify_jce-android",
         "//src/main/java/com/google/crypto/tink/subtle:elliptic_curves-android",
-        "//src/main/java/com/google/crypto/tink/subtle:selfkeytests_validators-android",
-        "//src/main/java/com/google/crypto/tink/subtle:validators-android",
-        "@maven//:com_google_protobuf_protobuf_javalite",
+        "//src/main/java/com/google/crypto/tink/util:secret_big_integer-android",
+        "@maven//:com_google_code_findbugs_jsr305",
     ],
 )
 
@@ -1251,3 +1229,13 @@
         "//src/main/java/com/google/crypto/tink/internal:tink_bug_exception",
     ],
 )
+
+android_library(
+    name = "ecdsa_verify_key_manager-android",
+    srcs = ["EcdsaVerifyKeyManager.java"],
+)
+
+java_library(
+    name = "ecdsa_verify_key_manager",
+    srcs = ["EcdsaVerifyKeyManager.java"],
+)
diff --git a/src/main/java/com/google/crypto/tink/signature/EcdsaSignKeyManager.java b/src/main/java/com/google/crypto/tink/signature/EcdsaSignKeyManager.java
index db139a9..110baef 100644
--- a/src/main/java/com/google/crypto/tink/signature/EcdsaSignKeyManager.java
+++ b/src/main/java/com/google/crypto/tink/signature/EcdsaSignKeyManager.java
@@ -18,149 +18,91 @@
 
 import static com.google.crypto.tink.internal.TinkBugException.exceptionIsBug;
 
+import com.google.crypto.tink.AccessesPartialKey;
+import com.google.crypto.tink.InsecureSecretKeyAccess;
+import com.google.crypto.tink.KeyManager;
 import com.google.crypto.tink.KeyTemplate;
 import com.google.crypto.tink.Parameters;
+import com.google.crypto.tink.PrivateKeyManager;
 import com.google.crypto.tink.PublicKeySign;
-import com.google.crypto.tink.Registry;
+import com.google.crypto.tink.PublicKeyVerify;
 import com.google.crypto.tink.config.internal.TinkFipsUtil;
-import com.google.crypto.tink.internal.KeyTypeManager;
+import com.google.crypto.tink.internal.KeyManagerRegistry;
+import com.google.crypto.tink.internal.LegacyKeyManagerImpl;
+import com.google.crypto.tink.internal.MutableKeyCreationRegistry;
 import com.google.crypto.tink.internal.MutableParametersRegistry;
-import com.google.crypto.tink.internal.PrimitiveFactory;
-import com.google.crypto.tink.internal.PrivateKeyTypeManager;
-import com.google.crypto.tink.proto.EcdsaKeyFormat;
-import com.google.crypto.tink.proto.EcdsaParams;
-import com.google.crypto.tink.proto.EcdsaPrivateKey;
-import com.google.crypto.tink.proto.EcdsaPublicKey;
+import com.google.crypto.tink.internal.MutablePrimitiveRegistry;
+import com.google.crypto.tink.internal.PrimitiveConstructor;
 import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
 import com.google.crypto.tink.signature.internal.EcdsaProtoSerialization;
-import com.google.crypto.tink.signature.internal.SigUtil;
 import com.google.crypto.tink.subtle.EcdsaSignJce;
+import com.google.crypto.tink.subtle.EcdsaVerifyJce;
 import com.google.crypto.tink.subtle.EllipticCurves;
-import com.google.crypto.tink.subtle.SelfKeyTestValidators;
-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.crypto.tink.util.SecretBigInteger;
 import java.security.GeneralSecurityException;
 import java.security.KeyPair;
 import java.security.interfaces.ECPrivateKey;
 import java.security.interfaces.ECPublicKey;
-import java.security.spec.ECPoint;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import javax.annotation.Nullable;
 
 /**
  * This key manager generates new {@code EcdsaPrivateKey} keys and produces new instances of {@code
  * EcdsaSignJce}.
  */
-public final class EcdsaSignKeyManager
-    extends PrivateKeyTypeManager<EcdsaPrivateKey, EcdsaPublicKey> {
-  EcdsaSignKeyManager() {
-    super(
-        EcdsaPrivateKey.class,
-        EcdsaPublicKey.class,
-        new PrimitiveFactory<PublicKeySign, EcdsaPrivateKey>(PublicKeySign.class) {
-          @Override
-          public PublicKeySign getPrimitive(EcdsaPrivateKey key) throws GeneralSecurityException {
-            ECPrivateKey privateKey =
-                EllipticCurves.getEcPrivateKey(
-                    SigUtil.toCurveType(key.getPublicKey().getParams().getCurve()),
-                    key.getKeyValue().toByteArray());
+public final class EcdsaSignKeyManager {
+  private static final PrimitiveConstructor<EcdsaPrivateKey, PublicKeySign>
+      PUBLIC_KEY_SIGN_PRIMITIVE_CONSTRUCTOR =
+          PrimitiveConstructor.create(
+              EcdsaSignJce::create, EcdsaPrivateKey.class, PublicKeySign.class);
 
-            ECPublicKey publicKey =
-                EllipticCurves.getEcPublicKey(
-                    SigUtil.toCurveType(key.getPublicKey().getParams().getCurve()),
-                    key.getPublicKey().getX().toByteArray(),
-                    key.getPublicKey().getY().toByteArray());
+  private static final PrimitiveConstructor<EcdsaPublicKey, PublicKeyVerify>
+      PUBLIC_KEY_VERIFY_PRIMITIVE_CONSTRUCTOR =
+          PrimitiveConstructor.create(
+              EcdsaVerifyJce::create, EcdsaPublicKey.class, PublicKeyVerify.class);
 
-            SelfKeyTestValidators.validateEcdsa(
-                privateKey,
-                publicKey,
-                SigUtil.toHashType(key.getPublicKey().getParams().getHashType()),
-                SigUtil.toEcdsaEncoding(key.getPublicKey().getParams().getEncoding()));
+  private static final PrivateKeyManager<PublicKeySign> legacyPrivateKeyManager =
+      LegacyKeyManagerImpl.createPrivateKeyManager(
+          getKeyType(), PublicKeySign.class, com.google.crypto.tink.proto.EcdsaPrivateKey.parser());
 
-            return new EcdsaSignJce(
-                privateKey,
-                SigUtil.toHashType(key.getPublicKey().getParams().getHashType()),
-                SigUtil.toEcdsaEncoding(key.getPublicKey().getParams().getEncoding()));
-          }
-        });
-  }
+  private static final KeyManager<PublicKeyVerify> legacyPublicKeyManager =
+      LegacyKeyManagerImpl.create(
+          EcdsaVerifyKeyManager.getKeyType(),
+          PublicKeyVerify.class,
+          KeyMaterialType.ASYMMETRIC_PUBLIC,
+          com.google.crypto.tink.proto.EcdsaPublicKey.parser());
 
-  @Override
-  public String getKeyType() {
+  static String getKeyType() {
     return "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey";
   }
 
-  @Override
-  public int getVersion() {
-    return 0;
-  }
+  @AccessesPartialKey
+  private static EcdsaPrivateKey createKey(
+      EcdsaParameters parameters, @Nullable Integer idRequirement) throws GeneralSecurityException {
+    KeyPair keyPair = EllipticCurves.generateKeyPair(parameters.getCurveType().toParameterSpec());
+    ECPublicKey pubKey = (ECPublicKey) keyPair.getPublic();
+    ECPrivateKey privKey = (ECPrivateKey) keyPair.getPrivate();
 
-  @Override
-  public EcdsaPublicKey getPublicKey(EcdsaPrivateKey key) throws GeneralSecurityException {
-    return key.getPublicKey();
-  }
-
-  @Override
-  public KeyMaterialType keyMaterialType() {
-    return KeyMaterialType.ASYMMETRIC_PRIVATE;
-  }
-
-  @Override
-  public EcdsaPrivateKey parseKey(ByteString byteString) throws InvalidProtocolBufferException {
-    return EcdsaPrivateKey.parseFrom(byteString, ExtensionRegistryLite.getEmptyRegistry());
-  }
-
-  @Override
-  public void validateKey(EcdsaPrivateKey privKey) throws GeneralSecurityException {
-    Validators.validateVersion(privKey.getVersion(), getVersion());
-    SigUtil.validateEcdsaParams(privKey.getPublicKey().getParams());
-  }
-
-  @Override
-  public KeyTypeManager.KeyFactory<EcdsaKeyFormat, EcdsaPrivateKey> keyFactory() {
-    return new KeyTypeManager.KeyFactory<EcdsaKeyFormat, EcdsaPrivateKey>(EcdsaKeyFormat.class) {
-      @Override
-      public void validateKeyFormat(EcdsaKeyFormat format) throws GeneralSecurityException {
-        SigUtil.validateEcdsaParams(format.getParams());
-      }
-
-      @Override
-      public EcdsaKeyFormat parseKeyFormat(ByteString byteString)
-          throws InvalidProtocolBufferException {
-        return EcdsaKeyFormat.parseFrom(byteString, ExtensionRegistryLite.getEmptyRegistry());
-      }
-
-      @Override
-      public EcdsaPrivateKey createKey(EcdsaKeyFormat format) throws GeneralSecurityException {
-        EcdsaParams ecdsaParams = format.getParams();
-        KeyPair keyPair =
-            EllipticCurves.generateKeyPair(SigUtil.toCurveType(ecdsaParams.getCurve()));
-        ECPublicKey pubKey = (ECPublicKey) keyPair.getPublic();
-        ECPrivateKey privKey = (ECPrivateKey) keyPair.getPrivate();
-        ECPoint w = pubKey.getW();
-
-        // Creates EcdsaPublicKey.
-        EcdsaPublicKey ecdsaPubKey =
-            EcdsaPublicKey.newBuilder()
-                .setVersion(getVersion())
-                .setParams(ecdsaParams)
-                .setX(ByteString.copyFrom(w.getAffineX().toByteArray()))
-                .setY(ByteString.copyFrom(w.getAffineY().toByteArray()))
-                .build();
-
-        // Creates EcdsaPrivateKey.
-        return EcdsaPrivateKey.newBuilder()
-            .setVersion(getVersion())
-            .setPublicKey(ecdsaPubKey)
-            .setKeyValue(ByteString.copyFrom(privKey.getS().toByteArray()))
+    EcdsaPublicKey publicKey =
+        EcdsaPublicKey.builder()
+            .setParameters(parameters)
+            .setIdRequirement(idRequirement)
+            .setPublicPoint(pubKey.getW())
             .build();
-      }
-    };
+
+    return EcdsaPrivateKey.builder()
+        .setPublicKey(publicKey)
+        .setPrivateValue(
+            SecretBigInteger.fromBigInteger(privKey.getS(), InsecureSecretKeyAccess.get()))
+        .build();
   }
 
+  @SuppressWarnings("InlineLambdaConstant") // We need a correct Object#equals in registration.
+  private static final MutableKeyCreationRegistry.KeyCreator<EcdsaParameters> KEY_CREATOR =
+      EcdsaSignKeyManager::createKey;
+
   private static Map<String, Parameters> namedParameters() throws GeneralSecurityException {
         Map<String, Parameters> result = new HashMap<>();
         result.put("ECDSA_P256", PredefinedSignatureParameters.ECDSA_P256);
@@ -208,20 +150,28 @@
         return Collections.unmodifiableMap(result);
   }
 
-  @Override
-  public TinkFipsUtil.AlgorithmFipsCompatibility fipsStatus() {
-    return TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_REQUIRES_BORINGCRYPTO;
-  };
-
   /**
    * Registers the {@link EcdsaSignKeyManager} and the {@link EcdsaVerifyKeyManager} with the
    * registry, so that the the Ecdsa-Keys can be used with Tink.
    */
   public static void registerPair(boolean newKeyAllowed) throws GeneralSecurityException {
-    Registry.registerAsymmetricKeyManagers(
-        new EcdsaSignKeyManager(), new EcdsaVerifyKeyManager(), newKeyAllowed);
     EcdsaProtoSerialization.register();
     MutableParametersRegistry.globalInstance().putAll(namedParameters());
+    MutablePrimitiveRegistry.globalInstance()
+        .registerPrimitiveConstructor(PUBLIC_KEY_SIGN_PRIMITIVE_CONSTRUCTOR);
+    MutablePrimitiveRegistry.globalInstance()
+        .registerPrimitiveConstructor(PUBLIC_KEY_VERIFY_PRIMITIVE_CONSTRUCTOR);
+    MutableKeyCreationRegistry.globalInstance().add(KEY_CREATOR, EcdsaParameters.class);
+    KeyManagerRegistry.globalInstance()
+        .registerKeyManagerWithFipsCompatibility(
+            legacyPrivateKeyManager,
+            TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_REQUIRES_BORINGCRYPTO,
+            newKeyAllowed);
+    KeyManagerRegistry.globalInstance()
+        .registerKeyManagerWithFipsCompatibility(
+            legacyPublicKeyManager,
+            TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_REQUIRES_BORINGCRYPTO,
+            false);
   }
 
   /**
@@ -270,4 +220,5 @@
                     .build()));
   }
 
+  private EcdsaSignKeyManager() {}
 }
diff --git a/src/main/java/com/google/crypto/tink/signature/EcdsaVerifyKeyManager.java b/src/main/java/com/google/crypto/tink/signature/EcdsaVerifyKeyManager.java
index 4cf6bdb..0fb4dfe 100644
--- a/src/main/java/com/google/crypto/tink/signature/EcdsaVerifyKeyManager.java
+++ b/src/main/java/com/google/crypto/tink/signature/EcdsaVerifyKeyManager.java
@@ -16,75 +16,14 @@
 
 package com.google.crypto.tink.signature;
 
-import com.google.crypto.tink.PublicKeyVerify;
-import com.google.crypto.tink.config.internal.TinkFipsUtil;
-import com.google.crypto.tink.internal.KeyTypeManager;
-import com.google.crypto.tink.internal.PrimitiveFactory;
-import com.google.crypto.tink.proto.EcdsaPublicKey;
-import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
-import com.google.crypto.tink.signature.internal.SigUtil;
-import com.google.crypto.tink.subtle.EcdsaVerifyJce;
-import com.google.crypto.tink.subtle.EllipticCurves;
-import com.google.crypto.tink.subtle.Validators;
-import com.google.protobuf.ByteString;
-import com.google.protobuf.ExtensionRegistryLite;
-import com.google.protobuf.InvalidProtocolBufferException;
-import java.security.GeneralSecurityException;
-import java.security.interfaces.ECPublicKey;
-
 /**
  * This key manager produces new instances of {@code EcdsaVerifyJce}. It doesn't support key
  * generation.
  */
-class EcdsaVerifyKeyManager extends KeyTypeManager<EcdsaPublicKey> {
-  public EcdsaVerifyKeyManager() {
-    super(
-        EcdsaPublicKey.class,
-        new PrimitiveFactory<PublicKeyVerify, EcdsaPublicKey>(PublicKeyVerify.class) {
-          @Override
-          public PublicKeyVerify getPrimitive(EcdsaPublicKey keyProto)
-              throws GeneralSecurityException {
-            ECPublicKey publicKey =
-                EllipticCurves.getEcPublicKey(
-                    SigUtil.toCurveType(keyProto.getParams().getCurve()),
-                    keyProto.getX().toByteArray(),
-                    keyProto.getY().toByteArray());
-            return new EcdsaVerifyJce(
-                publicKey,
-                SigUtil.toHashType(keyProto.getParams().getHashType()),
-                SigUtil.toEcdsaEncoding(keyProto.getParams().getEncoding()));
-          }
-        });
-  }
-
-  @Override
-  public String getKeyType() {
+class EcdsaVerifyKeyManager {
+  static String getKeyType() {
     return "type.googleapis.com/google.crypto.tink.EcdsaPublicKey";
   }
 
-  @Override
-  public int getVersion() {
-    return 0;
-  }
-
-  @Override
-  public KeyMaterialType keyMaterialType() {
-    return KeyMaterialType.ASYMMETRIC_PUBLIC;
-  }
-
-  @Override
-  public EcdsaPublicKey parseKey(ByteString byteString) throws InvalidProtocolBufferException {
-    return EcdsaPublicKey.parseFrom(byteString, ExtensionRegistryLite.getEmptyRegistry());
-  }
-
-  @Override
-  public void validateKey(EcdsaPublicKey pubKey) throws GeneralSecurityException {
-    Validators.validateVersion(pubKey.getVersion(), getVersion());
-    SigUtil.validateEcdsaParams(pubKey.getParams());
-  }
-
-  @Override
-  public TinkFipsUtil.AlgorithmFipsCompatibility fipsStatus() {
-    return TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_REQUIRES_BORINGCRYPTO;
-  };
+  private EcdsaVerifyKeyManager() {}
 }
diff --git a/src/main/java/com/google/crypto/tink/signature/SignatureKeyTemplates.java b/src/main/java/com/google/crypto/tink/signature/SignatureKeyTemplates.java
index 991f04e..2652c1e 100644
--- a/src/main/java/com/google/crypto/tink/signature/SignatureKeyTemplates.java
+++ b/src/main/java/com/google/crypto/tink/signature/SignatureKeyTemplates.java
@@ -240,7 +240,7 @@
     EcdsaKeyFormat format = EcdsaKeyFormat.newBuilder().setParams(params).build();
     return KeyTemplate.newBuilder()
         .setValue(format.toByteString())
-        .setTypeUrl(new EcdsaSignKeyManager().getKeyType())
+        .setTypeUrl(EcdsaSignKeyManager.getKeyType())
         .setOutputPrefixType(prefixType)
         .build();
   }
diff --git a/src/main/java/com/google/crypto/tink/signature/SignaturePemKeysetReader.java b/src/main/java/com/google/crypto/tink/signature/SignaturePemKeysetReader.java
index 4330dbe..634d158 100644
--- a/src/main/java/com/google/crypto/tink/signature/SignaturePemKeysetReader.java
+++ b/src/main/java/com/google/crypto/tink/signature/SignaturePemKeysetReader.java
@@ -210,14 +210,14 @@
               .build();
       EcdsaPublicKey ecdsaPubKey =
           EcdsaPublicKey.newBuilder()
-              .setVersion(new EcdsaVerifyKeyManager().getVersion())
+              .setVersion(0)
               .setParams(params)
               .setX(SigUtil.toUnsignedIntByteString(key.getW().getAffineX()))
               .setY(SigUtil.toUnsignedIntByteString(key.getW().getAffineY()))
               .build();
 
       return KeyData.newBuilder()
-          .setTypeUrl(new EcdsaVerifyKeyManager().getKeyType())
+          .setTypeUrl(EcdsaVerifyKeyManager.getKeyType())
           .setValue(ecdsaPubKey.toByteString())
           .setKeyMaterialType(KeyData.KeyMaterialType.ASYMMETRIC_PUBLIC)
           .build();
diff --git a/src/test/java/com/google/crypto/tink/signature/BUILD.bazel b/src/test/java/com/google/crypto/tink/signature/BUILD.bazel
index 30d86f7..e19fa96 100644
--- a/src/test/java/com/google/crypto/tink/signature/BUILD.bazel
+++ b/src/test/java/com/google/crypto/tink/signature/BUILD.bazel
@@ -126,25 +126,21 @@
     size = "small",
     srcs = ["EcdsaSignKeyManagerTest.java"],
     deps = [
-        "//proto:common_java_proto",
-        "//proto:ecdsa_java_proto",
-        "//proto:tink_java_proto",
+        "//src/main/java/com/google/crypto/tink:key",
         "//src/main/java/com/google/crypto/tink:key_template",
         "//src/main/java/com/google/crypto/tink:key_templates",
         "//src/main/java/com/google/crypto/tink:parameters",
         "//src/main/java/com/google/crypto/tink:public_key_sign",
         "//src/main/java/com/google/crypto/tink:public_key_verify",
         "//src/main/java/com/google/crypto/tink:registry_cluster",
-        "//src/main/java/com/google/crypto/tink/internal:key_type_manager",
+        "//src/main/java/com/google/crypto/tink/internal:key_manager_registry",
         "//src/main/java/com/google/crypto/tink/signature:ecdsa_parameters",
         "//src/main/java/com/google/crypto/tink/signature:ecdsa_sign_key_manager",
         "//src/main/java/com/google/crypto/tink/signature:signature_config",
         "//src/main/java/com/google/crypto/tink/signature:signature_private_key",
         "//src/main/java/com/google/crypto/tink/signature/internal/testing:ecdsa_test_util",
         "//src/main/java/com/google/crypto/tink/signature/internal/testing:signature_test_vector",
-        "//src/main/java/com/google/crypto/tink/subtle:hex",
         "@maven//:com_google_code_findbugs_jsr305",
-        "@maven//:com_google_protobuf_protobuf_java",
         "@maven//:com_google_truth_truth",
         "@maven//:junit_junit",
     ],
@@ -307,29 +303,6 @@
 )
 
 java_test(
-    name = "EcdsaVerifyKeyManagerTest",
-    size = "small",
-    srcs = ["EcdsaVerifyKeyManagerTest.java"],
-    deps = [
-        "//proto:common_java_proto",
-        "//proto:ecdsa_java_proto",
-        "//proto:tink_java_proto",
-        "//src/main/java/com/google/crypto/tink:public_key_verify",
-        "//src/main/java/com/google/crypto/tink/internal:key_type_manager",
-        "//src/main/java/com/google/crypto/tink/signature:ecdsa_sign_key_manager",
-        "//src/main/java/com/google/crypto/tink/signature:ecdsa_verify_key_manager",
-        "//src/main/java/com/google/crypto/tink/signature/internal:sig_util",
-        "//src/main/java/com/google/crypto/tink/subtle:elliptic_curves",
-        "//src/main/java/com/google/crypto/tink/subtle:hex",
-        "//src/main/java/com/google/crypto/tink/subtle:random",
-        "//src/main/java/com/google/crypto/tink/subtle:subtle_util_cluster",
-        "//src/main/java/com/google/crypto/tink/testing:test_util",
-        "@maven//:com_google_truth_truth",
-        "@maven//:junit_junit",
-    ],
-)
-
-java_test(
     name = "Ed25519PrivateKeyManagerTest",
     size = "small",
     srcs = ["Ed25519PrivateKeyManagerTest.java"],
@@ -717,3 +690,21 @@
         "@maven//:junit_junit",
     ],
 )
+
+java_test(
+    name = "EcdsaVerifyKeyManagerTest",
+    size = "small",
+    srcs = ["EcdsaVerifyKeyManagerTest.java"],
+    deps = [
+        "//src/main/java/com/google/crypto/tink:public_key_verify",
+        "//src/main/java/com/google/crypto/tink:registry_cluster",
+        "//src/main/java/com/google/crypto/tink/internal:big_integer_encoding",
+        "//src/main/java/com/google/crypto/tink/signature:ecdsa_parameters",
+        "//src/main/java/com/google/crypto/tink/signature:ecdsa_public_key",
+        "//src/main/java/com/google/crypto/tink/signature:signature_config",
+        "//src/main/java/com/google/crypto/tink/subtle:hex",
+        "//src/main/java/com/google/crypto/tink/subtle:random",
+        "//src/main/java/com/google/crypto/tink/testing:test_util",
+        "@maven//:junit_junit",
+    ],
+)
diff --git a/src/test/java/com/google/crypto/tink/signature/EcdsaSignKeyManagerTest.java b/src/test/java/com/google/crypto/tink/signature/EcdsaSignKeyManagerTest.java
index 24219eb..9e06601 100644
--- a/src/test/java/com/google/crypto/tink/signature/EcdsaSignKeyManagerTest.java
+++ b/src/test/java/com/google/crypto/tink/signature/EcdsaSignKeyManagerTest.java
@@ -19,28 +19,18 @@
 import static com.google.common.truth.Truth.assertThat;
 import static org.junit.Assert.assertThrows;
 
+import com.google.crypto.tink.Key;
 import com.google.crypto.tink.KeyTemplate;
 import com.google.crypto.tink.KeyTemplates;
 import com.google.crypto.tink.KeysetHandle;
 import com.google.crypto.tink.Parameters;
 import com.google.crypto.tink.PublicKeySign;
 import com.google.crypto.tink.PublicKeyVerify;
-import com.google.crypto.tink.internal.KeyTypeManager;
-import com.google.crypto.tink.proto.EcdsaKeyFormat;
-import com.google.crypto.tink.proto.EcdsaParams;
-import com.google.crypto.tink.proto.EcdsaPrivateKey;
-import com.google.crypto.tink.proto.EcdsaPublicKey;
-import com.google.crypto.tink.proto.EcdsaSignatureEncoding;
-import com.google.crypto.tink.proto.EllipticCurveType;
-import com.google.crypto.tink.proto.HashType;
-import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
+import com.google.crypto.tink.internal.KeyManagerRegistry;
 import com.google.crypto.tink.signature.internal.testing.EcdsaTestUtil;
 import com.google.crypto.tink.signature.internal.testing.SignatureTestVector;
-import com.google.crypto.tink.subtle.Hex;
-import com.google.protobuf.ByteString;
 import java.security.GeneralSecurityException;
-import java.util.Set;
-import java.util.TreeSet;
+import java.util.Arrays;
 import javax.annotation.Nullable;
 import org.junit.Before;
 import org.junit.Test;
@@ -53,268 +43,23 @@
 /** Unit tests for EcdsaSignKeyManager. */
 @RunWith(Theories.class)
 public class EcdsaSignKeyManagerTest {
-  private final EcdsaSignKeyManager manager = new EcdsaSignKeyManager();
-  private final KeyTypeManager.KeyFactory<EcdsaKeyFormat, EcdsaPrivateKey> factory =
-      manager.keyFactory();
-
   @Before
   public void register() throws Exception {
     SignatureConfig.register();
   }
 
-  private static EcdsaKeyFormat createKeyFormat(
-      HashType hashType, EllipticCurveType curveType, EcdsaSignatureEncoding encoding) {
-    return EcdsaKeyFormat.newBuilder()
-        .setParams(
-            EcdsaParams.newBuilder()
-                .setHashType(hashType)
-                .setCurve(curveType)
-                .setEncoding(encoding))
-        .build();
-  }
-
   @Test
-  public void basics() throws Exception {
-    assertThat(manager.getKeyType())
-        .isEqualTo("type.googleapis.com/google.crypto.tink.EcdsaPrivateKey");
-    assertThat(manager.getVersion()).isEqualTo(0);
-    assertThat(manager.keyMaterialType())
-        .isEqualTo(KeyMaterialType.ASYMMETRIC_PRIVATE);
-  }
-
-  @Test
-  public void validateKeyFormat_empty() throws Exception {
-    assertThrows(
-        GeneralSecurityException.class,
-        () -> factory.validateKeyFormat(EcdsaKeyFormat.getDefaultInstance()));
-  }
-
-  @Test
-  public void validateKeyFormat_valid() throws Exception {
-    // SHA256 NIST_P256 DER
-    factory.validateKeyFormat(
-        createKeyFormat(HashType.SHA256, EllipticCurveType.NIST_P256, EcdsaSignatureEncoding.DER));
-    // SHA256 NIST_P256 IEEE_P1363
-    factory.validateKeyFormat(
-        createKeyFormat(
-            HashType.SHA256, EllipticCurveType.NIST_P256, EcdsaSignatureEncoding.IEEE_P1363));
-    // SHA384 NIST_P384 DER
-    factory.validateKeyFormat(
-        createKeyFormat(HashType.SHA384, EllipticCurveType.NIST_P384, EcdsaSignatureEncoding.DER));
-    // SHA384 NIST_P384 IEEE_P1363
-    factory.validateKeyFormat(
-        createKeyFormat(
-            HashType.SHA384, EllipticCurveType.NIST_P384, EcdsaSignatureEncoding.IEEE_P1363));
-    // SHA512 NIST_P384 DER
-    factory.validateKeyFormat(
-        createKeyFormat(HashType.SHA512, EllipticCurveType.NIST_P384, EcdsaSignatureEncoding.DER));
-    // SHA512 NIST_P384 IEEE_P1363
-    factory.validateKeyFormat(
-        createKeyFormat(
-            HashType.SHA512, EllipticCurveType.NIST_P384, EcdsaSignatureEncoding.IEEE_P1363));
-    // SHA512 NIST_P521 DER
-    factory.validateKeyFormat(
-        createKeyFormat(HashType.SHA512, EllipticCurveType.NIST_P521, EcdsaSignatureEncoding.DER));
-    // SHA512 NIST_P521 IEEE_P1363
-    factory.validateKeyFormat(
-        createKeyFormat(
-            HashType.SHA512, EllipticCurveType.NIST_P521, EcdsaSignatureEncoding.IEEE_P1363));
-  }
-
-  @Test
-  public void validateKeyFormat_noSha1() throws Exception {
-    assertThrows(
-        GeneralSecurityException.class,
-        () ->
-            factory.validateKeyFormat(
-                createKeyFormat(
-                    HashType.SHA1, EllipticCurveType.NIST_P256, EcdsaSignatureEncoding.DER)));
-    assertThrows(
-        GeneralSecurityException.class,
-        () ->
-            factory.validateKeyFormat(
-                createKeyFormat(
-                    HashType.SHA1, EllipticCurveType.NIST_P384, EcdsaSignatureEncoding.DER)));
-    assertThrows(
-        GeneralSecurityException.class,
-        () ->
-            factory.validateKeyFormat(
-                createKeyFormat(
-                    HashType.SHA1, EllipticCurveType.NIST_P521, EcdsaSignatureEncoding.DER)));
-  }
-
-  @Test
-  public void validateKeyFormat_p384NotWithSha256() throws Exception {
-    assertThrows(
-        GeneralSecurityException.class,
-        () ->
-            factory.validateKeyFormat(
-                createKeyFormat(
-                    HashType.SHA256, EllipticCurveType.NIST_P384, EcdsaSignatureEncoding.DER)));
-  }
-
-  @Test
-  public void validateKeyFormat_p521OnlyWithSha512() throws Exception {
-    assertThrows(
-        GeneralSecurityException.class,
-        () ->
-            factory.validateKeyFormat(
-                createKeyFormat(
-                    HashType.SHA256, EllipticCurveType.NIST_P521, EcdsaSignatureEncoding.DER)));
-    assertThrows(
-        GeneralSecurityException.class,
-        () ->
-            factory.validateKeyFormat(
-                createKeyFormat(
-                    HashType.SHA384, EllipticCurveType.NIST_P521, EcdsaSignatureEncoding.DER)));
-  }
-
-  @Test
-  public void validateKeyFormat_unkownsProhibited() throws Exception {
-    assertThrows(
-        GeneralSecurityException.class,
-        () ->
-            factory.validateKeyFormat(
-                createKeyFormat(
-                    HashType.UNKNOWN_HASH,
-                    EllipticCurveType.NIST_P256,
-                    EcdsaSignatureEncoding.DER)));
-    assertThrows(
-        GeneralSecurityException.class,
-        () ->
-            factory.validateKeyFormat(
-                createKeyFormat(
-                    HashType.SHA256, EllipticCurveType.UNKNOWN_CURVE, EcdsaSignatureEncoding.DER)));
-    assertThrows(
-        GeneralSecurityException.class,
-        () ->
-            factory.validateKeyFormat(
-                createKeyFormat(
-                    HashType.SHA256,
-                    EllipticCurveType.NIST_P256,
-                    EcdsaSignatureEncoding.UNKNOWN_ENCODING)));
-  }
-
-  @Test
-  public void validateKey_empty() throws Exception {
-    assertThrows(
-        GeneralSecurityException.class,
-        () -> manager.validateKey(EcdsaPrivateKey.getDefaultInstance()));
-  }
-
-  @Test
-  public void createCorruptedPublicKeyPrimitive_throws() throws Exception {
-
-    EcdsaKeyFormat format =
-        createKeyFormat(HashType.SHA256, EllipticCurveType.NIST_P256, EcdsaSignatureEncoding.DER);
-    EcdsaPrivateKey originalKey = factory.createKey(format);
-    byte[] originalPubX = originalKey.getPublicKey().getX().toByteArray();
-    byte[] originalPubY = originalKey.getPublicKey().getY().toByteArray();
-    originalPubX[0] = (byte) (originalPubX[0] ^ 0x01);
-    ByteString corruptedPubX = ByteString.copyFrom(originalPubX);
-    EcdsaPublicKey corruptedPub =
-        EcdsaPublicKey.newBuilder()
-            .setVersion(originalKey.getPublicKey().getVersion())
-            .setParams(originalKey.getPublicKey().getParams())
-            .setX(corruptedPubX)
-            .setY(ByteString.copyFrom(originalPubY))
-            .build();
-    EcdsaPrivateKey corruptedKey =
-        EcdsaPrivateKey.newBuilder()
-            .setVersion(originalKey.getVersion())
-            .setPublicKey(corruptedPub)
-            .setKeyValue(originalKey.getKeyValue())
-            .build();
-    assertThrows(
-        GeneralSecurityException.class,
-        () -> manager.getPrimitive(corruptedKey, PublicKeySign.class));
-  }
-
-  /** Tests that a public key is extracted properly from a private key. */
-  @Test
-  public void getPublicKey_checkValues() throws Exception {
-    EcdsaPrivateKey privateKey =
-        factory.createKey(
-            createKeyFormat(
-                HashType.SHA256, EllipticCurveType.NIST_P256, EcdsaSignatureEncoding.DER));
-    EcdsaPublicKey publicKey = manager.getPublicKey(privateKey);
-
-    assertThat(publicKey).isEqualTo(privateKey.getPublicKey());
-  }
-
-  // Tests that generated keys have an adequate size. This is best-effort because keys might
-  // have leading zeros that are stripped off. These tests are flaky; the probability of
-  // failure is 2^-64 which happens when a key has 8 leading zeros.
-  @Test
-  public void createKey_nistP256_keySize() throws Exception {
-    EcdsaPrivateKey privateKey =
-        factory.createKey(
-            createKeyFormat(
-                HashType.SHA256, EllipticCurveType.NIST_P256, EcdsaSignatureEncoding.DER));
-    assertThat(privateKey.getKeyValue().size()).isAtLeast(256 / 8 - 8);
-    assertThat(privateKey.getKeyValue().size()).isAtMost(256 / 8 + 1);
-  }
-
-  // Tests that generated keys have an adequate size. This is best-effort because keys might
-  // have leading zeros that are stripped off. These tests are flaky; the probability of
-  // failure is 2^-64 which happens when a key has 8 leading zeros.
-  @Test
-  public void createKey_nistP384_keySize() throws Exception {
-    EcdsaPrivateKey privateKey =
-        factory.createKey(
-            createKeyFormat(
-                HashType.SHA384, EllipticCurveType.NIST_P384, EcdsaSignatureEncoding.DER));
-    assertThat(privateKey.getKeyValue().size()).isAtLeast(384 / 8 - 8);
-    assertThat(privateKey.getKeyValue().size()).isAtMost(384 / 8 + 1);
-  }
-
-  // Tests that generated keys have an adequate size. This is best-effort because keys might
-  // have leading zeros that are stripped off. These tests are flaky; the probability of
-  // failure is 2^-64 which happens when a key has 8 leading zeros.
-  @Test
-  public void createKey_nistP521_keySize() throws Exception {
-    EcdsaPrivateKey privateKey =
-        factory.createKey(
-            createKeyFormat(
-                HashType.SHA512, EllipticCurveType.NIST_P521, EcdsaSignatureEncoding.DER));
-    assertThat(privateKey.getKeyValue().size()).isAtLeast(521 / 8 - 8);
-    assertThat(privateKey.getKeyValue().size()).isAtMost(521 / 8 + 1);
-  }
-
-  @Test
-  public void createKey_nistP256_differentValues() throws Exception {
-    EcdsaKeyFormat format =
-        createKeyFormat(HashType.SHA256, EllipticCurveType.NIST_P256, EcdsaSignatureEncoding.DER);
-    Set<String> keys = new TreeSet<>();
-    int numTests = 100;
-    for (int i = 0; i < numTests; i++) {
-      keys.add(Hex.encode(factory.createKey(format).getKeyValue().toByteArray()));
-    }
-    assertThat(keys).hasSize(numTests);
-  }
-
-  @Test
-  public void createKey_nistP384_differentValues() throws Exception {
-    EcdsaKeyFormat format =
-        createKeyFormat(HashType.SHA384, EllipticCurveType.NIST_P384, EcdsaSignatureEncoding.DER);
-    Set<String> keys = new TreeSet<>();
-    int numTests = 100;
-    for (int i = 0; i < numTests; i++) {
-      keys.add(Hex.encode(factory.createKey(format).getKeyValue().toByteArray()));
-    }
-    assertThat(keys).hasSize(numTests);
-  }
-
-  @Test
-  public void createKey_nistP521_differentValues() throws Exception {
-    EcdsaKeyFormat format =
-        createKeyFormat(HashType.SHA512, EllipticCurveType.NIST_P521, EcdsaSignatureEncoding.DER);
-    Set<String> keys = new TreeSet<>();
-    int numTests = 100;
-    for (int i = 0; i < numTests; i++) {
-      keys.add(Hex.encode(factory.createKey(format).getKeyValue().toByteArray()));
-    }
-    assertThat(keys).hasSize(numTests);
+  public void testKeyManagersRegistered() throws Exception {
+    assertThat(
+            KeyManagerRegistry.globalInstance()
+                .getKeyManager(
+                    "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey", PublicKeySign.class))
+        .isNotNull();
+    assertThat(
+            KeyManagerRegistry.globalInstance()
+                .getKeyManager(
+                    "type.googleapis.com/google.crypto.tink.EcdsaPublicKey", PublicKeyVerify.class))
+        .isNotNull();
   }
 
   @Test
@@ -344,6 +89,15 @@
   }
 
   @Test
+  public void callingCreateTwiceGivesDifferentKeys() throws Exception {
+    Parameters p = EcdsaSignKeyManager.ecdsaP256Template().toParameters();
+    Key key = KeysetHandle.generateNew(p).getAt(0).getKey();
+    for (int i = 0; i < 100; ++i) {
+      assertThat(KeysetHandle.generateNew(p).getAt(0).getKey().equalsKey(key)).isFalse();
+    }
+  }
+
+  @Test
   public void testKeyTemplateAndManagerCompatibility() throws Exception {
     Parameters p = EcdsaSignKeyManager.ecdsaP256Template().toParameters();
     assertThat(KeysetHandle.generateNew(p).getAt(0).getKey().getParameters()).isEqualTo(p);
@@ -415,6 +169,35 @@
     verifier.verify(signature, testVector.getMessage());
   }
 
+  private static byte[] modifyInput(byte[] message) {
+    if (message.length == 0) {
+      return new byte[] {1};
+    }
+    byte[] copy = Arrays.copyOf(message, message.length);
+    copy[0] ^= 1;
+    return copy;
+  }
+
+  @Theory
+  public void test_computeFreshSignatureWithTestVector_throwsWithWrongMessage(
+      @FromDataPoints("allTests") SignatureTestVector testVector) throws Exception {
+    SignaturePrivateKey key = testVector.getPrivateKey();
+    KeysetHandle.Builder.Entry entry = KeysetHandle.importKey(key).makePrimary();
+    @Nullable Integer id = key.getIdRequirementOrNull();
+    if (id == null) {
+      entry.withRandomId();
+    } else {
+      entry.withFixedId(id);
+    }
+    KeysetHandle handle = KeysetHandle.newBuilder().addEntry(entry).build();
+    PublicKeySign signer = handle.getPrimitive(PublicKeySign.class);
+    byte[] signature = signer.sign(testVector.getMessage());
+    PublicKeyVerify verifier = handle.getPublicKeysetHandle().getPrimitive(PublicKeyVerify.class);
+    assertThrows(
+        GeneralSecurityException.class,
+        () -> verifier.verify(signature, modifyInput(testVector.getMessage())));
+  }
+
   @DataPoints("allTests")
   public static final SignatureTestVector[] ALL_TEST_VECTORS =
       EcdsaTestUtil.createEcdsaTestVectors();
diff --git a/src/test/java/com/google/crypto/tink/signature/EcdsaVerifyKeyManagerTest.java b/src/test/java/com/google/crypto/tink/signature/EcdsaVerifyKeyManagerTest.java
index 5f8c98b..307b110 100644
--- a/src/test/java/com/google/crypto/tink/signature/EcdsaVerifyKeyManagerTest.java
+++ b/src/test/java/com/google/crypto/tink/signature/EcdsaVerifyKeyManagerTest.java
@@ -16,24 +16,13 @@
 
 package com.google.crypto.tink.signature;
 
-import static com.google.common.truth.Truth.assertThat;
 import static org.junit.Assert.assertThrows;
 
+import com.google.crypto.tink.KeysetHandle;
 import com.google.crypto.tink.PublicKeyVerify;
-import com.google.crypto.tink.internal.KeyTypeManager;
-import com.google.crypto.tink.proto.EcdsaKeyFormat;
-import com.google.crypto.tink.proto.EcdsaParams;
-import com.google.crypto.tink.proto.EcdsaPrivateKey;
-import com.google.crypto.tink.proto.EcdsaPublicKey;
-import com.google.crypto.tink.proto.EcdsaSignatureEncoding;
-import com.google.crypto.tink.proto.EllipticCurveType;
-import com.google.crypto.tink.proto.HashType;
-import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
-import com.google.crypto.tink.signature.internal.SigUtil;
-import com.google.crypto.tink.subtle.EllipticCurves;
+import com.google.crypto.tink.internal.BigIntegerEncoding;
 import com.google.crypto.tink.subtle.Hex;
 import com.google.crypto.tink.subtle.Random;
-import com.google.crypto.tink.subtle.SubtleUtil;
 import com.google.crypto.tink.testing.TestUtil;
 import com.google.crypto.tink.testing.TestUtil.BytesMutation;
 import java.security.GeneralSecurityException;
@@ -44,97 +33,17 @@
 import java.security.interfaces.ECPublicKey;
 import java.security.spec.ECParameterSpec;
 import java.security.spec.ECPoint;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
-/**
- * Unit tests for EcdsaVerifyKeyManager.
- */
+/** Unit tests for EcdsaVerifyKeyManager. */
 @RunWith(JUnit4.class)
 public class EcdsaVerifyKeyManagerTest {
-  private final EcdsaSignKeyManager signManager = new EcdsaSignKeyManager();
-  private final EcdsaVerifyKeyManager verifyManager = new EcdsaVerifyKeyManager();
-  private final KeyTypeManager.KeyFactory<EcdsaKeyFormat, EcdsaPrivateKey> factory =
-      signManager.keyFactory();
-
-  private EcdsaPrivateKey createKey(
-      HashType hashType, EllipticCurveType curveType, EcdsaSignatureEncoding encoding)
-      throws GeneralSecurityException {
-    return factory.createKey(
-        EcdsaKeyFormat.newBuilder()
-            .setParams(
-                EcdsaParams.newBuilder()
-                    .setHashType(hashType)
-                    .setCurve(curveType)
-                    .setEncoding(encoding))
-            .build());
-  }
-
-  @Test
-  public void basics() throws Exception {
-    assertThat(verifyManager.getKeyType())
-        .isEqualTo("type.googleapis.com/google.crypto.tink.EcdsaPublicKey");
-    assertThat(verifyManager.getVersion()).isEqualTo(0);
-    assertThat(verifyManager.keyMaterialType()).isEqualTo(KeyMaterialType.ASYMMETRIC_PUBLIC);
-  }
-
-  @Test
-  public void validateKey_usualPublicKey() throws Exception {
-    verifyManager.validateKey(
-        signManager.getPublicKey(
-            createKey(HashType.SHA256, EllipticCurveType.NIST_P256, EcdsaSignatureEncoding.DER)));
-    verifyManager.validateKey(
-        signManager.getPublicKey(
-            createKey(
-                HashType.SHA256, EllipticCurveType.NIST_P256, EcdsaSignatureEncoding.IEEE_P1363)));
-    verifyManager.validateKey(
-        signManager.getPublicKey(
-            createKey(HashType.SHA384, EllipticCurveType.NIST_P384, EcdsaSignatureEncoding.DER)));
-    verifyManager.validateKey(
-        signManager.getPublicKey(
-            createKey(
-                HashType.SHA384, EllipticCurveType.NIST_P384, EcdsaSignatureEncoding.IEEE_P1363)));
-    verifyManager.validateKey(
-        signManager.getPublicKey(
-            createKey(HashType.SHA512, EllipticCurveType.NIST_P384, EcdsaSignatureEncoding.DER)));
-    verifyManager.validateKey(
-        signManager.getPublicKey(
-            createKey(
-                HashType.SHA512, EllipticCurveType.NIST_P384, EcdsaSignatureEncoding.IEEE_P1363)));
-    verifyManager.validateKey(
-        signManager.getPublicKey(
-            createKey(HashType.SHA512, EllipticCurveType.NIST_P521, EcdsaSignatureEncoding.DER)));
-    verifyManager.validateKey(
-        signManager.getPublicKey(
-            createKey(
-                HashType.SHA512, EllipticCurveType.NIST_P521, EcdsaSignatureEncoding.IEEE_P1363)));
-  }
-
-  private EcdsaPublicKey validPublicKey() throws Exception {
-    return signManager.getPublicKey(
-        createKey(HashType.SHA256, EllipticCurveType.NIST_P256, EcdsaSignatureEncoding.DER));
-  }
-
-  @Test
-  public void validateKey_wrongVersion_throws() throws Exception {
-    EcdsaPublicKey wrongVersionKey =
-        EcdsaPublicKey.newBuilder(validPublicKey()).setVersion(1).build();
-    assertThrows(GeneralSecurityException.class, () -> verifyManager.validateKey(wrongVersionKey));
-  }
-
-  @Test
-  public void validateKey_badParams_throws() throws Exception {
-    EcdsaPublicKey validKey = validPublicKey();
-    EcdsaPublicKey wrongHashKey =
-        EcdsaPublicKey.newBuilder(validKey)
-            .setParams(
-                EcdsaParams.newBuilder(validKey.getParams())
-                    .setHashType(HashType.SHA256)
-                    .setCurve(EllipticCurveType.NIST_P521)
-                    .build())
-            .build();
-    assertThrows(GeneralSecurityException.class, () -> verifyManager.validateKey(wrongHashKey));
+  @BeforeClass
+  public static void setUp() throws Exception {
+    SignatureConfig.register();
   }
 
   class RfcTestVector {
@@ -142,8 +51,8 @@
     byte[] pubX;
     byte[] pubY;
     byte[] sig;
-    HashType hashType;
-    EllipticCurveType curveType;
+    EcdsaParameters.HashType hashType;
+    EcdsaParameters.CurveType curveType;
 
     public RfcTestVector(
         String msg,
@@ -151,8 +60,8 @@
         String pubY,
         String r,
         String s,
-        HashType hashType,
-        EllipticCurveType curveType) {
+        EcdsaParameters.HashType hashType,
+        EcdsaParameters.CurveType curveType) {
       try {
         this.msg = msg.getBytes("UTF-8");
       } catch (Exception ignored) {
@@ -174,8 +83,8 @@
         "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299",
         "EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716",
         "F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8",
-        HashType.SHA256,
-        EllipticCurveType.NIST_P256),
+        EcdsaParameters.HashType.SHA256,
+        EcdsaParameters.CurveType.NIST_P256),
     new RfcTestVector(
         "sample",
         "EC3A4E415B4E19A4568618029F427FA5DA9A8BC4AE92E02E06AAE5286B300C64"
@@ -186,8 +95,8 @@
             + "FE30F35CC900056D7C99CD7882433709",
         "512C8CCEEE3890A84058CE1E22DBC2198F42323CE8ACA9135329F03C068E5112"
             + "DC7CC3EF3446DEFCEB01A45C2667FDD5",
-        HashType.SHA512,
-        EllipticCurveType.NIST_P384),
+        EcdsaParameters.HashType.SHA512,
+        EcdsaParameters.CurveType.NIST_P384),
     new RfcTestVector(
         "test",
         "01894550D0785932E00EAA23B694F213F8C3121F86DC97A04E5A7167DB4E5BCD3"
@@ -202,8 +111,8 @@
         "01FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78"
             + "A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4D"
             + "CE3",
-        HashType.SHA512,
-        EllipticCurveType.NIST_P521),
+        EcdsaParameters.HashType.SHA512,
+        EcdsaParameters.CurveType.NIST_P521),
   };
 
   @Test
@@ -225,10 +134,11 @@
   }
 
   private static class HashAndCurveType {
-    public HashType hashType;
-    public EllipticCurveType curveType;
+    public EcdsaParameters.HashType hashType;
+    public EcdsaParameters.CurveType curveType;
 
-    public HashAndCurveType(HashType hashType, EllipticCurveType curveType) {
+    public HashAndCurveType(
+        EcdsaParameters.HashType hashType, EcdsaParameters.CurveType curveType) {
       this.hashType = hashType;
       this.curveType = curveType;
     }
@@ -237,23 +147,21 @@
   @Test
   public void testGetPrimitiveWithJCE() throws Exception {
     HashAndCurveType[] hashAndCurves = {
-      new HashAndCurveType(HashType.SHA256, EllipticCurveType.NIST_P256),
-      new HashAndCurveType(HashType.SHA512, EllipticCurveType.NIST_P384),
-      new HashAndCurveType(HashType.SHA512, EllipticCurveType.NIST_P521)
+      new HashAndCurveType(EcdsaParameters.HashType.SHA256, EcdsaParameters.CurveType.NIST_P256),
+      new HashAndCurveType(EcdsaParameters.HashType.SHA512, EcdsaParameters.CurveType.NIST_P384),
+      new HashAndCurveType(EcdsaParameters.HashType.SHA512, EcdsaParameters.CurveType.NIST_P521)
     };
     for (int i = 0; i < hashAndCurves.length; i++) {
-      HashType hashType = hashAndCurves[i].hashType;
-      EllipticCurveType curveType = hashAndCurves[i].curveType;
-      ECParameterSpec ecParams = EllipticCurves.getCurveSpec(SigUtil.toCurveType(curveType));
+      EcdsaParameters.HashType hashType = hashAndCurves[i].hashType;
+      EcdsaParameters.CurveType curveType = hashAndCurves[i].curveType;
       KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
-      keyGen.initialize(ecParams);
+      keyGen.initialize(curveType.toParameterSpec());
       KeyPair keyPair = keyGen.generateKeyPair();
       ECPublicKey pubKey = (ECPublicKey) keyPair.getPublic();
       ECPrivateKey privKey = (ECPrivateKey) keyPair.getPrivate();
 
       // Sign with JCE's Signature.
-      Signature signer =
-          Signature.getInstance(SubtleUtil.toEcdsaAlgo(SigUtil.toHashType(hashType)));
+      Signature signer = Signature.getInstance(hashType.toString() + "withECDSA");
       signer.initSign(privKey);
       byte[] msg = Random.randBytes(1231);
       signer.update(msg);
@@ -265,7 +173,7 @@
           createVerifier(
               hashType,
               curveType,
-              EcdsaSignatureEncoding.DER,
+              EcdsaParameters.SignatureEncoding.DER,
               w.getAffineX().toByteArray(),
               w.getAffineY().toByteArray());
       verifier.verify(signature, msg);
@@ -275,17 +183,14 @@
   @Test
   public void testGetPrimitiveWithUnsupportedKey() throws Exception {
     HashAndCurveType[] hashAndCurves = {
-      new HashAndCurveType(HashType.SHA1, EllipticCurveType.NIST_P256),
-      new HashAndCurveType(HashType.SHA1, EllipticCurveType.NIST_P384),
-      new HashAndCurveType(HashType.SHA1, EllipticCurveType.NIST_P521),
-      new HashAndCurveType(HashType.SHA256, EllipticCurveType.NIST_P384),
-      new HashAndCurveType(HashType.SHA256, EllipticCurveType.NIST_P521),
-      new HashAndCurveType(HashType.SHA512, EllipticCurveType.NIST_P256),
+      new HashAndCurveType(EcdsaParameters.HashType.SHA256, EcdsaParameters.CurveType.NIST_P384),
+      new HashAndCurveType(EcdsaParameters.HashType.SHA256, EcdsaParameters.CurveType.NIST_P521),
+      new HashAndCurveType(EcdsaParameters.HashType.SHA512, EcdsaParameters.CurveType.NIST_P256),
     };
     for (int i = 0; i < hashAndCurves.length; i++) {
-      HashType hashType = hashAndCurves[i].hashType;
-      EllipticCurveType curveType = hashAndCurves[i].curveType;
-      ECParameterSpec ecParams = EllipticCurves.getCurveSpec(SigUtil.toCurveType(curveType));
+      EcdsaParameters.HashType hashType = hashAndCurves[i].hashType;
+      EcdsaParameters.CurveType curveType = hashAndCurves[i].curveType;
+      ECParameterSpec ecParams = curveType.toParameterSpec();
       KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
       keyGen.initialize(ecParams);
       KeyPair keyPair = keyGen.generateKeyPair();
@@ -302,7 +207,7 @@
                 createVerifier(
                     hashType,
                     curveType,
-                    EcdsaSignatureEncoding.DER,
+                    EcdsaParameters.SignatureEncoding.DER,
                     w.getAffineX().toByteArray(),
                     w.getAffineY().toByteArray());
           });
@@ -311,19 +216,32 @@
 
   private PublicKeyVerify createVerifier(RfcTestVector t) throws Exception {
     return createVerifier(
-        t.hashType, t.curveType, EcdsaSignatureEncoding.IEEE_P1363, t.pubX, t.pubY);
+        t.hashType, t.curveType, EcdsaParameters.SignatureEncoding.IEEE_P1363, t.pubX, t.pubY);
   }
 
   private PublicKeyVerify createVerifier(
-      HashType hashType,
-      EllipticCurveType curve,
-      EcdsaSignatureEncoding encoding,
+      EcdsaParameters.HashType hashType,
+      EcdsaParameters.CurveType curve,
+      EcdsaParameters.SignatureEncoding encoding,
       byte[] pubX,
       byte[] pubY)
       throws Exception {
-    EcdsaPublicKey ecdsaPubKey = TestUtil.createEcdsaPubKey(hashType, curve, encoding, pubX, pubY);
-    // Validating so that we throw exceptions when it is expected.
-    verifyManager.validateKey(ecdsaPubKey);
-    return verifyManager.getPrimitive(ecdsaPubKey, PublicKeyVerify.class);
+    EcdsaParameters parameters =
+        EcdsaParameters.builder()
+            .setHashType(hashType)
+            .setCurveType(curve)
+            .setSignatureEncoding(encoding)
+            .build();
+    ECPoint publicPoint =
+        new ECPoint(
+            BigIntegerEncoding.fromUnsignedBigEndianBytes(pubX),
+            BigIntegerEncoding.fromUnsignedBigEndianBytes(pubY));
+    EcdsaPublicKey publicKey =
+        EcdsaPublicKey.builder().setParameters(parameters).setPublicPoint(publicPoint).build();
+    KeysetHandle keysetHandle =
+        KeysetHandle.newBuilder()
+            .addEntry(KeysetHandle.importKey(publicKey).makePrimary().withRandomId())
+            .build();
+    return keysetHandle.getPrimitive(PublicKeyVerify.class);
   }
 }
diff --git a/src/test/java/com/google/crypto/tink/signature/SignatureKeyTemplatesTest.java b/src/test/java/com/google/crypto/tink/signature/SignatureKeyTemplatesTest.java
index 5e659e7..2e0ed9f 100644
--- a/src/test/java/com/google/crypto/tink/signature/SignatureKeyTemplatesTest.java
+++ b/src/test/java/com/google/crypto/tink/signature/SignatureKeyTemplatesTest.java
@@ -50,7 +50,7 @@
   @Test
   public void ecdsaP256() throws Exception {
     KeyTemplate template = SignatureKeyTemplates.ECDSA_P256;
-    assertEquals(new EcdsaSignKeyManager().getKeyType(), template.getTypeUrl());
+    assertEquals(EcdsaSignKeyManager.getKeyType(), template.getTypeUrl());
     assertEquals(OutputPrefixType.TINK, template.getOutputPrefixType());
     EcdsaKeyFormat format =
         EcdsaKeyFormat.parseFrom(template.getValue(), ExtensionRegistryLite.getEmptyRegistry());
@@ -64,7 +64,7 @@
   @Test
   public void ecdsaP256Ieee() throws Exception {
     KeyTemplate template = SignatureKeyTemplates.ECDSA_P256_IEEE_P1363;
-    assertEquals(new EcdsaSignKeyManager().getKeyType(), template.getTypeUrl());
+    assertEquals(EcdsaSignKeyManager.getKeyType(), template.getTypeUrl());
     assertEquals(OutputPrefixType.TINK, template.getOutputPrefixType());
     EcdsaKeyFormat format =
         EcdsaKeyFormat.parseFrom(template.getValue(), ExtensionRegistryLite.getEmptyRegistry());
@@ -78,7 +78,7 @@
   @Test
   public void ecdsaP256IeeeWithoutPrefix() throws Exception {
     KeyTemplate template = SignatureKeyTemplates.ECDSA_P256_IEEE_P1363_WITHOUT_PREFIX;
-    assertEquals(new EcdsaSignKeyManager().getKeyType(), template.getTypeUrl());
+    assertEquals(EcdsaSignKeyManager.getKeyType(), template.getTypeUrl());
     assertEquals(OutputPrefixType.RAW, template.getOutputPrefixType());
     EcdsaKeyFormat format =
         EcdsaKeyFormat.parseFrom(template.getValue(), ExtensionRegistryLite.getEmptyRegistry());
@@ -92,7 +92,7 @@
   @Test
   public void ecdsaP384() throws Exception {
     KeyTemplate template = SignatureKeyTemplates.ECDSA_P384;
-    assertEquals(new EcdsaSignKeyManager().getKeyType(), template.getTypeUrl());
+    assertEquals(EcdsaSignKeyManager.getKeyType(), template.getTypeUrl());
     assertEquals(OutputPrefixType.TINK, template.getOutputPrefixType());
     EcdsaKeyFormat format =
         EcdsaKeyFormat.parseFrom(template.getValue(), ExtensionRegistryLite.getEmptyRegistry());
@@ -106,7 +106,7 @@
   @Test
   public void ecdsaP384Ieee() throws Exception {
     KeyTemplate template = SignatureKeyTemplates.ECDSA_P384_IEEE_P1363;
-    assertEquals(new EcdsaSignKeyManager().getKeyType(), template.getTypeUrl());
+    assertEquals(EcdsaSignKeyManager.getKeyType(), template.getTypeUrl());
     assertEquals(OutputPrefixType.TINK, template.getOutputPrefixType());
     EcdsaKeyFormat format =
         EcdsaKeyFormat.parseFrom(template.getValue(), ExtensionRegistryLite.getEmptyRegistry());
@@ -120,7 +120,7 @@
   @Test
   public void ecdsaP521Ieee() throws Exception {
     KeyTemplate template = SignatureKeyTemplates.ECDSA_P521_IEEE_P1363;
-    assertEquals(new EcdsaSignKeyManager().getKeyType(), template.getTypeUrl());
+    assertEquals(EcdsaSignKeyManager.getKeyType(), template.getTypeUrl());
     assertEquals(OutputPrefixType.TINK, template.getOutputPrefixType());
     EcdsaKeyFormat format =
         EcdsaKeyFormat.parseFrom(template.getValue(), ExtensionRegistryLite.getEmptyRegistry());
@@ -141,7 +141,7 @@
     OutputPrefixType prefixType = OutputPrefixType.TINK;
     KeyTemplate template =
         SignatureKeyTemplates.createEcdsaKeyTemplate(hashType, curve, encoding, prefixType);
-    assertEquals(new EcdsaSignKeyManager().getKeyType(), template.getTypeUrl());
+    assertEquals(EcdsaSignKeyManager.getKeyType(), template.getTypeUrl());
     assertEquals(OutputPrefixType.TINK, template.getOutputPrefixType());
 
     EcdsaKeyFormat format =
diff --git a/src/test/java/com/google/crypto/tink/signature/SignaturePemKeysetReaderTest.java b/src/test/java/com/google/crypto/tink/signature/SignaturePemKeysetReaderTest.java
index 14b2837..7f153c2 100644
--- a/src/test/java/com/google/crypto/tink/signature/SignaturePemKeysetReaderTest.java
+++ b/src/test/java/com/google/crypto/tink/signature/SignaturePemKeysetReaderTest.java
@@ -107,7 +107,7 @@
     assertThat(ks.getPrimaryKeyId()).isEqualTo(key.getKeyId());
     assertThat(key.getStatus()).isEqualTo(KeyStatusType.ENABLED);
     assertThat(key.getOutputPrefixType()).isEqualTo(OutputPrefixType.RAW);
-    assertThat(keyData.getTypeUrl()).isEqualTo(new EcdsaVerifyKeyManager().getKeyType());
+    assertThat(keyData.getTypeUrl()).isEqualTo(EcdsaVerifyKeyManager.getKeyType());
     assertThat(keyData.getKeyMaterialType()).isEqualTo(KeyMaterialType.ASYMMETRIC_PUBLIC);
     assertThat(publicKeyProto.getParams().getHashType()).isEqualTo(HashType.SHA256);
     assertThat(publicKeyProto.getParams().getCurve()).isEqualTo(EllipticCurveType.NIST_P256);
@@ -297,7 +297,7 @@
             PemKeyType.ECDSA_P256_SHA256.readKey(new BufferedReader(new StringReader(ecPem)));
     assertThat(secondKey.getStatus()).isEqualTo(KeyStatusType.ENABLED);
     assertThat(secondKey.getOutputPrefixType()).isEqualTo(OutputPrefixType.RAW);
-    assertThat(keyData.getTypeUrl()).isEqualTo(new EcdsaVerifyKeyManager().getKeyType());
+    assertThat(keyData.getTypeUrl()).isEqualTo(EcdsaVerifyKeyManager.getKeyType());
     assertThat(keyData.getKeyMaterialType()).isEqualTo(KeyMaterialType.ASYMMETRIC_PUBLIC);
     assertThat(ecPublicKeyProto.getParams().getHashType()).isEqualTo(HashType.SHA256);
     assertThat(ecPublicKeyProto.getParams().getCurve()).isEqualTo(EllipticCurveType.NIST_P256);