金鑰與參數物件

實際上,Tink 提供 Key 物件來代表 Parameters 物件則代表 Parameters。舉例來說,在 Java 中,我們有 AesGcmKey 物件來代表 AES GCM 金鑰。

在本節中,我們將說明這些物件以 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 OutputPrefixType getOutputPrefixType() {...}
  public boolean equals(Object object) {...}
  public int hashCode() {...}
}

如「金鑰組、標記加密文」一節所述,當部分鍵位於金鑰組時,其 ID 對其 ID 有規定。每個 Parameters 物件都有一個方法 hasIdRequirement,該方法可指定由此 Parameters 物件建立的金鑰是否具有此類必要 ID。

AesGcmParameters 物件接下來會提供 getKeySizeBytes()getIvSizeBytes()getTagSizeBytes() 方法。這些類別會傳回所用金鑰的長度、使用的 IV 長度,以及產生的標記長度 (以位元組為單位)。雖然 Tink 提供部分函式以提供完整資訊,但並不一定允許為每個選項建立 Aead。舉例來說,AES GCM 目前只支援 12 位元組 IV。

AesGcmParameters 物件也會覆寫先前定義的方法 (以及 Java 標準方法 equalshashCode,這是不錯的做法)。

最後,它提供靜態方法來建立新的 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,而且沒有提供未經證實的假設,因此無法以與 equals 相容的安全方式實作 hashCode

接下來,我們需要 getParameters() 方法。這樣做可讓使用者取得用於建立金鑰的參數原始資訊。

最後,AesGcmKeygetKeyBytes 方法會傳回原始金鑰內容。這種方法在金鑰類別非常常見:這是專屬於類型,並提供基礎金鑰內容的存取權。使用者只要運用這些原則,即可瞭解各種原則,例如導入金鑰代表的原始功能,或者為金鑰序列化,以將金鑰儲存在磁碟中或透過網路傳送。金鑰本身負責保護金鑰內容,防止他人在未經授權的情況下擅自存取。舉例來說,SecretBytes 需要存取權杖才能實際提供內容 (請參閱存取權控管)。

非對稱金鑰

針對非對稱基元,Tink 會使用兩個 Key 類別:一個是私密金鑰類別,另一個用於公開金鑰。針對參數,使用相同的類別會比較方便 (因為只有一個類別可用來產生金鑰)。

Tink 也有 PrivateKey 介面,並含有額外的 getPublicKey() 函式。