Trung tâm phát triển văn hóa đọc Nhà văn

Mật mã học xác thực AEAD – mã hóa và xác thực trong một bước

Giải thích đầy đủ AEAD (Authenticated Encryption with Associated Data) – mô hình bảo mật IND-CPA và INT-CTXT, vai trò dữ liệu liên kết, so sánh AES-GCM, ChaCha20-Poly1305 và AES-CBC-HMAC, cùng các nguyên tắc triển khai an toàn trong Signal Protocol.

44 phút đọc.

0 lượt xem.

AEAD là lớp mã hóa hiện đại kết hợp đồng thời tính bí mật và tính toàn vẹn trong một thao tác duy nhất, loại bỏ các lỗ hổng kinh điển xuất hiện khi mã hóa và xác thực được xây dựng riêng biệt rồi ghép lại.

Giới thiệu

Bài viết này mô tả mã hóa xác thực với dữ liệu liên kết AEAD (Authenticated Encryption with Associated Data – Mã hóa xác thực với dữ liệu liên kết), lớp mã hóa được Signal Protocol sử dụng như thành phần cuối cùng trong chuỗi bảo vệ tin nhắn. Sau khi X3DH thiết lập khóa phiên SK, sau khi Double Ratchet dẫn xuất khóa tin nhắn mk cho từng tin nhắn riêng lẻ, chính AEAD là thành phần trực tiếp mã hóa nội dung tin nhắn và đảm bảo rằng bất kỳ sự thay đổi nào đối với bản mã – dù chỉ một bit – sẽ bị phát hiện và từ chối tức thì khi giải mã.

Tên gọi Authenticated Encryption phản ánh bản chất kép của AEAD: encryption (mã hóa) đảm bảo tính bí mật – nội dung tin nhắn không thể đọc được nếu không có khóa; authenticated (xác thực) đảm bảo tính toàn vẹn và xác thực nguồn gốc – bất kỳ ai giả mạo hay sửa đổi bản mã đều bị phát hiện. Phần with Associated Data (với dữ liệu liên kết) bổ sung khả năng xác thực thêm một số dữ liệu được gửi dạng văn bản rõ cùng bản mã – như tiêu đề gói tin hay siêu dữ liệu giao thức – đảm bảo rằng chúng không bị sửa đổi dù không được mã hóa. Trong Double Ratchet, dữ liệu liên kết là tiêu đề tin nhắn chứa khóa Ratchet công khai và số thứ tự – thông tin cần truyền dưới dạng rõ để người nhận biết cách giải mã nhưng cần được xác thực để kẻ tấn công không thể sửa đổi.

Trước khi AEAD được chuẩn hóa và phổ biến vào đầu những năm 2000, hầu hết các giao thức bảo mật xây dựng mã hóa và xác thực như hai thành phần riêng biệt rồi kết hợp theo các thứ tự khác nhau. Thực tiễn đó tạo ra một loạt các lỗ hổng nghiêm trọng – từ tấn công padding oracle phá vỡ TLS 1.0 đến tấn công lựa chọn bản mã trên SSH – phần lớn xuất phát từ việc xác thực được áp dụng ở sai tầng hoặc sai thứ tự so với mã hóa. AEAD giải quyết tất cả các vấn đề đó bằng cách cung cấp một giao diện duy nhất, đã được phân tích hình thức, đảm bảo cả hai tính chất cùng một lúc và theo thứ tự đúng đắn về mặt mật mã.

Trong Signal Protocol, AEAD xuất hiện tại ba điểm chính: trong hàm ENCRYPT(mk, plaintext, associated_data)DECRYPT(mk, ciphertext, associated_data) của Double Ratchet; trong mã hóa bản mã ban đầu của X3DH và PQXDH bằng khóa SK mới thiết lập; và trong mã hóa tiêu đề tin nhắn của biến thể Double Ratchet với header encryption. Mỗi điểm đó có các yêu cầu cụ thể về sơ đồ AEAD, cách quản lý nonce và xử lý lỗi – tất cả đều được đặc tả Signal Protocol định nghĩa rõ ràng để tránh các lỗ hổng triển khai phổ biến.

Nền tảng lý thuyết

Để hiểu tại sao AEAD được thiết kế theo cách nó hoạt động và tại sao các giải pháp đơn giản hơn không đủ, cần nắm rõ ba nền tảng lý thuyết: bài toán mã hóa xác thực và các điểm yếu lịch sử của các cách tiếp cận ngây thơ; mô hình bảo mật IND-CPA và INT-CTXT định nghĩa chính xác những gì AEAD cần đảm bảo; và vai trò của dữ liệu liên kết trong bức tranh bảo mật tổng thể.

Bài toán mã hóa xác thực và những giới hạn của mã hóa đơn thuần

Mã hóa đối xứng thông thường – như AES trong chế độ CBC hay CTR – chỉ đảm bảo tính bí mật (confidentiality): kẻ không có khóa không thể đọc nội dung. Tuy nhiên, mã hóa đơn thuần không đảm bảo tính toàn vẹn (integrity) hay tính xác thực nguồn gốc (authenticity): kẻ tấn công không biết khóa vẫn có thể sửa đổi bản mã theo những cách có chủ đích, và khi người nhận giải mã, họ sẽ nhận được một thông điệp đã bị giả mạo mà không hề hay biết.

Tấn công padding oracle là ví dụ điển hình nhất về hậu quả của mã hóa không có xác thực. Trong AES-CBC với đệm PKCS#7, máy chủ giải mã bản mã và trả về hai loại lỗi khác nhau: lỗi đệm không hợp lệ và lỗi xử lý nội dung. Sự khác biệt tưởng chừng vô hại này biến máy chủ thành một oracle giải mã: kẻ tấn công gửi các bản mã đã sửa đổi và quan sát loại lỗi để suy ra từng byte bản rõ, hoàn toàn mà không cần biết khóa. Cuộc tấn công này được Serge Vaudenay (1968–) phát hiện năm 2002 và sau đó được chứng minh là có thể áp dụng thực tế trên nhiều giao thức, bao gồm TLS 1.0 (tấn công BEAST năm 2011) và ASP.NET (tấn công năm 2010 của Rizzo và Duong). Nguyên nhân gốc rễ không phải là AES-CBC yếu về mật mã, mà là hệ thống giải mã trước khi xác thực tính toàn vẹn, cho phép kẻ tấn công khai thác phản hồi từ quá trình giải mã.

Tấn công bit-flipping trên CTR mode là một ví dụ khác. Trong AES-CTR, bản mã là XOR của bản rõ với keystream: C = P ⊕ KS. Nếu kẻ tấn công biết rằng byte thứ i của bản rõ là 0x00 (giá trị phổ biến như khoảng trắng hay null byte), họ có thể đảo bit của byte tương ứng trong bản mã để khiến byte đó khi giải mã thành bất kỳ giá trị nào mong muốn: C’[i] = C[i] ⊕ target sẽ giải mã thành P’[i] = C’[i] ⊕ KS[i] = P[i] ⊕ target ⊕ KS[i] = 0x00 ⊕ target ⊕ 0x00 = target. Kẻ tấn công không cần biết khóa hay keystream – họ chỉ cần biết (hay đoán) một phần bản rõ để sửa đổi có chủ đích phần tương ứng. Trong các ứng dụng thực tế như cookie session mã hóa hay tin nhắn có định dạng cố định, điều này cho phép giả mạo nội dung mà người nhận không phát hiện được.

