Объекты ключей и параметров

На практике Tink предоставляет объекты Key, представляющие ключи, и объекты Parameters, представляющие Parameters. Например, в Java для представления ключей AES GCM используются объекты AesGcmKey.

В этом разделе мы расскажем, как эти объекты устроены в Java и как они взаимодействуют.

Parameters объекта

Рассмотрим AES GCM – широко используемую схему шифрования AEAD. Tink предоставляет объект AesGcmParameters с информацией, необходимой для создания AesGcmKey. Подробнее об этом рассказывается ниже. Иерархия параметров в Java выглядит следующим образом:

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

Как объясняется в разделе Наборы ключей и тегирование зашифрованных текстов, к идентификаторам некоторых ключей в наборе предъявляются определенные требования. У каждого объекта Parameters есть метод hasIdRequirement, который определяет, будет ли у ключа, созданного этим объектом Parameters, такой обязательный идентификатор.

Объект AesGcmParameters предоставляет методы getKeySizeBytes(), getIvSizeBytes() и getTagSizeBytes(). Они возвращают длину используемого ключа, длину используемого вектора инициализации и длину созданного тега в байтах. Хотя Tink предоставляет некоторые из этих функций для полноты, он не всегда позволяет создавать Aead для каждого выбора. Например, в настоящее время для AES GCM поддерживаются только 12-байтовые векторы инициализации.

Объект AesGcmParameters также переопределяет ранее определенные методы (и стандартные методы Java equals и hashCode, что считается хорошей практикой).

Наконец, он предоставляет статические методы для создания новых объектов AeadParameters. Они проверяют входные данные, то есть проверяют, что размер равен 16, 24 или 32.

Ключевые объекты

В Tink также есть иерархия ключей. Продолжая наш пример с AES GCM, это выглядит следующим образом:

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);
}

Метод getIdRequirementOrNull возвращает идентификатор, который должен быть у этого ключа, или null, если такого требования нет. Это требование связано с тем, что в некоторых случаях Tink добавляет к зашифрованному тексту или подписи префикс 0x01<id>. Подробнее об этом рассказывается в разделе Тегирование зашифрованного текста.

Это значение всегда будет соответствовать результату getParameters().hasIdRequirement(), и разработчики новых классов ключей должны это обеспечить.

Реализации Key также должны предоставлять метод equalsKey для сравнения разных ключей. Такой метод часто бывает полезен, например при тестировании деривации ключей, когда нужно убедиться, что повторное применение деривации дает тот же объект ключа. Кроме того, сервис управления ключами может проверять, не совпадают ли ключи, которые он предоставляет разным пользователям (такое иногда случается, если пользователи делятся ключами и загружают их в один и тот же сервис управления ключами несколько раз). Обратите внимание, что мы не переопределяем метод Java equals, поскольку для этого нам пришлось бы переопределить hashCode. Однако реализовать hashCode безопасным способом, совместимым с equals, без недоказанных предположений невозможно.

Затем нужно указать метод getParameters(). Это позволяет пользователям получать исходную информацию о параметрах, использованных для создания ключа.

Наконец, у AesGcmKey есть метод getKeyBytes, который возвращает необработанный материал ключа. Такие методы типичны для классов ключей: они зависят от типа и предоставляют доступ к базовому материалу ключа. Используя их, пользователи могут, например, реализовать примитив, представленный ключом, или сериализовать ключ, чтобы сохранить его на диске или отправить по сети. Ключ сам отвечает за защиту своего материала от несанкционированного доступа. Например, для предоставления материалов SecretBytes требуется токен доступа (см. раздел Контроль доступа).

Асимметричные ключи

Для асимметричных примитивов Tink использует два класса Key: один для закрытых ключей, а другой – для открытых. Для параметров удобнее использовать один и тот же класс, поскольку для создания ключей можно использовать только один класс.

В Tink также есть интерфейс PrivateKey с дополнительной функцией getPublicKey().