Phát trực tuyến AEAD với AES-GCM-HKDF

Tài liệu này chính thức định nghĩa hàm toán học được biểu thị bằng các khoá Truyền trực tuyến AES-GCM-HKDF, được mã hoá theo định dạng proto dưới dạng type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey.

Phương thức mã hoá này dựa trên HRRV151 một cách thoải mái. Đối với phân tích bảo mật, chúng tôi tham khảo HS202.

Khoá và thông số

Các khoá được mô tả bằng các phần sau (tất cả kích thước trong tài liệu này đều tính bằng byte):

  • \(\mathrm{KeyValue}\), một chuỗi byte.
  • \(\mathrm{CiphertextSegmentSize} \in \{1, 2, \ldots, 2^{31}-1\}\).
  • \(\mathrm{DerivedKeySize} \in \{16, 32\}\).
  • \(\mathrm{HkdfHashType} \in \{\mathrm{SHA1}, \mathrm{SHA256}, \mathrm{SHA512}\}\).

Các khoá hợp lệ đáp ứng thêm các thuộc tính sau:

  • \(\mathrm{len}(\mathrm{KeyValue}) \geq \mathrm{DerivedKeySize}\).
  • \(\mathrm{CiphertextSegmentSize} > \mathrm{DerivedKeySize} + 24\) (Điều này tương đương với \(\mathrm{len}(\mathrm{Header}) + 16\) như giải thích ở phần sau).

Tink sẽ từ chối các khoá không đáp ứng bất kỳ thuộc tính nào trong số này, dù khi khoá được phân tích cú pháp hoặc khi tạo dữ liệu gốc tương ứng.

Chức năng mã hoá

Để mã hoá thông báo \(\mathrm{Msg}\) bằng dữ liệu liên kết\(\mathrm{AssociatedData}\), chúng ta sẽ tạo một tiêu đề, chia thông báo thành nhiều phân đoạn, mã hoá từng phân đoạn và nối các phân đoạn đã mã hoá.

Tạo tiêu đề

Chúng tôi chọn một chuỗi ngẫu nhiên đồng nhất \(\mathrm{Salt}\) có độ dài\(\mathrm{DerivedKeySize}\) và một chuỗi ngẫu nhiên đồng nhất \(\mathrm{NoncePrefix}\)có độ dài là 7.

Sau đó, chúng tôi đặt \(\mathrm{Header} := \mathrm{len}(\mathrm{Header}) \| \mathrm{Salt} \| \mathrm{NoncePrefix}\), trong đó độ dài của tiêu đề được mã hoá dưới dạng một byte. Xin lưu ý rằng \(\mathrm{len}(\mathrm{Header}) \in \{24, 40\}\).

Tiếp theo, chúng tôi sử dụng HKDF3 với hàm băm được cung cấp bởi \(\mathrm{HkdfHashType}\) và dữ liệu đầu vào \(\mathrm{ikm} := \mathrm{KeyValue}\), \(\mathrm{salt} := \mathrm{Salt}\)và \(\mathrm{info} := \mathrm{AssociatedData}\), với độ dài đầu ra \(\mathrm{DerivedKeySize}\). Chúng ta gọi kết quả này là \(\mathrm{DerivedKey}\).

Tách tin nhắn

Tiếp theo, thông báo \(\mathrm{Msg}\) sẽ được chia thành các phần: \(\mathrm{Msg} = M_0 \| M_1 \| \cdots \| M_{n-1}\).

Độ dài của quảng cáo được chọn để đáp ứng:

  • \(\mathrm{len}(M_0) \in \{0,\ldots, \mathrm{CiphertextSegmentSize} - \mathrm{len}(\mathrm{Header}) - \mathrm{16}\}\).
  • Nếu \(n>1\), thì \(\mathrm{len}(M_1), \ldots, \mathrm{len}(M_{n-1}) \in \{1,\ldots, \mathrm{CiphertextSegmentSize} - \mathrm{16}\}\).
  • Nếu là \(n>1\), thì \(\mathrm{len}(M_{0}), \ldots, \mathrm{len}(M_{n-2})\) phải có độ dài tối đa theo các điều kiện ràng buộc ở trên.

\(n\) có thể tối đa là \(2^{32}\). Nếu không, sẽ không mã hoá được.

Mã hoá các khối