Những cuộc tấn công này thúc đẩy cộng đồng mật mã học chuyển sang AEAD như tiêu chuẩn mặc định thay vì cố gắng kết hợp mã hóa và xác thực theo các cách thủ công. Phillip Rogaway (1963–) và Mihir Bellare đặt nền tảng lý thuyết cho AEAD qua một loạt bài báo từ cuối những năm 1990 đến đầu những năm 2000, chuẩn hóa định nghĩa và yêu cầu bảo mật. Sau nhiều năm nghiên cứu, NIST tổ chức cuộc thi CAESAR (Competition for Authenticated Encryption: Security, Applicability, and Robustness) từ 2013 đến 2019 để tìm kiếm các sơ đồ AEAD tốt nhất cho nhiều ngữ cảnh ứng dụng khác nhau, phản ánh tầm quan trọng của lĩnh vực này trong bảo mật hiện đại.

Mô hình bảo mật IND-CPA và INT-CTXT

Bảo mật của AEAD được định nghĩa chính xác thông qua hai mô hình bổ sung cho nhau: IND-CPA (Indistinguishability under Chosen Plaintext Attack – Không thể phân biệt dưới tấn công lựa chọn bản rõ) cho tính bí mật, và INT-CTXT (Integrity of Ciphertexts – Tính toàn vẹn của bản mã) cho tính xác thực.

Mô hình IND-CPA định nghĩa tính bí mật thông qua một trò chơi giữa kẻ tấn công và một thách thức (challenger). Kẻ tấn công có thể gửi bất kỳ cặp bản rõ (m₀, m₁) nào có cùng độ dài cho thách thức, và nhận lại bản mã của một trong hai bản rõ được chọn ngẫu nhiên. Kẻ tấn công có thể thực hiện bao nhiêu truy vấn tùy ý (lựa chọn bản rõ) trước và sau khi nhận bản mã thách thức. Sơ đồ mã hóa là IND-CPA an toàn nếu không có kẻ tấn công đa thức nào có thể đoán đúng bản rõ nào được mã hóa với xác suất cao hơn 1/2 đáng kể. Nói ngắn gọn: bản mã không tiết lộ bất kỳ thông tin nào về bản rõ, ngay cả khi kẻ tấn công có thể chọn bản rõ để mã hóa. Điều kiện cơ bản để đạt IND-CPA là sơ đồ mã hóa phải ngẫu nhiên (probabilistic) – mỗi lần mã hóa cùng bản rõ phải cho ra bản mã khác nhau. Đây là lý do tại sao AES-ECB (Electronic Code Book), mã hóa mỗi khối độc lập với cùng khóa, không thể đạt IND-CPA: cùng khối bản rõ luôn cho ra cùng khối bản mã, tiết lộ cấu trúc của bản rõ qua bản mã.

Mô hình INT-CTXT định nghĩa tính toàn vẹn cũng thông qua một trò chơi: kẻ tấn công có thể yêu cầu mã hóa bất kỳ bản rõ nào, nhận bản mã tương ứng, nhưng mục tiêu là tạo ra một bản mã mới (chưa từng được mã hóa trước đó) mà hàm giải mã chấp nhận là hợp lệ. Sơ đồ là INT-CTXT an toàn nếu không có kẻ tấn công đa thức nào có thể tạo bản mã giả mạo hợp lệ với xác suất đáng kể. Lưu ý rằng INT-CTXT mạnh hơn INT-PTXT (Integrity of Plaintexts): INT-PTXT cho phép kẻ tấn công tạo bản mã giả mạo miễn là nó giải mã thành bản rõ đã từng được mã hóa trước đó (tấn công phát lại), trong khi INT-CTXT yêu cầu bản mã phải hoàn toàn mới – tức là không thể phát lại. AEAD thường yêu cầu cả hai tính chất và cộng thêm tính chống phát lại qua cơ chế nonce.

Bảo mật đầy đủ của AEAD, ký hiệu là Authenticated Encryption security hay AE security, được định nghĩa là đạt đồng thời IND-CPA và INT-CTXT. Phillip Rogaway và Mihir Bellare chứng minh rằng hai tính chất này là độc lập và bổ sung cho nhau: có thể xây dựng sơ đồ đạt IND-CPA nhưng không đạt INT-CTXT (mã hóa đơn thuần) và ngược lại. Chỉ khi đạt cả hai, sơ đồ mới an toàn trong mô hình đối thủ mạnh nhất – kẻ tấn công có thể chọn bản rõ tùy ý và cố tình giả mạo bản mã. Điều quan trọng là tính chất AE tổng hợp này có thể phân rã: bất kỳ vi phạm nào đối với IND-CPA hay INT-CTXT đều là vi phạm tính chất AE tổng thể, cho phép phân tích bảo mật từng thành phần độc lập rồi kết hợp.

Bảo mật hậu lượng tử của AEAD là một câu hỏi riêng biệt quan trọng trong bối cảnh PQXDH. Thuật toán Grover của máy tính lượng tử có thể tìm kiếm không gian khóa theo căn bậc hai: tấn công brute-force khóa 128 bit cần 2^128 phép tính trên máy cổ điển nhưng chỉ cần 2^64 phép tính lượng tử. Do đó, để đạt bảo mật 128 bit lượng tử (tiêu chuẩn NIST Level 1), khóa AEAD cần có ít nhất 256 bit – lý do tại sao Signal Protocol khuyến nghị AES-256-GCM hay ChaCha20-Poly1305 với khóa 256 bit thay vì các biến thể 128 bit.

Dữ liệu liên kết và tính xác thực bổ sung

Phần Associated Data trong tên gọi AEAD giải quyết một tình huống phổ biến trong thiết kế giao thức: cần mã hóa một số trường trong gói tin nhưng để một số trường khác ở dạng văn bản rõ để các thành phần trung gian (như bộ định tuyến hay proxy) có thể xử lý mà không cần giải mã. Tuy nhiên, dù để ở dạng văn bản rõ, các trường đó vẫn cần được bảo vệ chống sửa đổi – nếu kẻ tấn công có thể thay đổi tiêu đề gói tin, họ có thể định tuyến lại tin nhắn đến sai người nhận, thay đổi số thứ tự để gây lỗi giải mã, hay sửa metadata giao thức để khai thác logic xử lý ở tầng ứng dụng.

Dữ liệu liên kết AD là chuỗi byte được xác thực nhưng không được mã hóa: nó được đưa vào quá trình tính thẻ xác thực nhưng không xuất hiện trong bản mã đầu ra. Người nhận cung cấp cùng giá trị AD trong quá trình giải mã; nếu AD khác với lúc mã hóa – kể cả thay đổi một bit – giải mã thất bại và bản mã bị từ chối. Điều quan trọng là tính bảo mật của AEAD đảm bảo rằng thẻ xác thực phụ thuộc vào cả AD lẫn bản rõ theo cách không thể chia cắt: kẻ tấn công không thể tạo một cặp (AD’, CT’) hợp lệ từ AD gốc và CT gốc nếu AD’ ≠ AD, trừ khi họ biết khóa.

