> [!NOTE]
> This section describes the future design of Tink. The current status may depend on the programming language used.

In practice, Tink provides `Key` objects to represent
[keys](https://developers.google.com/tink/design/keys) and `Parameters` objects to represent `Parameters`.
For example, in Java, we have `AesGcmKey` objects to
represent AES GCM keys.

In this section, we explain how these objects are designed in Java and how they
interact.

## `Parameters` objects

Consider AES GCM, a widely used AEAD encryption scheme.
Tink provides an `AesGcmParameters` object with the necessary information to
create a `AesGcmKey`, which we explain later.
The parameters hierarchy in Java looks as follows:

    public abstract class Parameters {
      public abstract boolean hasIdRequirement();
    }

    public abstract class AeadParameters extends Parameters {}

    public final class AesGcmParameters extends AeadParameters {
      /**
       * The Variant specified how ciphertexts are [tagged](/tink/design/keysets#tagging_ciphertexts).
       */
      public static final class Variant {...}
      /** A helper object to create new AesGcmParameters. */
      public static final class Builder {...}

      public int getKeySizeBytes() {...}
      public int getIvSizeBytes() {...}
      public int getTagSizeBytes() {...}

      public Variant getVariant() {...}

      public boolean equals(Object object) {...}
      public int hashCode() {...}
    }

As explained in the section
[Keysets, Tagging Ciphertexts](https://developers.google.com/tink/design/keysets#tagging_ciphertexts),
some keys have a requirement on their id, when they are in a keyset. Every
`Parameters` object has a method `hasIdRequirement` which specifies whether the
key created by this `Parameters` object will have such a required id, or not.

The `AesGcmParameters` object next provides methods `getKeySizeBytes()`,
`getIvSizeBytes()`, and `getTagSizeBytes()`. These return the lengths of
the key used, the length of the IV used, and the length of the produced tag,
in bytes. While Tink provides some of these functions for completeness, it
does not always allow creating `Aead`s for every choice. For example, currently
only 12 byte IVs are supported for AES GCM.

The `AesGcmParameters` object also provides overrides for the previously
defined methods (and the Java standard methods `equals` and `hashCode`
which is considered good practice).

Finally, it provides static methods to create new `AeadParameters` objects.
These validate the inputs, i.e., they check that the size is one of 16, 24,
or 32.

## Key objects

Tink also has a key hierarchy. Remaining with our example of AES GCM, it looks
like this:

    public abstract class Key {
      public abstract Parameters getParameters();
      public abstract @Nullable Integer getIdRequirementOrNull();
      public abstract boolean equalsKey(Key other);
    }

    public abstract class AeadKey extends Key {
      public abstract AeadParameters getParameters();
      public abstract Bytes getOutputPrefix();
    }

    public final class AesGcmKey extends AeadKey {
      public SecretBytes getKeyBytes();
      public Bytes getOutputPrefix();
      public AesGcmParameters getParameters();
      public @Nullable Integer getIdRequirementOrNull();
      public boolean equalsKey(Key object);
    }

The method `getIdRequirementOrNull` returns the id which this key needs to have,
or `null` if there is no requirement.
(Such a requirement on the key comes from the fact that Tink in some cases
prefixes ciphertexts or signatures with the string `0x01<id>`, see the section
on [ciphertext tagging](https://developers.google.com/tink/design/keysets#tagging_ciphertexts)).

This will always be consistent with the result of
`getParameters().hasIdRequirement()` and implementers of new
key classes need to ensure this.

Implementations of `Key` also need to provide a method `equalsKey` to
compare different keys. Such
a method is often useful: for example when testing key derivation, one is
interested in ensuring that repeated application of the derivation yields
the same key object. Also, a KMS might want to check if any of the keys it
provides to different users are equal (which happens sometimes if users share
keys and upload them to the same KMS multiple times). It is notable that we
do not override the Java method `equals`, because this would require us to
override `hashCode`, and there is no way to implement `hashCode` in a safe
way compatible with `equals` without making unproven assumptions.

Next, we require a method `getParameters()`. This allows users to get the
original information about the Parameters used to create the key.

Finally, `AesGcmKey` has a method `getKeyBytes` which returns the raw key material.
Such methods are very typical for key classes: they are specific to the type,
and provide access to the underlying key material. Using those, users
can in principle e.g. implement the primitive represented by the key,
or serialize the key in order to store it on disk or send it over the
network. The key itself is responsible for protecting the key material against
unauthorized access. For example, `SecretBytes` requires an access token to
actually provide the material
(see [Access Control](https://developers.google.com/tink/design/access_control)).

## Asymmetric Keys

For asymmetric primitives, Tink uses two Key classes, one for private and one
for public keys. For the Parameters, it is more convenient to use the same
class (as there is only one class which can be used to generate the keys).

Tink also has an interface `PrivateKey` with the additional
function `getPublicKey()`.