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