Trong Double Ratchet, AD là chuỗi được tính từ dữ liệu liên kết của phiên (thường là Encode(IKA) || Encode(IKB) từ X3DH) nối với tiêu đề tin nhắn mã hóa (chứa khóa Ratchet công khai, số thứ tự và độ dài chuỗi trước đó). Cấu trúc này đảm bảo hai tính chất quan trọng: thứ nhất, bản mã tin nhắn chỉ hợp lệ khi đi kèm đúng tiêu đề – kẻ tấn công không thể hoán đổi bản mã của một tin nhắn với tiêu đề của tin nhắn khác; thứ hai, SK của phiên (được tích hợp vào AD qua Encode(IKA) || Encode(IKB)) ràng buộc bản mã với danh tính cụ thể của hai bên – bản mã từ một phiên không thể phát lại sang phiên khác dù dùng cùng khóa tin nhắn mk. Tính chất ràng buộc ngữ cảnh này của AD là lý do tại sao AEAD an toàn hơn đáng kể so với mã hóa đơn thuần kết hợp với MAC riêng biệt: tính toàn vẹn không chỉ bao phủ bản mã mà còn bao phủ toàn bộ ngữ cảnh sử dụng bản mã đó.

Một lưu ý kỹ thuật quan trọng: nếu AD không được đảm bảo là có thể phân tích (parseable) một cách duy nhất, có thể phát sinh tấn công ghép nối. Ví dụ, nếu AD = A || B mà không có dấu phân cách hay tiền tố độ dài, kẻ tấn công có thể tạo A’ || B’ với A’ || B’ = A || BA’ ≠ AB’ ≠ B, qua đó làm lẫn lộn ngữ cảnh. Đặc tả Double Ratchet giải quyết bằng hàm CONCAT(ad, header) mã hóa tiêu đề thành chuỗi byte có thể phân tích rồi thêm ad vào phía trước với tiền tố độ dài nếu cần, đảm bảo toàn bộ chuỗi AD được phân tích duy nhất.

Cấu trúc AEAD

AEAD định nghĩa một giao diện gồm hai hàm đối xứng: ENCRYPTDECRYPT, cùng với một số yêu cầu về cách sử dụng khóa và nonce để đảm bảo bảo mật trong thực tế. Phần này trình bày cấu trúc giao diện, vai trò và yêu cầu của nonce, và cấu tạo cùng kích thước tối thiểu của thẻ xác thực.

Giao diện mã hóa và giải mã

Hàm mã hóa AEAD nhận bốn đầu vào và cho một đầu ra:

CT = AEAD-Encrypt(K, N, AD, PT)

Trong đó K là khóa bí mật (thường 256 bit); N là nonce (number used once – số chỉ dùng một lần, thường 96 hay 128 bit); AD là dữ liệu liên kết (tùy ý, có thể rỗng); PT là bản rõ (plaintext, độ dài tùy ý); và CT là bản mã đầu ra có độ dài bằng PT cộng thêm một thẻ xác thực (authentication tag) thường 128 bit. Thẻ xác thực được tính từ cả K, N, AD lẫn PT, và được đính kèm vào cuối bản mã đầu ra.

Hàm giải mã nhận cùng khóa, nonce và dữ liệu liên kết, cùng với bản mã:

PT hoặc LỖI = AEAD-Decrypt(K, N, AD, CT)

Trước tiên, giải mã tách thẻ xác thực khỏi CT và xác minh tính hợp lệ của nó đối với toàn bộ CT (bao gồm phần bản mã thực sự) và AD. Chỉ khi xác thực thành công, giải mã mới thực sự giải mã phần bản mã để lấy PT. Nếu xác thực thất bại – dù vì khóa sai, nonce sai, bản mã bị sửa đổi hay AD không khớp – hàm trả về lỗi và không giải mã bất kỳ phần nào của bản mã. Thứ tự này – xác thực trước, giải mã sau – là điểm khác biệt quan trọng so với cách kết hợp thủ công không đúng thứ tự dẫn đến các cuộc tấn công như padding oracle.

Một thuộc tính thiết yếu của AEAD là tính không thể uốn nắn (non-malleability): không tồn tại thuật toán hiệu quả nào có thể biến đổi bản mã hợp lệ CT thành bản mã hợp lệ khác CT’ (với CT’ ≠ CT) mà không biết khóa K, ngay cả khi cho phép CT’ giải mã thành bản rõ khác. Tính chất này mạnh hơn INT-CTXT một chút và đảm bảo rằng kẻ tấn công không thể thực hiện bất kỳ biến đổi có nghĩa nào đối với bản mã – toàn bộ hoặc từng phần – mà không bị phát hiện. Trong bối cảnh Double Ratchet, tính không thể uốn nắn đảm bảo rằng kẻ tấn công không thể sửa đổi nội dung tin nhắn được mã hóa theo bất kỳ cách nào có kiểm soát, ngay cả khi họ biết cấu trúc định dạng của bản rõ.

Đặc tả Double Ratchet định nghĩa hàm ENCRYPT(mk, plaintext, associated_data)DECRYPT(mk, ciphertext, associated_data) theo đúng giao diện AEAD này. Khóa tin nhắn mk đóng vai trò K; nonce được xử lý theo một trong bốn cách: cố định ở hằng số (được phép vì mỗi mk chỉ dùng một lần), tạo từ mk và khóa mã hóa độc lập, tạo như đầu ra bổ sung từ KDF_CK, hoặc chọn ngẫu nhiên và truyền kèm. Lựa chọn giữa bốn cách này ảnh hưởng đến chi phí lưu trữ và truyền tải nhưng không ảnh hưởng đến tính bảo mật cơ bản miễn là mỗi cặp (K, N) chỉ được dùng một lần.

Nonce và yêu cầu không tái sử dụng

Nonce (Number Used Once) là giá trị được đưa vào quá trình mã hóa để đảm bảo rằng cùng một bản rõ với cùng một khóa sẽ cho ra bản mã khác nhau mỗi lần – điều kiện cần thiết để đạt IND-CPA. Nonce không cần giữ bí mật và thường được truyền kèm bản mã dưới dạng văn bản rõ. Điều kiện quan trọng duy nhất là không bao giờ tái sử dụng cùng một nonce với cùng một khóa.

Hậu quả của việc tái sử dụng nonce phụ thuộc vào sơ đồ AEAD cụ thể nhưng thường rất nghiêm trọng. Trong AES-GCM, tái sử dụng cặp (K, N) cho hai bản mã (CT₁, CT₂) cho phép kẻ tấn công tính CT₁ ⊕ CT₂ = PT₁ ⊕ PT₂ (vì cùng keystream được dùng để mã hóa cả hai). Nếu biết một trong hai bản rõ – hay biết cấu trúc định dạng của chúng – kẻ tấn công có thể khôi phục hoàn toàn bản rõ kia. Tệ hơn nữa, trong AES-GCM, tái sử dụng nonce còn cho phép tính toán khóa xác thực (authentication key), từ đó có thể giả mạo bất kỳ bản mã nào dùng cùng khóa và nonce đó. Đây là cuộc tấn công nonce misuse và nó phá vỡ hoàn toàn cả tính bí mật lẫn tính xác thực.

Signal Protocol xử lý yêu cầu nonce bằng cách khai thác thực tế là mỗi khóa tin nhắn mk trong Double Ratchet chỉ được dùng đúng một lần. Vì mk là duy nhất cho mỗi tin nhắn (được tạo từ bước tăng không thể tái tạo trong chuỗi KDF), sử dụng nonce hằng số (thường là chuỗi toàn số 0) với mỗi mk là an toàn hoàn toàn: không bao giờ có hai bản mã được tạo từ cùng cặp (mk, nonce_0). Thiết kế này đơn giản hóa triển khai và loại bỏ toàn bộ lớp rủi ro liên quan đến quản lý nonce – nguồn gốc của nhiều lỗ hổng bảo mật trong thực tế khi lập trình viên tái sử dụng counter hay nonce ngẫu nhiên chất lượng thấp.

