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