Nguyên gốc và giao diện

Tiếp theo, chúng tôi định nghĩa (chính thức nhưng sau đó chính thức hơn), hai phần quan trọng của ngôn ngữ dùng trong Tink là Primitive (Nguyên tắc) và Interface (Giao diện).

Nguyên bản

Đối tượng gốc là một đối tượng toán học tương ứng với tất cả các thuật toán thực hiện một số tác vụ một cách an toàn. Ví dụ: dữ liệu gốc AEAD bao gồm tất cả các thuật toán mã hoá đáp ứng các thuộc tính bảo mật mà Tink yêu cầu đối với Aead.

Chúng tôi nhấn mạnh rằng các dữ liệu nguyên gốc không bị ràng buộc với một ngôn ngữ lập trình hoặc một cách cụ thể để truy cập vào các dữ liệu đó. Thay vào đó, bạn nên coi dữ liệu nguyên thuỷ là đối tượng toán học thuần tuý. Ví dụ: nếu chúng ta xem xét AEAD, thì về cơ bản, AEAD sẽ bao gồm các cặp hàm, một hàm thực hiện việc mã hoá và một hàm thực hiện việc giải mã.

Giao diện

Giao diện là một cách mà chúng ta cung cấp cho người dùng quyền truy cập vào một dữ liệu gốc. Ví dụ: chúng tôi dự kiến rằng trong tương lai, Tink sẽ cung cấp giao diện Mac nhưng cũng cung cấp giao diện StreamingMac, cho phép tính toán máy mac của dữ liệu không được tải trực tiếp vào bộ nhớ.

Lưu ý rằng chúng ta phân biệt rõ ràng giao diện và dữ liệu gốc tại đây. Điều này sẽ làm rõ rằng đối tượng toán học mà hai giao diện này cấp quyền truy cập là như nhau.

Định nghĩa chính thức

Đối với hầu hết người đọc, những giải thích trực quan nêu trên có lẽ là đủ. Tuy nhiên, đôi khi chúng tôi cảm thấy rằng việc đưa ra định nghĩa chính thức về các khái niệm này là rất quan trọng.

Hàm mã hoá

Khái niệm về hàm mã hoá không quan trọng như khái niệm về hàm nguyên gốc, nhưng chúng ta cần đưa hàm này vào để chính thức xác định dữ liệu gốc.

Hàm mật mã

Hàm mật mã là một bản đồ

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

từ một tập hợp \({\bf K}\) (không gian khoá), một tập hợp \({\bf R} = \{0,1\}^{\infty}\) (độ ngẫu nhiên, mà chúng tôi giả định là tập hợp các chuỗi bit vô hạn) và một tập hợp \({\bf I}\) (không gian đầu vào), thành một tập hợp \({\bf O}\) (không gian đầu ra).

Sau này, bạn sẽ biết rõ lý do chúng ta thêm một tham số ngẫu nhiên cụ thể.

Ví dụ: chúng tôi đưa ra một khả năng về cách liên kết các khái niệm này với AES-GCM. Đối với mỗi kích thước khoá hợp lệ \(s_k\), kích thước số chỉ dùng một lần \(s_n\)và kích thước thẻ\(s_t\), AES-GCM bao gồm 2 hàm mã hoá, một hàm để mã hoá và một hàm để giải mã. Cả hai sẽ có cùng một không gian phím \({\bf K} = \{0,1\}^{s_k}\).

Đối với hàm mã hoá \(\mathrm{Enc}\), các bit \(s_n\) đầu tiên của ngẫu nhiên sẽ được dùng để chọn số chỉ dùng một lần.

Để \({\bf B} = \{0,1\}^8\) biểu thị một byte. Không gian đầu vào của hàm mã hoá là các cặp \({\bf I} = {\bf B}^{*} \times {\bf B}^{*}\) của chuỗi byte có độ dài tuỳ ý. Phần tử đầu tiên của cặp này là thông báo, phần tử thứ hai là dữ liệu liên quan. Tiêu chuẩn AES-GCM có giới hạn trên về độ dài của dữ liệu đầu vào, nhưng chúng tôi muốn cho phép độ dài tuỳ ý và thay vào đó, thêm một biểu tượng lỗi đặc biệt \(\bot\) vào không gian đầu ra. Sau đó, không gian đầu ra trở thành \({\bf O} = {\bf B}^* \cup \{\bot\}\), trong đó chúng ta tuỳ ý xác định kết quả của các phép tính thành công là phép nối \((\mathrm{IV} \| \mathrm{ciphertext} \| \mathrm{tag})\) như đã cho trong tiêu chuẩn và đầu ra\(\bot\), trong trường hợp có một số dữ liệu đầu vào quá dài. Do đó, đối với một khoá cố định, hàm mã hoá sẽ trở thành kiểu \(\mathrm{Enc}_k : {\bf R} \times {\bf B}^* \times {\bf B}^* \rightarrow {\bf B}^* \cup \{\bot\}\).

Đối với hàm giải mã \(\mathrm{Dec}\) không gian khoá là giống nhau. Không gian đầu vào trùng hợp là giống nhau: \({\bf I} ={\bf B}^* \times {\bf B}^*\), nhưng giờ đây, phần tử đầu tiên là đầu ra của hàm mã hoá, trong khi phần tử thứ hai vẫn là dữ liệu liên kết.

Không gian đầu ra cũng sẽ không thay đổi \({\bf O} = {\bf B}^* \cup \{\bot\}\) (lại là một sự trùng hợp). Cách diễn giải có phần khác, \(\bot\) thường biểu thị lỗi xác thực (mặc dù đó cũng sẽ là kết quả trong trường hợp một số dữ liệu đầu vào quá dài).