Trong các ngữ cảnh khác – như tiêu đề tin nhắn trong Double Ratchet với header encryption, hay mã hóa bản mã ban đầu trong X3DH – nonce phải được tạo ngẫu nhiên với ít nhất 128 bit entropy và đảm bảo không tái sử dụng. Hàm HENCRYPT(hk, plaintext) trong đặc tả header encryption yêu cầu nonce AEAD phải là giá trị không lặp lại có trạng thái (stateful counter) hoặc giá trị ngẫu nhiên với ít nhất 128 bit entropy. Yêu cầu 128 bit cho nonce ngẫu nhiên xuất phát từ nghịch lý sinh nhật: với nonce 96 bit (chuẩn của AES-GCM), xác suất tái sử dụng sau 2^48 bản mã là khoảng 50%, quá thấp cho các hệ thống lớn; với nonce 128 bit, giới hạn an toàn tăng lên 2^64 bản mã – đủ cho mọi ứng dụng thực tế.

Các biến thể AEAD có khả năng chịu lỗi nonce (nonce-misuse resistant) như AES-GCM-SIV (SIV là Synthetic IV) hay AES-SIV cung cấp một lớp bảo vệ bổ sung: kể cả khi nonce bị tái sử dụng vô tình, bảo mật chỉ bị suy giảm đến mức tính toàn vẹn vẫn được bảo toàn và kẻ tấn công chỉ biết hai bản rõ đã được mã hóa dùng cùng khóa chứ không thể giả mạo. Đặc tả Double Ratchet đề cập đến AES-SIV như một lựa chọn vì khả năng chịu lỗi nonce này – phù hợp cho các trường hợp triển khai không thể đảm bảo tuyệt đối nonce là duy nhất do lỗi phần cứng hay khôi phục từ bản sao lưu.

Thẻ xác thực và độ dài tối thiểu

Thẻ xác thực (authentication tag) là thành phần tạo nên sự khác biệt cơ bản giữa AEAD và mã hóa đơn thuần. Đây là giá trị mật mã có độ dài cố định được tính từ toàn bộ nội dung mã hóa (bao gồm K, N, AD và bản mã) và đính kèm vào bản mã đầu ra. Người nhận tính lại thẻ xác thực từ dữ liệu nhận được và so sánh với thẻ trong bản mã; chỉ khi hai thẻ khớp chính xác mới thực hiện giải mã.

Độ dài thẻ xác thực quyết định xác suất một kẻ tấn công có thể giả mạo bản mã hợp lệ bằng cách đoán thẻ đúng. Với thẻ t bit, xác suất đoán đúng một lần là 2^(−t). Với thẻ 128 bit (tiêu chuẩn của AES-GCM và ChaCha20-Poly1305), kẻ tấn công cần khoảng 2^128 lần thử để tạo được một bản mã giả mạo hợp lệ – cùng mức độ khó với tấn công brute-force trên khóa AES-128. Đây là lý do các sơ đồ AEAD hiện đại đều dùng thẻ 128 bit như tiêu chuẩn mặc định và không khuyến nghị cắt bớt xuống dưới mức này.

Đặc tả Double Ratchet có một điều khoản đặc biệt về cắt thẻ xác thực: nếu dùng AES-CBC với HMAC, có thể cắt đầu ra HMAC xuống còn 128 bit để giảm kích thước tin nhắn, và trong mọi trường hợp, HMAC cuối cùng không nên bị cắt xuống dưới 64 bit. Điều khoản 64 bit tối thiểu xuất phát từ phân tích cụ thể: với thẻ 64 bit, kẻ tấn công cần 2^64 lần thử để giả mạo – vẫn đủ an toàn trước tấn công thực tế khi mỗi lần thử đòi hỏi truy vấn mạng và nhận phản hồi. Tuy nhiên, cắt xuống dưới 64 bit đưa xác suất giả mạo vào vùng có thể khai thác được trong điều kiện tấn công hiện đại, đặc biệt khi kẻ tấn công có thể thực hiện hàng triệu truy vấn song song.

So sánh với thẻ xác thực của HMAC đơn thuần: HMAC không nhất thiết phải tích hợp với mã hóa và có thể bị tách rời nếu không cẩn thận. Trong sơ đồ Encrypt-then-MAC (mã hóa rồi MAC, thứ tự đúng đắn), HMAC được tính trên bản mã, đảm bảo toàn vẹn. Tuy nhiên, ngay cả thứ tự đúng cũng không đảm bảo an toàn đầy đủ nếu MAC và khóa mã hóa không được phân tách miền đúng cách hay nếu thuật toán MAC cho phép các tấn công độ dài mở rộng. AEAD loại bỏ toàn bộ các vấn đề này bằng cách cung cấp một giao diện thống nhất, trong đó thẻ xác thực là phần không thể tách rời của sơ đồ và được tính theo cách không thể khai thác độ dài mở rộng.

Các sơ đồ AEAD phổ biến

Signal Protocol đặc tả ba sơ đồ AEAD theo thứ tự ưu tiên giảm dần: SIV hay AES-CBC-HMAC, và cung cấp khuyến nghị cụ thể về cách xây dựng từ AES-CBC và HMAC. Ngoài đặc tả Signal Protocol, hai sơ đồ phổ biến rộng rãi nhất trong thực tế là AES-GCM và ChaCha20-Poly1305. Phần này trình bày cả ba sơ đồ, phân tích ưu nhược điểm và điều kiện sử dụng phù hợp.

AES-GCM – sơ đồ phổ biến nhất hiện nay

AES-GCM (Galois/Counter Mode) là sơ đồ AEAD phổ biến nhất hiện tại, được NIST tiêu chuẩn hóa năm 2007 và được tích hợp trong TLS 1.2, TLS 1.3, QUIC, SSH, IPsec và hầu hết các giao thức bảo mật hiện đại. GCM kết hợp hai thành phần: chế độ counter (CTR mode) của AES để mã hóa, và phép nhân Galois (GF(2^128)) để tạo thẻ xác thực.

Phần mã hóa của AES-GCM hoạt động theo chế độ CTR: từ nonce N và khóa K, tạo ra một keystream bằng cách mã hóa các counter tuần tự (N || 0), (N || 1), (N || 2), … và XOR với bản rõ. Không có padding cần thiết vì XOR hoạt động trực tiếp trên từng byte. Điều này làm cho AES-CTR (và AES-GCM) an toàn trước tấn công padding oracle: không có padding, không có oracle padding.

Phần xác thực sử dụng phép tính GHASH – một hàm tuyến tính trên trường GF(2^128) – để tính thẻ xác thực từ AD, bản mã và một khóa xác thực H = AES_K(0^128) được tạo từ khóa và nonce. GHASH tính một đa thức có hệ số là các khối 128-bit của AD và bản mã, đánh giá tại điểm H. Kết quả được kết hợp với một giá trị mã hóa của nonce để tạo thẻ xác thực cuối cùng.

