Tink 在所有程式設計語言中的行為必須「相同」。這個概念並不簡單,但最重要的是:
為維持一致性,Tink 會使用跨語言測試,您可以在跨語言 GitHub 存放區中找到這些測試。這些測試會驗證不同語言的一致性和互通性。
不過,定義一致性並不像預期那樣簡單。因此,本頁面提供我們的實用定義。基本上,Tink 提供兩種一致性:
背景資訊
概括來說,Tink 提供下列 API:
金鑰集操作:Tink 提供 API,可將新金鑰新增至金鑰集、從金鑰集移除金鑰,以及變更金鑰集中的主鍵。
金鑰組序列化:Tink 提供 API,可將金鑰組序列化為位元組序列,並反向剖析位元組序列中的金鑰組。
建立原語:Tink 提供 API,可從金鑰組建立原語介面。舉例來說,如要從 Java 的金鑰組建立
Aead物件,使用者會呼叫keysetHandle.getPrimitive(config, Aead.class)。原始物件使用:原始物件建立步驟中產生的介面會提供 API,用於執行加密編譯作業。
關於這些 API,有兩個重要問題需要考量:
建立: 對於指定的序列化金鑰組、語言和原始物件,是否能以該語言從這個金鑰組建立原始物件?
評估:如果可以透過特定金鑰集以某種語言建立原語,原語物件的行為為何?
請注意,Tink 在剖析金鑰集時不提供一致性。舉例來說,Tink C++
- 成功剖析含有 CHACHA20-POLY1305 金鑰的金鑰集,即使 Tink 未實作 CHACHA20-POLY1305 AEAD 作業也一樣。
- 成功剖析長度為 1 位元組的金鑰集,這類金鑰在所有加密編譯作業中都會失敗。
這些行為可能會在子版本中變更。
評估一致性
評估的一致性比建立程序中的任何一致性更重要:如果 Java 中的 AEAD 無法解密 C++ 中 AEAD 的加密,使用者就會遇到嚴重問題。
一般來說,Tink 的目標是以顯而易見的方式,為原語提供一致的行為。舉例來說,如果 C++ 二進位檔使用 public_key_sign->Sign(data) 計算簽章,則對應的 Java 驗證呼叫 publicKeyVerify.verify(signature, data) 應會成功。
不過,即使是這種情況,仍有一些注意事項。舉例來說,Java 中 aead.Encrypt 的傳回類型是 byte[]。根據 Java 語言規格 (JLS) §10.7,陣列長度為 int 類型,根據 §JLS 4.2.1,最大值為 2147483647。因此,在 Java 中加密長度為 2147483647 的陣列會失敗:加密會產生一些負擔,這表示輸出內容會過長。不過,在其他語言中,這類輸入內容可以成功加密。
因此,Tink 提供評估一致性:對於特定金鑰集,如果以兩種語言建立原始物件成功,則兩者的行為相同。
例外狀況是,某些作業在某些特殊情況下可能會失敗。
創作一致性
並非所有金鑰集都能成功建立原始物件。舉例來說,如果金鑰內容長度為 128 位元,Tink 不允許使用者建立 AesSivKey。
不過,Tink 仍會提供一致性,如下所示:如果兩種語言都支援某個金鑰類型,則可建立原始物件的金鑰組合會一致。當然,如果語言不支援金鑰類型,就無法建立原始物件。
建立一致性不如評估一致性重要,且這項規則的例外狀況比評估一致性多。如要瞭解這些限制,請參閱支援的金鑰類型清單。舉例來說,對於金鑰類型 ECIES,Tink 提供多種橢圓曲線供您選擇,用於金鑰協議,但 Java 不支援 X25519。因此,在 Java 中使用 X25519 建立金鑰會失敗。
-
在本文件中,我們使用
Keyset一詞來表示在大多數語言中稱為KeysetHandle的物件。 ↩