Key and Parameters Objects

In practice, Tink provides Key objects to represent 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 OutputPrefixType getOutputPrefixType() {...}
  public boolean equals(Object object) {...}
  public int hashCode() {...}
}

As explained in the section 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 Aeads 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 implements AeadKey {
  public SecretBytes getKeyBytes();
  public abstract 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).

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).

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().