Ưu điểm lớn nhất của AES-GCM là hiệu suất phần cứng: tất cả CPU x86-64 hiện đại đều có lệnh AES-NI cho phép thực hiện từng vòng AES trong một lệnh phần cứng, và lệnh PCLMULQDQ tăng tốc phép nhân Galois. Kết quả là AES-256-GCM đạt thông lượng 10–40 GB/s trên phần cứng hiện đại – nhanh hơn băng thông mạng của hầu hết các thiết bị và gần đạt tốc độ đọc ổ SSD. Phần cứng di động cũng ngày càng có tăng tốc AES-NI, giúp AES-GCM hiệu quả trên điện thoại thông minh.

Điểm yếu của AES-GCM nằm ở tính nhạy cảm với nonce: như đã phân tích, tái sử dụng nonce không chỉ phá vỡ tính bí mật mà còn cho phép kẻ tấn công tính khóa xác thực H và giả mạo bất kỳ bản mã nào. Điểm yếu thứ hai là phép nhân Galois trong GHASH là tuyến tính, tức là kẻ tấn công biết bố cục của AD và bản mã có thể khai thác các tính chất đại số của GCM để tạo ra một số dạng tấn công đặc biệt – đáng chú ý nhất là tấn công phân biệt (distinguishing attack) khi nonce bị tái sử dụng. Với nonce ngẫu nhiên 96 bit, giới hạn an toàn của AES-GCM thực tế là khoảng 2^32 bản mã dưới cùng khóa (do nghịch lý sinh nhật trên không gian nonce 96 bit), sau đó nên luân chuyển khóa. Với nonce 128 bit, giới hạn tăng lên 2^64 – thực tế là vô giới hạn cho mọi ứng dụng thực tế.

ChaCha20-Poly1305 – lựa chọn tối ưu cho phần mềm

ChaCha20-Poly1305 được Daniel Bernstein thiết kế và công bố năm 2014 như một giải pháp thay thế cho AES-GCM trên các thiết bị không có tăng tốc phần cứng AES. Sơ đồ kết hợp thuật toán mã hóa luồng ChaCha20 (biến thể của Salsa20) với hàm xác thực Poly1305.

ChaCha20 là mật mã luồng (stream cipher) dựa trên cấu trúc ARX (Add-Rotate-XOR): mỗi bước tăng thực hiện một loạt phép cộng modulo 32 bit, phép quay bit và XOR theo một sơ đồ cố định. Không có S-box hay bảng tra cứu, toàn bộ tính toán là phép toán số học đơn giản trực tiếp trên số nguyên 32 bit. Đặc điểm này có hai hệ quả quan trọng: thứ nhất, ChaCha20 không bị ảnh hưởng bởi tấn công kênh cache (cache-timing attack) vì không có bảng tra cứu phụ thuộc vào dữ liệu; thứ hai, ChaCha20 nhanh trên mọi phần cứng chỉ có ALU cơ bản, không cần lệnh đặc biệt.

Poly1305 là hàm xác thực dựa trên trường nguyên tố GF(2^130 – 5). Nhận một khóa ngẫu nhiên 256 bit, Poly1305 tính một đa thức từ các khối 128-bit của thông điệp đầu vào, đánh giá tại điểm r (128 bit đầu của khóa) rồi cộng với s (128 bit còn lại), tất cả modulo 2^130 – 5. Kết quả được cắt lại còn 128 bit để tạo thẻ xác thực. Poly1305 nhanh hơn GHASH của AES-GCM trên phần mềm thuần túy vì phép nhân modulo 2^130 – 5 có thể tối ưu hóa tốt hơn phép nhân Galois modulo 2^128 + 1 bằng phép tính số học số nguyên 64 bit tiêu chuẩn.

Trong ChaCha20-Poly1305, quá trình kết hợp diễn ra như sau: từ khóa K và nonce N, ChaCha20 sinh ra 64 byte đầu tiên của keystream; 32 byte đầu dùng làm khóa cho Poly1305 (bao gồm rs), 32 byte còn lại bị bỏ. ChaCha20 tiếp tục từ counter 1 để tạo keystream mã hóa bản rõ. Poly1305 sau đó nhận AD, bản mã và các giá trị độ dài để tạo thẻ xác thực 128 bit. Thiết kế này đảm bảo khóa Poly1305 được tạo mới cho mỗi (K, N), loại bỏ rủi ro tái sử dụng khóa xác thực.

So sánh thực tế giữa AES-256-GCM và ChaCha20-Poly1305: trên phần cứng có AES-NI (hầu hết laptop và điện thoại cao cấp), AES-256-GCM nhanh hơn khoảng 2–3 lần; trên phần cứng không có AES-NI (điện thoại giá rẻ, vi điều khiển, thiết bị IoT), ChaCha20-Poly1305 nhanh hơn 2–4 lần. Google chọn ChaCha20-Poly1305 làm cipher ưu tiên trong TLS 1.3 cho Android để cải thiện hiệu suất và bảo mật trên các thiết bị tầm thấp. TLS 1.3 hỗ trợ cả hai sơ đồ và thương lượng theo khả năng phần cứng của từng thiết bị.

AES-CBC với HMAC – sơ đồ khuyến nghị trong Double Ratchet

Mặc dù AES-GCM và ChaCha20-Poly1305 là các lựa chọn hiện đại phổ biến, đặc tả Double Ratchet khuyến nghị một sơ đồ cụ thể dựa trên AES-256-CBC và HMAC-SHA256 (hoặc SHA512). Lý do cho sự lựa chọn này không phải là hiệu suất mà là khả năng chịu lỗi lạm dụng (misuse resistance): nếu nonce bị tái sử dụng vô tình (dù thiết kế không cho phép), AES-CBC-HMAC cung cấp bảo vệ tốt hơn AES-GCM trong trường hợp đó.

Quy trình xây dựng sơ đồ AEAD từ AES-256-CBC và HMAC theo đặc tả Double Ratchet:

Bước 1 – Dẫn xuất khóa con:
(enc_key, auth_key, IV) = HKDF(
    IKM  = mk,
    salt = 0^HashLen,
    info = chuỗi cụ thể ứng dụng,
    L    = 80  -- 32 byte enc_key + 32 byte auth_key + 16 byte IV
)

Bước 2 – Mã hóa:
CT = AES-256-CBC-PKCS7(enc_key, IV, plaintext)

Bước 3 – Xác thực:
tag = HMAC-SHA256(auth_key, associated_data || CT)

Bước 4 – Đầu ra:
output = CT || tag

Để giải mã:

Bước 1 – Dẫn xuất khóa con: (giống bước mã hóa)
Bước 2 – Xác thực: kiểm tra tag bằng so sánh thời gian cố định
Bước 3 – Giải mã: chỉ khi xác thực thành công
         PT = AES-256-CBC-UNPAD(enc_key, IV, CT)
Bước 4 – Trả về PT hoặc LỖI

Thiết kế này có một số điểm đáng chú ý. Thứ nhất, HKDF được dùng để tạo enc_key, auth_keyIV từ cùng mk – đảm bảo phân tách miền giữa khóa mã hóa và khóa xác thực, tránh tái sử dụng cùng khóa cho hai mục đích. Thứ hai, IV được tạo xác định từ mk thay vì ngẫu nhiên – vì mk duy nhất cho mỗi tin nhắn, IV cũng duy nhất mà không cần lưu trữ hay truyền tải thêm. Thứ ba, thứ tự là Encrypt-then-MAC (mã hóa rồi tính MAC): HMAC được tính trên bản mã, không phải bản rõ, đảm bảo bất kỳ sửa đổi nào đối với bản mã đều bị phát hiện trước khi giải mã được thực hiện.

