在实际操作中,Tink 会提供 Key 对象来表示
用于表示 Parameters 的 key 和 Parameters 对象。
例如,在 Java 中,有 AesGcmKey 对象用于
表示 AES GCM 密钥。
在本部分中,我们将介绍如何在 Java 中设计这些对象,以及如何 互动
Parameters 个对象
请考虑采用广泛使用的 AEAD 加密方案 AES GCM。
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 OutputPrefixType getOutputPrefixType() {...}
public boolean equals(Object object) {...}
public int hashCode() {...}
}
如本节所述
密钥集、标记加密文、
当某些密钥位于密钥集内时,它们对 ID 有要求。每个
Parameters 对象有一个 hasIdRequirement 方法,用于指定是否将
此 Parameters 对象创建的键是否具有这样的必需 ID。
AesGcmParameters 对象接下来提供 getKeySizeBytes() 方法,
getIvSizeBytes()和getTagSizeBytes()。这些函数会返回
使用的密钥、使用的 IV 的长度以及生成的标签的长度,
(以字节为单位)。尽管 Tink 提供了一些此类函数,但
并不总是允许为每个选择创建 Aead。例如,目前
AES GCM 仅支持 12 个字节的 IV。
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 implements AeadKey {
public SecretBytes getKeyBytes();
public abstract Bytes getOutputPrefix();
public AesGcmParameters getParameters();
public @Nullable Integer getIdRequirementOrNull();
public boolean equalsKey(Key object);
}
getIdRequirementOrNull 方法会返回此键需要具有的 ID。
如果没有要求,则为 null。
(对于密钥,之所以这样要求,是因为 Tink 在某些情况下可能
使用字符串 0x01<id> 为密文或签名添加前缀,请参阅此部分
密文标记)。
这始终与
getParameters().hasIdRequirement() 以及
关键类需要确保这一点。
Key 的实现还需要提供一个 equalsKey 方法,
比较不同的键此类
方法通常很有用:例如,在测试密钥派生时,
旨在确保重复应用该推导可产生
相同的键对象。另外,KMS 可能想要检查其中是否存在任何密钥
提供给不同用户的服务是平等的(
密钥并将其多次上传到同一 KMS)。值得注意的是,
不要替换 Java 方法 equals,因为这需要我们执行以下操作:
替换 hashCode,并且无法在安全的环境中实现 hashCode
与 equals 兼容,而无需做出未经证明的假设。
接下来,我们需要 getParameters() 方法。这样,用户便可以在
与用于创建键的参数有关的原始信息。
最后,AesGcmKey 具有 getKeyBytes 方法,该方法会返回原始密钥材料。
此类方法对于键类来说非常典型:它们因类型而异,
并提供对底层密钥材料的访问权限。借助这些功能,用户
例如实现由键表示的基元,
或者对密钥进行序列化,以便将其存储在磁盘上,或者通过
。密钥本身负责保护密钥材料
未经授权的访问。例如,SecretBytes 需要访问令牌才能
提供
(请参阅访问权限控制)。
非对称密钥
对于非对称基元,Tink 使用两个 Key 类,一个用于私有,一个 。对于 Parameters,使用与 类(因为只有一个类可用于生成键)。
Tink 还有一个接口 PrivateKey,其中包含额外的
函数 getPublicKey()。