Tink 線路格式

本頁說明 Tink 的金鑰和原始輸出內容的線路格式。本說明文件適用對象為希望在 Tinkoff 中新增其他語言的密碼學家,以及希望使用線路相容模式的其他高階加密程式庫維護者。不適合一般觀眾觀看。

金鑰組序列化

Tink 會使用 Google 通訊協定緩衝區將其鍵組序列化。

  • 二進位序列化金鑰組是 tink.proto 中定義的序列化 Keyset proto。鍵的 KeyData 值屬性是對應鍵類型的序列化 Proto。
  • JSON 序列化金鑰組是採用 JSON 格式序列化的 Keyset proto。請注意,KeyData 值仍是二進位序列化的 Proto。
  • 加密金鑰組是 tink.proto 中定義的序列化 EncryptedKeyset 原型。其中包含已加密的二進位序列化金鑰組,以及一些選用的未加密 KeysetInfo 中繼資料。

Tink 輸出內容前置字串

大多數 Tink 基本元素都支援 5 個位元組的輸出前置字串,包括:

  • 1 個位元組版本:0x01
  • 4 個位元組的索引鍵提示:這是所用索引鍵的索引鍵 ID。

部分舊版金鑰也可能支援版本位元 0x00

請注意,這個前置字串未經過驗證,因此無法用於安全性用途。Tink 會使用這項資訊做為提示,加快解密或驗證作業。

AEAD

一般而言,Tink 會將 AEAD 密文格式化為:

prefix || IV || ciphertext || tag

除非在相應的 RFC 中另有規定,否則 prefix 為空白或 5 個位元組的 Tink 輸出前置字元。

AES-CTR-HMAC

針對 AES-CTR-HMAC,Tink 會使用相關聯資料 (AD) 計算 MAC,如下所示:

AD || IV || ciphertext || bitlen(AD)

其中 bitlen(AD) 是 AD 的長度,以位元為單位,以 64 位元大端序的未簽署整數表示。這個 HMAC 配置會遵循 Mcgrew 的 AES-CBC-HMAC 草稿

確定性 AEAD

Tink 會實作 AES-SIV 的 RFC 5297,將合成初始向量 (SIV) 置於密文開頭。原始碼可能會新增 5 個位元組的 Tink 輸出前置字串。

雖然 RFC 5297 支援關聯資料清單,但 Tink 只支援確切的一個關聯資料,對應於 RFC 5297 中含有一個元素的清單。空相關資料是指含有一個空元素的清單,而非空清單。

串流 AEAD

請參閱 AES-CTR HMACAES-GCM-HKDF

信封式加密

信封式加密會使用 Tinkoff 的 AEAD 基本元素,以資料加密金鑰 DEK 加密資料。加密機制的運作方式如下:

  • 系統會使用指定的鍵範本 (或鍵參數) 產生新的 DEK
  • DEK 會序列化為位元組字串。序列化格式是金鑰類型 proto 的通訊協定緩衝區序列化。舉例來說,這是在 aes_gcm.proto 中定義的序列化 AesGcmKey 通訊協定緩衝區訊息,適用於金鑰類型為 AES GCM 的 DEK。如要瞭解如何序列化通訊協定緩衝區,請參閱「通訊協定緩衝區序列化」一文。
  • 外部供應商 (例如 GCP) 會將序列化的 DEK 加密成 encrypted DEK
  • DEK 會將明文與相關聯的資料加密為 ciphertext。因此,ciphertext 的格式與對應 DEK 的 AEAD 原始值完全相同。

信封式加密的輸出格式如下:

encrypted DEK length || encrypted DEK || ciphertext

encrypted DEK length 為 4 個位元組,會以 32 位元大端序整數儲存 encrypted DEK 的長度。

MAC

Tink 會遵循相應的 RFC。原始碼可能會在標記中加入 5 個位元組的 Tink 輸出前置字串。

PRF 集