Ưu điểm của sơ đồ này so với AES-GCM là khả năng chịu lỗi: nếu vì lý do nào đó cùng IV được dùng với cùng khóa mã hóa, tệ nhất là lộ mối quan hệ giữa các bản rõ qua phân tích bản mã (cùng prefix của bản rõ dẫn đến cùng prefix bản mã), nhưng khóa xác thực độc lập với IV đảm bảo tính toàn vẹn vẫn được bảo toàn. Trong AES-GCM, cùng nonce phá vỡ cả tính bí mật lẫn tính toàn vẹn đồng thời. Nhược điểm là hiệu suất thấp hơn và kích thước thẻ lớn hơn so với AES-GCM (32 byte HMAC-SHA256 so với 16 byte GCM tag), nhưng trong bối cảnh tin nhắn đã có mk duy nhất cho từng tin nhắn, lợi thế chịu lỗi của sơ đồ này được đặc tả Signal Protocol coi là đáng giá.

AEAD trong Signal Protocol

Sau khi đã hiểu lý thuyết và các sơ đồ cụ thể, phần này phân tích chi tiết cách AEAD được sử dụng tại từng điểm trong Signal Protocol, các yêu cầu đặc thù, và sự khác biệt so với các ứng dụng AEAD thông thường.

Vai trò trong Double Ratchet

Trong Double Ratchet, AEAD là thành phần cuối cùng và trực tiếp bảo vệ nội dung tin nhắn. Mỗi tin nhắn được mã hóa bằng khóa tin nhắn mk riêng của nó, được tạo từ một bước tăng trong chuỗi KDF và bị xóa ngay sau khi dùng. Sự độc lập giữa các mk kế tiếp nhau đảm bảo rằng bảo mật AEAD của từng tin nhắn là hoàn toàn độc lập: biết mk của tin nhắn thứ i không giúp tính mk của bất kỳ tin nhắn nào khác. Đây là điều kiện cần thiết để tính chất bảo mật chuyển tiếp và bảo mật tương lai của Double Ratchet có thể hiện thực hóa ở tầng nội dung thực sự của từng tin nhắn.

Dữ liệu liên kết AD trong Double Ratchet được tính từ hàm CONCAT(AD_session, header), trong đó AD_session là dữ liệu liên kết của phiên (từ X3DH, thường là Encode(IKA) || Encode(IKB)) và header là tiêu đề tin nhắn (chứa khóa Ratchet công khai, số thứ tự NPN). Cấu trúc này thực hiện hai chức năng bảo mật cùng lúc: ràng buộc bản mã với định danh phiên (ngăn phát lại sang phiên khác) và ràng buộc bản mã với tiêu đề cụ thể của tin nhắn đó (ngăn kẻ tấn công hoán đổi tiêu đề và bản mã từ các tin nhắn khác nhau trong cùng phiên). Điều này đặc biệt quan trọng trong trường hợp đặc biệt: nếu kẻ tấn công thu thập nhiều tin nhắn mã hóa trong một phiên và cố gắng ghép tiêu đề của tin nhắn này với bản mã của tin nhắn khác để tạo ra tin nhắn giả mạo hợp lệ, xác thực AEAD sẽ từ chối ngay lập tức vì AD không khớp.

Xử lý lỗi xác thực AEAD trong Double Ratchet tuân theo nguyên tắc all-or-nothing: nếu DECRYPT trả về lỗi (xác thực thất bại), toàn bộ trạng thái Double Ratchet không được cập nhật và tin nhắn bị loại bỏ hoàn toàn. Điều này là bắt buộc vì nếu cập nhật trạng thái trước khi xác thực (ví dụ tiến chuỗi KDF hay thực hiện bước tăng DH), trạng thái sẽ mất đồng bộ với thiết bị gửi và các tin nhắn tiếp theo cũng sẽ không giải mã được. Hàm RatchetDecrypt trong đặc tả thực hiện điều này thông qua cơ chế giao dịch: tất cả thay đổi trạng thái được thực hiện trên bản sao tạm thời và chỉ được cam kết khi DECRYPT thành công.

Vai trò trong X3DH và PQXDH

Trong X3DH, AEAD được dùng để mã hóa tin nhắn ban đầu – thường là tin nhắn đầu tiên trong phiên Double Ratchet – bằng khóa phiên SK vừa thiết lập. Đây là điểm khác biệt so với các tin nhắn tiếp theo: SK không phải là khóa tin nhắn duy nhất mà là khóa gốc từ đó chuỗi Double Ratchet bắt đầu. Do đó, khóa thực sự dùng cho AEAD trong tin nhắn ban đầu X3DH thường là SK hoặc một giá trị được tạo từ SK qua PRF – đặc tả nói rõ sử dụng khóa mã hóa là SK hoặc đầu ra của một PRF mật mã được khóa bằng SK. Điều này đảm bảo SK không bao giờ được dùng trực tiếp làm khóa AEAD (tránh rủi ro từ việc SK cũng được dùng trong các ngữ cảnh khác), mà thay vào đó một khóa mã hóa chuyên biệt được dẫn xuất từ SK cho mục đích cụ thể này.

Dữ liệu liên kết trong X3DH là AD = Encode(IKA) || Encode(IKB), có thể mở rộng thêm thông tin định danh bổ sung. Vai trò của AD ở đây là ràng buộc bản mã với danh tính cụ thể của hai bên: nếu kẻ tấn công lấy bản mã ban đầu từ một phiên Mỹ Anh–Đan Nguyên và cố gắng phát lại sang phiên Mỹ Anh–Kỳ Lân (giả sử họ có thể thao túng máy chủ), xác thực AEAD sẽ thất bại vì AD chứa Encode(IKB) (khóa của Đan Nguyên) không khớp với Encode(IKLân) (khóa của Kỳ Lân) mà Mỹ Anh cung cấp khi giải mã. Đây là biện pháp bảo vệ quan trọng chống lại các cuộc tấn công phát lại tin nhắn ban đầu trong môi trường đa người dùng.

Trong PQXDH, một yêu cầu bổ sung liên quan đến dữ liệu liên kết: nếu sơ đồ pqkem không tích hợp PQPKB vào bản mã KEM (một số KEM không làm vậy), Encode(PQPKB) phải được thêm vào AD. Lý do là nếu PQPKB không được ràng buộc vào bản mã AEAD qua AD, kẻ tấn công có thể thực hiện tấn công tái mã hóa KEM: lấy bản mã KEM CT từ một phiên sử dụng khóa KEM PQPKB₁ và đóng gói lại bí mật chung SS cho khóa KEM khác PQPKB₂ (chưa bị xâm phạm). Nếu bản mã AEAD không bị ràng buộc với PQPKB cụ thể, Đan Nguyên không thể phân biệt được PQPKB₁PQPKB₂, dẫn đến chấp nhận phiên bị giả mạo. Thêm Encode(PQPKB) vào AD ràng buộc bản mã AEAD với đúng khóa KEM được dùng, loại bỏ hoàn toàn cuộc tấn công này.

Yêu cầu bảo mật hậu lượng tử

