本頁說明 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 HMAC 和 AES-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_key
和 encrypted_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
後方會接著 x
和 y
座標,以固定大小的整數表示。對於壓縮座標,系統會使用位元組 0x02
或 0x03
,以及 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 P1363
或 ASN.1 DER
。
IEEE P1363
簽章的格式為 r || s
,其中 r
和 s
會以零填補,且位元組大小與曲線的順序相同。舉例來說,對於 NIST P-256
曲線,r
和 s
會補零至 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 編碼簽名無效)。
這有助於防止簽章可塑性攻擊,這類攻擊通常會影響加密貨幣系統。