Để mã hoá phân đoạn \(M_i\), chúng tôi tính toán \(\mathrm{IV}_i := \mathrm{NoncePrefix} \| \mathrm{i} \| b\), trong đó \(\mathrm{i}\) là 4 byte theo phương thức mã hoá Big-endian và byte $b$ là 0x00 nếu $i < n-1$ và ngược lại là 0x01.

Sau đó, chúng tôi mã hoá \(M_i\) bằng AES-GCM4, trong đó khoá là\(\mathrm{DerivedKey}\), vectơ khởi tạo là \(\mathrm{IV}_i\)và dữ liệu liên quan là chuỗi trống. \(C_i\) là kết quả của quá trình mã hoá này (tức là việc nối \(C\) và \(T\) trong mục 5.2.1.2 của tệp tham chiếu AES-GCM được liên kết).

Nối các phân đoạn đã mã hoá

Cuối cùng, tất cả các phân đoạn được nối dưới dạng \(\mathrm{Header} \| C_0 \| \cdots \| C_{n-1}\), đây là văn bản mật mã cuối cùng.

Giải mã

Quá trình giải mã sẽ đảo ngược quá trình mã hoá. Chúng tôi sử dụng tiêu đề để lấy \mathrm{NoncePrefix}$$ và giải mã từng phân đoạn của thuật toán mật mã.

API có thể (và thường cho phép) cho phép truy cập ngẫu nhiên hoặc truy cập vào đầu tệp mà không cần kiểm tra phần cuối tệp. Điều này là có chủ ý vì có thể giải mã \(M_i\) từ \(C_i\)mà không cần giải mã tất cả các khối mật mã trước đó và còn lại.

Tuy nhiên, các API phải cẩn thận để không cho phép người dùng nhầm lẫn giữa lỗi kết thúc tệp và lỗi giải mã: trong cả hai trường hợp, API có thể phải trả về lỗi và việc bỏ qua sự khác biệt có thể dẫn đến việc đối thủ có thể cắt bớt tệp một cách hiệu quả.

Tuần tự hoá và phân tích cú pháp khoá

Để chuyển đổi tuần tự một khoá ở định dạng "Tink Proto", trước tiên, chúng tôi ánh xạ các tham số một cách rõ ràng vào proto được cung cấp tại aes_gcm_hkdf_streaming.proto. Bạn cần đặt trường version thành 0. Sau đó, chúng tôi sẽ chuyển đổi tuần tự dữ liệu này bằng cách sử dụng tính năng chuyển đổi tuần tự proto thông thường rồi nhúng chuỗi kết quả vào giá trị của trường của proto KeyData. Chúng ta đặt trường type_url thành type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey. Sau đó, chúng ta đặt key_material_type thành SYMMETRIC và nhúng tệp này vào một tập hợp khoá. Chúng tôi thường đặt output_prefix_type thành RAW. Trường hợp ngoại lệ là nếu khoá được phân tích cú pháp với tập hợp giá trị khác cho output_prefix_type, thì Tink có thể ghi RAW hoặc giá trị trước đó.

Để phân tích cú pháp một khoá, chúng ta đảo ngược quy trình trên (theo cách thông thường khi phân tích cú pháp các giao thức). Trường key_material_type sẽ bị bỏ qua. Bạn có thể bỏ qua giá trị của output_prefix_type hoặc từ chối các khoá có output_prefix_type khác với RAW. Các khoá có version khác 0 phải bị từ chối.

Vấn đề đã biết

Cách triển khai hàm mã hoá nêu trên dự kiến sẽ không an toàn cho nhánh phát triển. Xem bài viết An toàn về ngã ba.

Tài liệu tham khảo


  1. Hoàng, Reyhanitabar, Rogaway, Vizar, 2015. Phương thức mã hoá xác thực trực tuyến và khả năng chống sử dụng lại số chỉ dùng một lần. CRYPTO 2015. https://eprint.iacr.org/2015/189 

  2. Hoàng, Shen, 2020. Tính bảo mật của tính năng mã hoá truyền trực tuyến trong Thư viện tink của Google. https://eprint.iacr.org/2020/1019 

  3. RFC 5869. Hàm dẫn xuất khoá Trích xuất và mở rộng dựa trên HMAC (HKDF). https://www.rfc-editor.org/rfc/rfc5869 

  4. NIST SP 800-38D. Đề xuất cho chế độ hoạt động của thuật toán mật mã khối: Chế độ Galois/Counter Mode (GCM) và GMAC. https://csrc.nist.gov/pubs/sp/800/38/d/final