AEAD là một trong những thành phần yếu nhất tiềm năng trong chuỗi bảo mật hậu lượng tử, và lựa chọn đúng đắn có ảnh hưởng trực tiếp đến mức bảo mật thực tế của PQXDH. Thuật toán Grover của máy tính lượng tử có thể tìm kiếm không gian khóa đối xứng theo căn bậc hai: khóa AEAD 128 bit cung cấp khoảng 64 bit bảo mật lượng tử, không đạt tiêu chuẩn NIST Level 1 (yêu cầu ít nhất 128 bit bảo mật lượng tử tương đương 256 bit khóa AES). Do đó, PQXDH yêu cầu aead cung cấp bảo mật IND-CPA và INT-CTXT hậu lượng tử, và chỉ AES-256 (không phải AES-128) hay ChaCha20 với khóa 256 bit mới đáp ứng.

AES-256-GCM đạt tiêu chuẩn NIST Level 1 hậu lượng tử theo đánh giá của NIST: tấn công khóa trên AES-256 với Grover cần khoảng 2^128 phép tính lượng tử – đây chính là ngưỡng Level 1 được định nghĩa là ít nhất khó như tìm kiếm không gian khóa AES-128. Một cuộc tấn công tìm kiếm khóa trên AES-256 bằng Grover cần 2^128 phép tính lượng tử trong khi tìm kiếm khóa trên AES-128 cần 2^64 phép tính lượng tử – tức là AES-256 khó hơn AES-128 (trong không gian lượng tử) một hệ số 2^64. NIST Level 1 được định nghĩa là ít nhất khó như tấn công Grover trên AES-128, tức là yêu cầu ít nhất 2^64 phép tính lượng tử. AES-256 vượt qua yêu cầu này với biên an toàn lớn.

Tuy nhiên, có một điểm tế nhị: mức bảo mật lượng tử của AES-GCM không chỉ phụ thuộc vào khóa mà còn vào độ mạnh của hàm xác thực GHASH. Phân tích hậu lượng tử của GHASH vẫn là một chủ đề nghiên cứu tích cực: thuật toán Simon có thể tấn công một số cấu trúc đối xứng trong mô hình lượng tử thực thể – mô hình trong đó kẻ tấn công có thể truy vấn oracle mã hóa bằng các trạng thái lượng tử. Tuy nhiên, trong mô hình tấn công thực tế hơn – nơi kẻ tấn công chỉ có thể quan sát lưu lượng mã hóa cổ điển – AES-256-GCM vẫn được coi là an toàn ở mức NIST Level 1. Đây là mức bảo mật mà PQXDH nhắm đến cho thành phần AEAD.

Triển khai an toàn

Khoảng cách giữa đặc tả AEAD đúng đắn và triển khai AEAD an toàn trong thực tế là nơi phát sinh nhiều lỗ hổng bảo mật nhất. Phần này trình bày các nguyên tắc và quy trình triển khai không thể bỏ qua.

Quản lý nonce trong môi trường thực tế

Quản lý nonce là thách thức thực tế khó khăn nhất trong triển khai AEAD, đặc biệt trong các hệ thống phân tán và đa thiết bị như Signal Protocol. Lý thuyết đơn giản – mỗi (K, N) chỉ dùng một lần – trở nên phức tạp khi thiết bị có thể bị khởi động lại, khôi phục từ bản sao lưu, hoặc nhiều tiến trình cùng sử dụng chung khóa.

Signal Protocol giải quyết vấn đề nonce bằng cách thiết kế từ gốc để nonce không cần quản lý: mỗi khóa tin nhắn mk trong Double Ratchet được dùng đúng một lần, sau đó bị xóa. Không có cơ chế quản lý nonce vì không cần nonce khác nhau khi khóa luôn là khác nhau. Đây là thiết kế lý tưởng nhưng đòi hỏi nghiêm ngặt rằng mk không bao giờ được tái tạo hay khôi phục sau khi đã dùng – điều này được đảm bảo bởi thiết kế một chiều của chuỗi KDF và yêu cầu xóa an toàn.

Cho các ngữ cảnh cần nonce thực sự – như mã hóa tiêu đề trong header encryption hay lưu trữ khóa – có ba chiến lược phổ biến:

Chiến lược counter có trạng thái (stateful counter): nonce là bộ đếm tăng đơn điệu, bắt đầu từ giá trị ngẫu nhiên và tăng một đơn vị mỗi lần mã hóa. Counter phải được lưu bền vững (trên đĩa hay NVRAM) và cập nhật nguyên tử trước khi dùng. Rủi ro: nếu thiết bị tắt đột ngột sau khi mã hóa nhưng trước khi ghi counter mới, counter bị lùi lại và nonce tái sử dụng. Giải pháp là thiết kế ghi-nguyên-tử: ghi nonce mới vào bộ nhớ bền trước khi mã hóa, không phải sau.

Chiến lược nonce ngẫu nhiên (random nonce): tạo nonce ngẫu nhiên từ CSPRNG (Cryptographically Secure Pseudo-Random Number Generator) cho mỗi lần mã hóa và đính kèm vào bản mã. Không cần lưu trạng thái. Rủi ro: với nonce 96 bit và nhiều bản mã, nghịch lý sinh nhật tạo va chạm sau khoảng 2^48 bản mã. Giải pháp là dùng nonce 128 bit hay luân chuyển khóa sau 2^32 bản mã.

Chiến lược nonce tổng hợp (synthetic nonce / SIV): tính nonce từ MAC của bản rõ và AD, đảm bảo nonce là hàm xác định của nội dung. Hai bản rõ giống nhau sẽ cho cùng nonce nhưng điều này không phá vỡ bảo mật – nó chỉ tiết lộ rằng cùng bản rõ được mã hóa hai lần. Đây là nguyên lý của AES-SIV và AES-GCM-SIV, mang lại khả năng chịu lỗi nonce tốt nhất.

Xử lý lỗi xác thực

Xử lý lỗi xác thực AEAD đúng đắn là yêu cầu bảo mật bắt buộc, không phải tùy chọn. Có ba quy tắc không thể vi phạm.

Quy tắc thứ nhất: không bao giờ tiết lộ thông tin phân biệt về lý do xác thực thất bại. Hàm giải mã AEAD phải chỉ trả về hai trạng thái: thành công (và bản rõ) hoặc thất bại (không có thêm thông tin). Không được phân biệt khóa sai, nonce sai, AD không khớp, bản mã bị cắt ngắn, thẻ xác thực không hợp lệ – tất cả đều phải cho cùng một loại lỗi duy nhất. Bất kỳ thông tin phân biệt nào cũng có thể bị kẻ tấn công khai thác như một oracle để suy ra thông tin về khóa hay bản rõ. Tấn công padding oracle kinh điển hoàn toàn dựa vào việc phía máy chủ phân biệt hai loại lỗi giải mã; cách phòng thủ là không phân biệt.

Quy tắc thứ hai: so sánh thẻ xác thực theo thời gian cố định. Phép so sánh byte thông thường trong hầu hết ngôn ngữ lập trình dừng sớm ngay khi phát hiện byte đầu tiên không khớp, dẫn đến so sánh nhanh hơn khi nhiều byte đầu khớp và chậm hơn khi không byte nào khớp. Kẻ tấn công có thể đo thời gian so sánh để suy ra từng byte của thẻ xác thực đúng, từ đó giả mạo bản mã mà không cần biết khóa. So sánh thời gian cố định (constant-time comparison) luôn so sánh tất cả các byte bất kể kết quả, loại bỏ rò rỉ thông tin qua thời gian. Các thư viện mật mã cung cấp hàm này (như CRYPTO_memcmp trong OpenSSL hay sodium_memcmp trong libsodium); không bao giờ triển khai so sánh thẻ bằng memcmp thông thường hay vòng lặp if-break tự viết.