Chúng tôi nhấn mạnh rằng việc chính thức hoá nêu trên không phải là lựa chọn duy nhất để chính thức hoá tiêu chuẩn. Ví dụ: người dùng có thể coi số chỉ dùng một lần là một phần của dữ liệu đầu vào, thay vì đọc số chỉ dùng một lần từ sự ngẫu nhiên (dẫn đến một số nguyên gốc rất khác). Ngoài ra, người dùng có thể xác định đầu ra là một bộ ba chứa số chỉ dùng một lần, bản mã hoá và thẻ (thay vì phép nối). Hoặc bạn có thể hạn chế không gian khoá (phần nào tuỳ ý) thành\({\bf K} = \{0,1\}^{128} \cup \{0,1\}^{256}\).

Thuật toán mật mã:

Thuật toán mật mã (đối xứng) là một bộ dữ liệu

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

hàm mã hoá, trong đó tất cả hàm có cùng không gian khoá. Loại của thuật toán mã hoá là bộ dữ liệu \((({\bf I}_1, {\bf O}_1), \ldots, ({\bf I}_k, {\bf O}_k))\).

Ví dụ: đối với mỗi bộ 3 \((s_k, s_n, s_t)\) khoá, số chỉ dùng một lần và kích thước thẻ hợp lệ, AES-GCM\({}_{s_k, s_n, s_t}\) là thuật toán mã hoá gồm có 2 hàm \(\mathrm{Enc}\) và \(\mathrm{Dec}\) được mô tả ở trên.

Gốc và giao diện

Tiếp theo, chúng ta xác định một dữ liệu nguyên gốc mật mã.

Nguyên bản
Sơ đồ gốc là một tập hợp các thuật toán mã hoá, trong đó tất cả các thuật toán đều có cùng kiểu \((({\bf I}_1, {\bf O}_1), \ldots, ({\bf I}_k, {\bf O}_k))\)và các không gian chính của các thuật toán được tách rời theo cặp.

Ví dụ: hãy xem xét \(\mathrm{AEAD}\) nguyên gốc trong Tink. Mã này có nhiều thuật toán, trong đó có AES-GCM cho kích thước khoá 128 và 256 bit, với kích thước số chỉ dùng một lần 96 bit, AES-EAX với một số kích thước khoá và XChaCha20Poly1305. Các khoá này có các không gian khoá rời, nhưng tất cả đều cung cấp cùng một hàm mã hoá\(\mathrm{Enc}\) và \(\mathrm{Dec}\). (Chúng tôi không thấy mục đích nào về việc thu gọn các kích thước khoá khác nhau của AES-GCM trong cuộc thảo luận chính thức này, nhưng tất nhiên người ta có thể làm như vậy).

Xác định dữ liệu gốc

Cách nghĩ thông thường về dữ liệu gốc là trước tiên xác định các thuộc tính của các hàm mật mã, sau đó chỉ cần xem dữ liệu gốc là tất cả các thuật toán như vậy.

Ví dụ: đối với AEAD, chúng tôi sẽ nói rằng \(\mathrm{Dec}_k(\mathrm{Enc}_k(m, a), a) = m\) "luôn luôn" thoả mãn (ngoại trừ trường hợp văn bản thuần tuý \(m\) quá dài). Ngoài ra, chúng tôi còn có các thuộc tính bảo mật; ví dụ: đối với khoá ngẫu nhiên, quá trình mã hoá đáng kể.

Sau đó, dữ liệu gốc AEAD chỉ đơn giản là tập hợp tất cả các thuật toán mã hoá đáp ứng các thuộc tính này. Nói cách khác, trong thực tế, khi xác định một nguyên gốc cụ thể, chúng ta xác định dựa trên các thuộc tính. Chúng tôi không cung cấp danh sách các thuật toán, như định nghĩa cho thấy.

Giao diện

Một giao diện trong Tink cấp quyền truy cập vào một dữ liệu gốc, theo nghĩa là cho phép tính toán một phần tử của không gian đầu ra từ không gian đầu vào. Ví dụ: hãy xem xét giao diện AEAD trong Java:

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

Xin lưu ý rằng chúng tôi không cấp quyền truy cập vào tính ngẫu nhiên. Thay vào đó, chúng tôi cho phép người dùng cung cấp các phần tử của không gian nhập. Việc không cho phép truy cập vào tính ngẫu nhiên là tất nhiên có chủ đích.1

Tink đôi khi cung cấp nhiều giao diện cho một dữ liệu gốc. Điều này có thể rất hữu ích vì các yêu cầu đôi khi khác nhau. Tuy nhiên, thực hiện việc này có một mức giá: nói chung, càng nhiều giao diện cung cấp thì khả năng tương tác càng thấp. Ví dụ: giả sử ai đó viết một thư viện dựa trên Tink yêu cầu người dùng truyền vào một đối tượng Aead (để mã hoá nội bộ nội bộ). Nếu Tink cung cấp quá nhiều giao diện khác nhau cho \(\mathrm{AEAD}\) nguyên gốc, thì rất có thể người dùng chưa có sẵn thực thể hoạt động cho khoá mà người dùng đã chọn và thư viện cùng một lúc. Do đó, việc thêm nhiều giao diện hơn sẽ là sự đánh đổi.


  1. Thuật toán mật mã AEAD có thuộc tính bảo mật trước các cuộc tấn công bằng văn bản mật mã đã chọn. Điều này chỉ được đảm bảo nếu không sử dụng lại số chỉ dùng một lần. Giao diện Aead trong Tink được thiết kế để ngăn việc sử dụng lại số chỉ dùng một lần: người dùng không thể cung cấp số chỉ dùng một lần làm dữ liệu đầu vào để mã hoá, thay vào đó, một số chỉ dùng một lần mới được tạo ngẫu nhiên cho mỗi hoạt động mã hoá.