基本和介面

接下來,我們接著定義 Tink 語言中的兩個重要部分,例如 PrimitiveInterface

樸實

基本是一種「數學」物件,對應於所有安全執行某些工作的演算法。例如,AEAD 原始物件包含所有加密演算法,這些演算法可滿足 Tink 需要 Aead 的安全性屬性

我們想強調,基元不會受限於程式設計語言,也不會受到特定存取方式的限制。相反地,您應該將原始物件視為單純的數學物件。例如,如果我們考慮 AEAD,基本上就會包含一組函式、一種執行加密的函式,另一種則是執行解密的函式。

介面

介面是一種向使用者提供原始存取權的方式,舉例來說,我們預期日後 Tink 會提供 Mac 介面,同時提供 StreamingMac 介面,讓您計算不會直接載入記憶體的資料量。

請注意,我們明確區分這裡的介面和基元。這樣應該可以明確地區分這兩個介面授予存取權的數學物件。

正式定義

對多數讀者來說,上述直觀的說明應該就夠了。 儘管如此,我們認為有時提供這些概念的正式定義有時很重要。

加密編譯函式

加密編譯函式的概念不如原始的概念並不重要,但我們必須導入這個概念才能正式定義原始函式。

加密編譯函式

「密碼編譯函式」是地圖

\[ f: {\bf K} \times {\bf R} \times {\bf I} \to {\bf O}\]

從集合 \({\bf K}\) (鍵空間)、集合 \({\bf R} = \{0,1\}^{\infty}\)(隨機性,假設為無限位元字串集)、集合 \({\bf I}\) (輸入空間) 移至集合 \({\bf O}\) (輸出空間)。

之後會更清楚為何地加入特定隨機參數。

舉例來說,我們展示了這些概念如何將這些概念對應至 AES-GCM 的可能性。針對每個有效的金鑰大小 \(s_k\)、Nonce 大小 \(s_n\),以及標記大小\(s_t\),AES-GCM 包含兩個加密編譯函式,一個用於加密,另一個用於解密。兩者的索引鍵空間相同 \({\bf K} = \{0,1\}^{s_k}\)。

針對加密函式 \(\mathrm{Enc}\),系統會使用隨機的前 \(s_n\) 位元選取 Nonce。

用來 \({\bf B} = \{0,1\}^8\) 代表位元組。加密函式的輸入空間是指 \({\bf I} = {\bf B}^{*} \times {\bf B}^{*}\) 任意長度的位元組字串組合。配對的第一個元素是用來呈現訊息,第二個元素是關聯資料。AES-GCM 標準對輸入長度設有上限,但我們建議允許任意長度,改為在輸出空間中加入特殊錯誤符號 \(\bot\) 。然後輸出空間會變成 \({\bf O} = {\bf B}^* \cup \{\bot\}\),其中我們會依照標準所述的方式,任意定義成功計算的結果, \((\mathrm{IV} \| \mathrm{ciphertext} \| \mathrm{tag})\) 以及輸出\(\bot\)(避免部分輸入內容過長時)。因此,如果是固定金鑰,加密函式會變成 \(\mathrm{Enc}_k : {\bf R} \times {\bf B}^* \times {\bf B}^* \rightarrow {\bf B}^* \cup \{\bot\}\)類型。

解密函式 \(\mathrm{Dec}\) 金鑰空間相同。輸入空間恰好相同: \({\bf I} ={\bf B}^* \times {\bf B}^*\),但現在第一個元素是要用來輸出加密函式的輸出內容,而第二個元素則是相關聯的資料。

輸出內容空間也似乎相同 \({\bf O} = {\bf B}^* \cup \{\bot\}\) (再次相等於)。解釋方式略有不同,因為 \(\bot\) 通常表示驗證錯誤 (如果部分輸入內容過長,輸出結果也會是輸出內容)。