Quy tắc thứ ba: không giải mã nếu xác thực chưa thành công. Thứ tự là xác thực trước, giải mã sau – không có ngoại lệ. Ngay cả khi việc giải mã trước có vẻ hiệu quả hơn (tránh lưu trữ bản mã tạm thời), thứ tự đó mở ra toàn bộ lớp tấn công padding oracle và tấn công lựa chọn bản mã. Trong AES-GCM và ChaCha20-Poly1305, thứ tự này được thực thi tự nhiên bởi thiết kế của sơ đồ: thẻ xác thực được tính và kiểm tra trước, rồi mới giải mã. Với AES-CBC-HMAC xây dựng thủ công, thứ tự phải được đảm bảo tường minh trong code.

Lựa chọn sơ đồ AEAD và những đánh đổi

Lựa chọn sơ đồ AEAD phụ thuộc vào ba yếu tố: môi trường phần cứng, yêu cầu bảo mật và mức độ chịu lỗi cần thiết. Không có sơ đồ nào tốt nhất cho mọi trường hợp.

AES-256-GCM là lựa chọn đúng đắn khi: phần cứng có tăng tốc AES-NI (hầu hết laptop, máy chủ và điện thoại cao cấp hiện đại); yêu cầu thông lượng cao (lưu lượng mạng lớn, mã hóa lưu trữ); và quản lý nonce được kiểm soát tốt (không có rủi ro khởi động lại hay tái sử dụng nonce). Điểm yếu duy nhất là tính nhạy cảm với nonce – nhưng trong các ứng dụng được thiết kế tốt như Double Ratchet (mỗi mk dùng một lần), điểm yếu này không tồn tại trên thực tế.

ChaCha20-Poly1305 là lựa chọn đúng đắn khi: phần cứng không có AES-NI (điện thoại tầm thấp, vi điều khiển, thiết bị IoT); cần bảo vệ chống tấn công kênh cache (cache-timing attack) mạnh hơn AES; hay cần triển khai phần mềm thuần túy không dùng thư viện nào. Với cùng độ an toàn về mặt lý thuyết, ChaCha20-Poly1305 có thể nhanh hơn 2–4 lần trên phần cứng không có tăng tốc phần cứng.

AES-SIV hay AES-GCM-SIV là lựa chọn đúng đắn khi: quản lý nonce không đảm bảo tuyệt đối (hệ thống phân tán nhiều writer, môi trường khôi phục bản sao lưu, hay thiết bị IoT có thể mất trạng thái); hay cần bảo đảm rằng tái sử dụng nonce không phá vỡ tính toàn vẹn (chỉ có thể lộ rằng cùng bản rõ được mã hóa hai lần). Chi phí là bản mã dài hơn 16 byte (SIV) và hiệu suất chậm hơn một chút. Đặc tả Double Ratchet đề cập đến AES-SIV chính xác vì lý do này – mặc dù thiết kế Double Ratchet tự thân không cần chịu lỗi nonce, cung cấp sơ đồ SIV như tùy chọn cho các triển khai có môi trường rủi ro cao hơn.

Bất kể lựa chọn nào, hai nguyên tắc không thay đổi: luôn dùng triển khai từ thư viện mật mã được kiểm toán (không tự triển khai), và luôn xử lý lỗi xác thực theo ba quy tắc đã nêu. Các lỗ hổng AEAD trong thực tế gần như không bao giờ đến từ điểm yếu của thuật toán mà từ sai lầm triển khai – tái sử dụng nonce, so sánh thẻ không thời gian cố định, hay giải mã trước khi xác thực.

Kết luận

AEAD là thành phần mật mã học thiết yếu kết thúc chuỗi bảo mật mà X3DH và Double Ratchet xây dựng. X3DH tạo ra khóa phiên SK với xác thực lẫn nhau và bảo mật chuyển tiếp; Double Ratchet dẫn xuất khóa tin nhắn mk duy nhất cho từng tin nhắn và phục hồi bảo mật sau xâm phạm; AEAD là thành phần cuối cùng trực tiếp đảm bảo rằng nội dung tin nhắn không thể đọc được (tính bí mật) và không thể sửa đổi mà không bị phát hiện (tính toàn vẹn). Không có AEAD hay nếu AEAD được triển khai sai, toàn bộ chuỗi bảo vệ bên trên có thể sụp đổ dù hoàn hảo về mặt lý thuyết.

Bài học quan trọng nhất từ lịch sử phát triển AEAD là: kết hợp mã hóa và xác thực là bài toán tinh tế đòi hỏi thiết kế hệ thống cẩn thận chứ không phải chỉ lấy hai thành phần tốt và ghép lại. Thứ tự kết hợp sai, phân tách miền thiếu, so sánh thẻ không thời gian cố định hay tiết lộ thông tin qua lỗi – bất kỳ điểm nào trong số này đều có thể biến mã hóa mạnh thành lỗ hổng nghiêm trọng. AEAD giải quyết tất cả bằng cách đóng gói toàn bộ phức tạp này vào một giao diện đơn giản, đã được phân tích hình thức, mà người dùng chỉ cần đảm bảo ba điều: khóa bí mật, nonce không tái sử dụng và dữ liệu liên kết đúng ngữ cảnh.

Mật mã học xác thực AEAD – mã hóa và xác thực trong một bước – developer, bao mat, mat ma hoc, aead, ma hoa xac thuc, authenticated encryption, aes gcm, chacha20 poly1305, signal protocol, forward secrecy.
Mật mã học xác thực AEAD – mã hóa và xác thực trong một bước.
  • bao-mat (11)

  • mat-ma-hoc (11)

  • signal-protocol (10)

  • aead (1)

  • authenticated-encryption (1)

  • ma-hoa-xac-thuc (1)

  • aes-gcm (1)

  • chacha20-poly1305 (1)

  • ind-cpa (1)

  • int-ctxt (1)

  • associated-data (1)

  • du-lieu-lien-ket (1)

  • authentication-tag (1)

  • nonce (1)

  • padding-oracle (1)

  • double-ratchet (5)

  • forward-secrecy (9)

  • post-quantum (3)

  • ma-hoa-doi-xung (1)

Chuyên mục double-ratchet

Mật mã học xác thực AEAD – mã hóa và xác thực trong một bước

Mật mã học xác thực AEAD – mã hóa và xác thực trong một bước

Giải thích đầy đủ AEAD (Authenticated Encryption with Associated Data) – mô hình bảo mật IND-CPA và INT-CTXT, vai trò dữ liệu liên kết, so sánh AES-GCM, ChaCha20-Poly1305 và AES-CBC-HMAC, cùng các nguyên tắc triển khai an toàn trong Signal Protocol.

Mật mã học xác thực AEAD – mã hóa và xác thực trong một bước

Theo dõi hành trình

Hãy để lại thông tin, khi có gì mới thì Nhà văn sẽ gửi thư đến bạn để cập nhật. Cam kết không gửi email rác.

Họ và tên

Email liên lạc

Đôi dòng chia sẻ