Tink 會遵循相應的 RFC。請注意,對於 PRF 集,金鑰類型與相同演算法的 MAC 金鑰類型不同,因為前者不包含輸出長度。PRF 設定金鑰一律不會加入 Tink 輸出前置字串。這可確保輸出內容確實為 PRF。

混合式加密

Tink 混合式加密的一般線路格式如下:

prefix || encapsulated_key || encrypted_data

prefix 為空白或 5 個位元組的 Tink 輸出前置字串。每個鍵類型都包含解析多少位元組的資訊,以及如何從 encapsulated_key 解析這些位元組。

HPKE (混合式公開金鑰加密)

Tink 遵循 RFC 9180 中定義的 HPKE 標準。HPKE 密碼組合包含下列三個原始碼。

  • 金鑰封裝機制 (KEM)
  • 金鑰衍生函式 (KDF)
  • 附帶資料的已驗證加密 (AEAD)

HPKE 標準並未在 RFC 9180 的第 10 節中定義一般線路格式。Tink 的 HPKE 實作項目使用下列 encapsulated_keyencrypted_data 值。

  • encapsulated_key
    • 傳送者的序列化公開金鑰
    • RFC 9180 第 4.1 節所定義,為 enc
    • 格式取決於所使用的 HPKE KEM
  • encrypted_data
    • 密文和標記 (例如ciphertext || tag (不含 IV)
    • RFC 9180 第 4 節中定義為 ct
    • 格式由所使用的特定 HPKE AEAD 決定
X25519 Diffie-Hellman 架構的 KEM

對於 X25519 DHKEM,值 enc 是傳送端的 32 位元 Diffie-Hellman 公開金鑰。

ECIES-AEAD-HKDF

就 Tink 的 ECIES-AEAD-HKDF 實作而言,encapsulated_key 是金鑰封裝機制 (KEM) 的輸出內容,而 encrypted_data 則是資料封裝機制 (DEM) 的輸出內容。

KEM

視金鑰類型而定,Tink 會根據 RFC 8422/ANSI.X9-62.2005 編碼標準使用經過壓縮和未壓縮的橢圓曲線點。對於未壓縮的點,位元組 0x04 後方會接著 xy 座標,以固定大小的整數表示。對於壓縮座標,系統會使用位元組 0x020x03,以及 x 座標做為固定大小的整數。對於 X25519,我們採用 RFC 7748 定義 (x 座標為固定大小的整數)。

DEM

針對 encrypted_data,Tink 採用與 AEAD 相同的格式。這包括指定 IV。

金鑰衍生

系統會先計算共用點的 x 座標 x_ss。接著,AEAD 的鍵會設為:

HKDF(ikm = encapsulated_key || x_ss, salt = salt_of_key, info = context_info, length = dem_key_size)

其中 encapsulated_key 是完整的 KEM 輸出內容,以位元組為單位。

數位簽章

Tink 會遵循相應的 RFC。原始碼可能會在產生的標記中加入 5 個位元組的 Tink 輸出前置字串。

ECDSA

視金鑰中的 EcdsaSignatureEncoding 欄位而定,ECDSA 簽名的格式為 IEEE P1363ASN.1 DER

IEEE P1363 簽章的格式為 r || s,其中 rs 會以零填補,且位元組大小與曲線的順序相同。舉例來說,對於 NIST P-256 曲線,rs 會補零至 32 位元組。

DER 簽章會使用 ASN.1 進行編碼:

ECDSA-Sig-Value :: = SEQUENCE { r INTEGER, s INTEGER }

具體來說,編碼如下:

0x30 || totalLength || 0x02 || r's length || r || 0x02 || s's length || s

Tink 遵循簽名驗證的最佳做法,只接受 DER 編碼的 ECDSA 簽名 (其他 BER 編碼簽名無效)。

這有助於防止簽章可塑性攻擊,這類攻擊通常會影響加密貨幣系統