我們瞭解上述正規化不是正規化標準的唯一方法。舉例來說,您可以將 Nonce 視為輸入內容的一部分,而不是從隨機性讀取 (進而產生截然不同的原始資料)。或者,您也可以將輸出定義為包含 Nonce、密文和標記的三元組 (而非以串連)。或者,也可以將索引鍵空間 (某種程度) 限制為\({\bf K} = \{0,1\}^{128} \cup \{0,1\}^{256}\)。

加密編譯演算法:

(對稱) 密碼編譯演算法是元組

\[(f_1, ... f_k)\]

所有函式都有相同的金鑰空間。加密編譯演算法的「類型」是元組 \((({\bf I}_1, {\bf O}_1), \ldots, ({\bf I}_k, {\bf O}_k))\)。

例如,針對每個有效的第 \((s_k, s_n, s_t)\) 3 軸和標記大小,AES-GCM\({}_{s_k, s_n, s_t}\) 是一種加密演算法,包含兩個函式 \(\mathrm{Enc}\) 和 \(\mathrm{Dec}\) 上述說明。

基本和介面

接下來,我們要定義一個加密編譯基元。

樸實
「原始」是一組加密編譯演算法,所有演算法都具有相同的類型 \((({\bf I}_1, {\bf O}_1), \ldots, ({\bf I}_k, {\bf O}_k))\),且演算法的索引鍵空間會配對不相交。

例如,考慮使用 Tink 中的 \(\mathrm{AEAD}\) 原始物件。它擁有多個演算法,其中金鑰大小為 128 和 256 位元的 AES-GCM,搭配 Nonce 大小 96 位元、AES-EAX 搭配部分金鑰大小,以及 XChaCha20Poly1305。這些鍵空間沒有互連的索引鍵空間,但全都提供相同的加密編譯函式\(\mathrm{Enc}\) 和 \(\mathrm{Dec}\)。(在本正式的討論中,我們並未發現任何縮減 AES-GCM 金鑰大小的用意,但當然可以這麼做)。

定義基本

基元的常見思考方式,是先定義密碼編譯函式的屬性,然後只考量基元是所有這類演算法。

例如,如果是 AEAD,我們會說 \(\mathrm{Dec}_k(\mathrm{Enc}_k(m, a), a) = m\) 視為「always」(除外,例如明文 \(m\) 過長時除外)。此外,我們還提供安全性屬性;舉例來說,針對隨機金鑰,加密機制的安全性相當高。

然後,AEAD 原始版本就是滿足這些屬性的所有加密編譯演算法組合。換句話說,在實務上,當我們定義特定原始版本時,會根據屬性定義該原始版本。我們不會提供演算法清單 (如定義所示)。

介面

Tink 中的「介面」可讓您存取原始物件,因為它可以從輸入空間計算輸出空間的元素。例如,考慮 Java 中的 AEAD 介面:

public interface Aead {
  byte[] encrypt(byte[] plaintext, byte[] associated_data) throws GeneralSecurityException;
  byte[] decrypt(byte[] ciphertext, byte[] associated_data) throws GeneralSecurityException;
}

請注意,我們不會提供隨機性的存取權。改為讓使用者提供輸入空間的元素。我們也刻意禁止存取隨機性1

Tink 有時會針對單一原始項目提供多個介面。這非常實用,因為需求有時可能會不同。不過,執行此操作卻是價格:一般來說,介面越多,互通性就越低。例如,假設有人根據 Tink 編寫程式庫,要求使用者傳入 Aead 物件 (在內部加密項目)。如果 Tink 為原始提供過多介面, \(\mathrm{AEAD}\) 使用者就有可能並未準備就緒,且執行個體可能不適用於使用者所選金鑰和程式庫。因此,新增更多介面會產生缺點。


  1. AEAD 加密具有可對選擇的密文攻擊安全的屬性,此屬性只有在沒有重複使用 Nonce 時才能保證。Tink 中的 Aead 介面設計可避免 Nonce 重複使用:使用者無法提供 Nonce 做為加密的輸入內容,系統會為每項加密作業隨機產生一個新的 Nonce。