I. Mở đầu
Với các giao thức trực tuyến (online), mã xác thực thông báo mật mã (cryptographic Message Authentication Code –MAC ) là rất quan trọng và có tính chất như bắt buộc để đảm bảo tính xác thực giữa các bên tham gia giao dịch.
Mục đích của hàm MAC là đảm bảo để hai (hay nhiều) bên tham gia giao dịch khi có chung khóa bí mật có thể giao dịch với nhau, kèm theo khả năng có thể phát hiện được thay đổi của thông báo trong quá trình vận chuyển, nhằm tránh các tấn công làm thay đổi thông báo. Thuật toán MAC dựa trên thông báo đầu vào và khóa mật để tạo ra thẻ MAC (MAC tag). Thông báo và MAC tag được gửi tới người nhận, người nhận tính lại giá trị MAC tag và so sánh nó với giá trị thẻ MAC nhận được. Nếu hai giá trị thẻ MAC trùng nhau thì coi như thông báo “gần” chính xác, ngược lại thông báo coi là đã bị thay đổi, phải hủy bỏ và dừng kết nối. Đối với kẻ tấn công giả mạo thông báo, nó phải phá được hàm MAC, việc này khó tương đương với việc phá khóa bảo vệ thông báo. Trên thực tế, các giao thức thường chia thông báo dài làm nhiều đoạn nhỏ và chúng được xác thực độc lập với nhau, dẫn đến phát sinh tấn công lặp (replay attack). Do vậy khi thiết kế giao thức có sử dụng MAC cần rất thận trọng.
Để giúp các nhà phát triển ứng dụng tích hợp MAC vào các sản phẩm khác nhau, Viện tiêu chuẩn và công nghệ quốc gia của Mỹ (NIST) đưa ra hai chuẩn về hàm MAC. Tiêu chuẩn thứ nhất là Mã xác thực thông báo sử dụng hàm một chiều có khóa - HMAC (Keyd-Hash Messasge Authentication Code)[1]. Chuẩn này mô tả phương pháp an toàn chuyển hàm một chiều kháng va chạm hash thành hàm MAC. HMAC nguyên bản được đề nghị sử dụng với SHA-1, nó cũng thích hợp sử dụng với các hàm hash khác (những chứng minh hiện tại chỉ ra rằng kháng va chạm là không cần thiết đối với sự an toàn của NMAC (Nested MAC) [2] - một thuật toán mà từ đó HMAC được xây dựng. Tuy nhiên bài báo khác lại đề nghị rằng hash an toàn là cần thiết [3].
Chuẩn thứ hai NIST đưa ra là Mã xác thực thông báo mã hóa (Cipher Message Authentication Code- CMAC)[1],[6]. Không giống HMAC, CMAC sử dụng mã khối để thực hiện chức năng MAC, nó rất phù hợp với các ứng dụng bộ nhớ hạn chế chỉ đủ để dùng cho mã hóa dữ liệu.
Mục đích của hàm MAC khác với hàm một chiều hash, nó bảo đảm xác thực thông báo chứ không phải toàn vẹn thông báo. Tuy nhiên cả hai dựa trên những nguyên lý rất chung. Trong cả hai trường hợp chúng ta đều tìm cách xác định tính chính xác (đúng đắn), cụ thể hơn là sự toàn vẹn của thông báo. Tất nhiên mục tiêu của xác thực là tìm cách trả lại tính ban đầu (origin) của thông báo. Ví dụ nếu ta sử dụng SHA-1 để tóm lược thông báo để có 160 bit X và gửi cho người khác thì người đó chỉ có thể xác định được xem thông báo đó là giữ nguyên như ban đầu hay không bằng cách tính giá trị tóm lược và so sánh chúng với nhau, nhưng cách này không thể xác định được ai tạo thông báo đó, giá trị tóm lược không cung cấp thông tin này. Giả sử trong giao dịch cả hai đều dùng chung khóa K, nếu ta gửi thông báo và thẻ MAC với khóa K, thì người nhận có thể kiểm tra để xác định là thông báo có gửi từ bạn hay không bằng cách kiểm tra thẻ MAC.
Điểm khác nữa cũng nhận thấy ở đây là đối với hàm hash, tấn công ngày sinh nhật (birthday attack) giảm độ an toàn của hàm hash về độ dài một nửa kích thước giá trị hash (nếu sử dụng SHA-256 chỉ cần 2128 “phép toán” để tìm va chạm). Điều này xảy ra vì hàm tóm lược được tính offline, có thể thực hiện một số lượng lớn các tóm lược thông báo. Đối với MAC là online, không có được khóa, kẻ tấn công không thể tìm được va chạm (nếu coi MAC thực sự an toàn) và kẻ tấn công không thể tùy ý tính thẻ MAC được, tấn công ngày sinh không thể áp dụng cho hàm MAC. Do vậy nếu thẻ MAC có độ dài k bit thì nó cần 2k phép toán để tìm va chạm với giá trị cụ thể đó.
II. Mã xác thực thông báo mã hóa (CMAC)
CMAC được lấy từ Dự thảo mã xác thực thông báo một khóa (One-Key Message Authentication Code - OMAC). Nó dựa trên mã xác thực thông báo chế độ mã CBC ba khóa (three-key cipher block chaining MAC). MAC mã hóa nguyên thủy của NIST là CBC-MAC (hình 1). Trong đó người gửi chỉ cần chọn khóa độc lập (không có quan hệ nhiều) với khóa mã và sử dụng mã theo chế độ (mode) CBC. Người gửi bỏ qua mọi bản mã giữa, chỉ quan tâm đến bản mã cuối cùng là thẻ MAC. Khóa dùng cho CBC-MAC không trùng (“quan hệ yếu”) với khóa mã của bản rõ, khi đó MAC là an toàn .
Hình 1: Sơ đồ CBC-MAC
Như vậy nếu thông báo có thể chia thành các khối có độ dài bằng nhau (bằng độ dài của khối khóa) (hình 2) thì chỉ cần dùng một khóa. Khi thông báo gồm các khối có độ dài khác nhau (độ dài khối cuối nhỏ hơn độ dài các khối trước đó) (hình 3) lược đồ trên không an toàn, lừa đảo có thể xảy ra.
Hình 2: Sơ đồ OMAC thông báo với các khối có cùng độ dài
Hình 3: Sơ đồ OMAC thông báo với độ dài khối cuối ngắn hơn các khối trước
Để khắc phục, người ta đưa vào XCBC và sử dụng 3 khóa. Khóa đầu tiên sử dụng để mã hóa dữ liệu ở chế độ CBC-MAC. Hai khóa còn lại được áp dụng cho khối cuối với phép hoặc loại trừ (XOR), bất kể khối cuối có cùng độ dài với các khối trước đó hay không. Nếu khối cuối có cùng độ dài với các khối trước thì sử dụng khóa thứ hai, ngược lại khối cuối được ghép thêm (padded) để có cùng độ dài với các khối trước, và khóa thứ ba được sử dụng. Đối với XCBC, ba khóa phải độc lập với nhau.
Sau XCBC là TMAC sử dụng hai khóa. TMAC làm việc giống như XCBC với điểm khác là khóa thứ 3 có thể lấy tuyến tính từ khóa thứ nhất. OMAC là sự sửa lại của TMAC chỉ sử dụng một khóa (khóa thứ hai, thứ 3 được tính từ khóa thứ nhất).
1. An toàn của CMAC
Để thuận tiện, các khóa được tạo ra phụ thuộc vào nhau. Điều này phải trả giá là nếu kẻ tấn công biết được một khóa, nó có thể tìm ra khóa kia (hoặc tất cả trong trường hợp OMAC).
Tấn công đối với hàm MAC là các tấn công trực tuyến. Vì tất cả dữ liệu cần xác thực, kẻ tấn công không dễ gì truy vấn tới thiết bị, nhưng nó có thể biết được dữ liệu nào đưa vào MAC. Trên thực tế kẻ tấn công có rất ít thời gian để thực hiện giả mạo để không bị phát hiện, xác xuất thực hiện thành công sự giả mạo rất nhỏ . Ví dụ nếu sử dụng mã khối AES (độ dài khối n =128 bit), có thể sử dụng CMAC để xác thực 243 khối (1024 terabyte) mới thay đổi khóa mà vẫn đảm bảo xác xuất lừa đảo gói nhỏ hơn 2-40. Trong trường hợp mã hóa, tấn công là offline (hoạt động độc lập, không trực tuyến). Kẻ tấn công có thể lặp lại các tính toán (thử giải mã với khóa ngẫu nhiên) không cần có sự tham gia của đối tượng bị tấn công. Như vậy đối với mã hóa số bit khóa cần lớn hơn nhiều.
2 .Thiết kế CMAC
CMAC dựa trên thiết kế của OMAC; đặc biệt là thiết kế của OMAC1. Người thiết kế OMAC đưa ra hai giải pháp liên quan đến nhau OMAC1 và OMAC2 [6],[8], chúng khác nhau ở chỗ sinh khóa bổ sung. Trên thực tế người sử dụng có thể chỉ dùng OMAC1 nếu họ định tuân theo chuẩn CMAC.
3. Khởi tạo, mô tả cài đặt CMAC
CMAC nhận khóa mật K là đầu vào của quá trình khởi tạo. Nó sử dụng khóa đó để sinh hai khóa bổ sung K1 và K2. Có thể mô tả đơn giản như sau:
Đầu vào
K: Secret key
Đầu ra
K1, K2: Khóa CMAC bổ sung
1. L = EncryptK(0) (* Hàm mã khối, với khóa K, khối vào là 0 *)
2. If MSB(L) = 0, then K1 = L << 1
else K1 = (L << 1) XOR Rb
3. If MSB(K1) = 0, then K2 = K1 << 1
else K2 = (K1 << 1) XOR Rb
4. Return K1, K2
Các phép toán thực hiện trên xâu 64 hay 128 bit tùy thuộc vào độ dài khối được sử dụng trong mã khối. Giá trị Rb phụ thuộc vào độ dài khối. Nó là 0x87 khi khối là 128 bit và 0x1B khi khối là 64 bit. L là kết quả mã hóa của xâu toàn zero với khóa K. Có K1 và K2, chúng ta tạo được MAC. K1 và K2 phải được giữ bí mật như khóa mã.
Trường hợp đặc biệt, khi thông báo độ dài zero, CMAC coi như nó là khối chưa hoàn chỉnh. Cài đặt MAC được mô tả như sau:
Đầu vào
K: Khóa bí mật
K1, K2: Khóa CMAC bổ xung
M: Thông báo
L: Số bit của thông báo
Tlen: Độ dài thiết kế của thẻ MAC
w: Số bit/ block
Đầu ra
T: Thẻ MAC
1. Nếu L = 0, cho n = 1, ngược lại n = ceil(L/w)
2. Ký hiệu M1,M2,M3,... Mn biểu diễn các khối của thông báo
3. Nếu L > 0 và L mod w = 0 thì
Mn := Mn XOR K1
4. Nếu L = 0 hoặc L mod w > 0 thì
Gán vào một bit ‘1’ và sau đó một số lượng các bit ‘0’ để khối cuối đủ w bit
Mn := Mn XOR K2
5. C0 = 0
6. Cho i từ 1 tới n thực hiện
Ci = EncryptK(Ci-1 XOR Mi)
7. T = MSBTlen(Cn) (* Lấy Tlen bit trái nhất của xâu Cn)
8. Return T
Các giá trị Ci nhận được có vẻ như là bản mã của thông báo. Tuy nhiên không thể sử dụng nó như bản mã của thông báo được vì không có căn cứ chứng minh tính an toàn của nó đối với CMAC. Bản rõ cần được mã hóa với khóa khác (khóa mã dữ liệu, không có quan hệ với khóa MAC) để đảm bảo tính an toàn của CMAC.
Nhìn chung tốc độ của CMAC phụ thuộc vào tốc độ mã hóa, với sự tối ưu hóa hàm tính toán (phản hồi), có thể sử dụng phép toán XOR đối với từ (word) thay thế cho byte. Nhưng CMAC sử dụng chế độ CBC do vậy không thể song song hóa quá trình thực hiện. Trên thực tế tối ưu chỉ dựa vào cải tiến cài đặt AES (thuật toán mã hóa được sử dụng là AES)
III. Mã xác thực thông báo sử dụng hàm một chiều
HMAC [1] sử dụng hàm hash một chiều có khóa mật và đưa nó thành thuật toán mã xác thực thông báo. Dưới đây trình bày cách ứng dụng hash để tạo MAC
HMAC thường được thiết kế dựa trên NMAC (Nested MAC), sử dụng hàm giả ngẫu nhiên – PRF (pseudo random function ) để tạo hàm MAC với giới hạn an toàn chứng minh được.
tag = hash(key1 || hash(key2 || message))
PRF ở đây có dạng Hash(key2||message). NMAC yêu cầu 2 khóa, một cho hash trong (inner) một cho hash ngoài (outer). Hai khóa độc lập với nhau. HMAC dựa trên NMAC với sự khác biệt là hai khóa phụ thuộc tuyến tính, chỉ yêu cầu hàm PRF là an toàn [2], không yêu cầu nó kháng va chạm đối với một số hàm hash (Chứng minh mới về NMAC và HMAC: An toàn không cần kháng va chạm [2]), nhưng nó cần chống được tấn công phương sai.
1. Thiết kế HMAC
Ban đầu HMAC được thiết kế để sử dụng với SHA-1, trên thực tế có thể sử dụng nó an toàn với các hàm hash an toàn khác như SHA-256 và SHA-512. HMAC sinh hai khóa từ một khóa mật duy nhất bằng cách XOR hai hằng số với nó. Chú ý là khóa có kích thước bằng kích thước của khối sử dụng trong hàm hash (SHA-1 và SHA-256 khối nén 64-byte, SHA-512 khối nén 128-byte). Nếu khóa lớn hơn kích thước khối nén, thì khóa trước hết phải được hash, đầu ra của nó coi như là khóa mật. Khóa mật được gán thêm các byte zero đảm bảo là độ dài của nó bằng độ dài khối nén. Khóa được sao thành hai bản, bản thứ nhất được XOR với 0x36 tạo khóa ngoài (outer), bản thứ hai XOR với 0x5C tạo khóa trong (inner). Xâu gồm các byte 0x36 gọi là opad, xâu gồm các byte 0x5C là ipad. Khóa phải được bổ sung thêm (padded) để có độ dài bằng độ dài của khối nén để có thể thực hiện hash có khóa (keyed hash) thay cho hash thông qua việc tạo trạng thái hash khởi tạo phụ thuộc khóa. HMAC tương đương với việc lấy trạng thái khởi tạo hash một cách ngẫu nhiên trên khóa bí mật (Hình 4).
Hình 4: Sơ đồ khối HMAC
2. Thuật toán HMAC
Đầu vào
K: Khóa bí mật
message: Thông báo chúng ta cần tính giá trị MAC cho nó.
w: Độ dài khối nén
Tlen: Độ dài thẻ MAC theo thiết kế
Đầu ra
Tag: thẻ MAC
1. if length(K) > w then
K = hash(K)
2. Làm đầy K bởi zeros cho đến khi nó có độ dài đúng w bytes
3. Tag = hash((opad XOR K) || hash((ipad XOR K) || message)).
4. Chặt Tag lấy Tlen bytes bằng cách chỉ giữ Tlen bytes đầu tiên.
5. Return Tag.
HMAC không quá phức tạp, trong thiết kế nó sử dụng hash như là hàm PRF, điểm hạn chế của nó là không song song được thuật toán, trong sơ đồ thuật toán chỉ có thể tính hash của (opad XOR K) khi tính hash trong, nhưng điều này không cải tiến đáng kể được tốc độ.
IV. Ứng dụng hàm MAC trên thực tế
MAC được thiết kế để đảm bảo xác thực giữa các bên trong kênh liên lạc để giúp chúng có thể gửi và nhận thông báo được xác thực với nhau và khả năng bị kẻ tấn công giả mạo là rất thấp. Tuy vậy để sử dụng chúng an toàn, hiệu quả một số vấn đề sau đây cần đặc biệt lưu ý. Trên thực tế, MAC được triển khai sử dụng trong các giao thức SSL và TLS trên internet.
Ví dụ HTTPS sử dụng TLS hoặc SSL để mã hóa kênh và áp dụng MAC cho dữ liệu gửi qua lại để đảm bảo xác thực. Hoặc dùng để xác thực người dùng trong mạng GSM bằng thuật toán COMP128 [4],[7].
1. Chống tấn công lặp
Khi trao đổi thông tin, các gói dữ liệu được chia thành các khối do vậy tấn công lặp rất dễ xảy ra. Khi đã bị tấn công các gói lặp vẫn giữ nguyên và việc giải mã vẫn bình thường nên điều nguy hiểm là không dễ phát hiện được sự tấn công. Có hai giải pháp cơ bản để chống tấn công lặp là sử dụng tem thời gian và con đếm. Nó gắn gói tin vào ngữ cảnh (context), cho phép người nhận xác định được vị trí gói tin trong luồng dữ liệu.
Sử sụng Tem thời gian
Mục đích của sử dụng tem thời gian là đảm bảo cho thông báo có hiệu lực chỉ trong khoảng thời gian nào đó. Ví dụ hệ thống chỉ cho phép gói dữ liệu có hiệu lực trong 30 giây từ khi tem thời gian được dán vào. Tuy vậy, từ góc độ an toàn, thật khó đặt tem thời gian đủ nhỏ để tránh tấn công lặp. Ví dụ ta đặt cửa sổ hiệu lực là 5 phút thì kẻ tấn công dễ dàng thực hiện tấn công lặp trong 5 phút. Nhưng nếu đặt của sổ hiệu lực là 3 giây, thì có khó khăn là trong khoảng thời gian đó chưa chắc đã truyền được gói dữ liệu. Mặt khác vấn đề đồng bộ thời gian giữa các nút của hệ thống là tương đối và có thể khi đó hệ thống nói chung không sử dụng được.
Sử dụng con đếm
Con đếm là giải pháp lý tưởng chống tấn công lặp. Ở mức nền tảng cần giải quyết câu hỏi giá trị tiếp theo của con đếm là gì? Ví dụ ta lưu trạng thái thanh ghi dịch phản hồi tuyến tính - LFSR [5] trong một gói và hy vọng trạng thái tiếp theo của LFSR được điểm (clocked) ở gói tiếp theo. Nếu trạng thái của LFSR không được điểm đúng, ta có thể coi là không nhận được đúng gói dữ liệu cần thiết. Một cách tiếp cận đơn giản mà thuận tiện là sử dụng giá trị con đếm là số tự nhiên. Chỉ cần giá trị con đếm không lặp lại trong cùng một phiên liên lạc (không có sự thay đổi khóa MAC). Giá trị con đếm được thỏa thuận giữa hai bên không cần phải ngẫu nhiên, và cũng không cần duy nhất nếu khóa MAC mới được sử dụng trong phiên. Khi mỗi gói gửi đi giá trị con đếm được tăng lên, bản thân giá trị con đếm được chứa trong thông báo và là một phần đầu vào hàm MAC. Tức là ta MAC cả giá trị con đếm và văn bản mã. Có thể mã hóa cả giá trị con đếm, nhưng điều đó không quan trọng vì độ an toàn tăng lên là “không đáng kể”. Người nhận kiểm tra giá trị con đếm trước khi tiến hành bất kỳ động tác khác nào. Nếu giá trị con đếm nhỏ hơn hoặc bằng giá trị con đếm gói mới nhất, thì đó là gói lặp. Kích thước của con đếm có cỡ lớn nhất bằng kích thước gói dữ liệu cần gửi. Thường con đếm 32 bit là đủ, trong trường hợp đặc biệt có thể 40 bit hay 48 bit.
2. Sử dụng MAC
Việc sử dụng hàm MAC không nên quá lạm dụng trong các ứng dụng yêu cầu bảo mật, ít nhất không sử dụng nó như hàm hash hay hàm mã hóa.
Đôi khi người ta muốn sử dụng CMAC với khóa cố định để tạo ra hash. Cách thiết kế như vậy là không an toàn vì hàm “nén” (mã) không thực sự là PRF. Một số tài liệu đã nêu cách chuyển mã hóa thành hash an toàn [9].
Một câu hỏi đặt ra là nên sử dụng CMAC hay HMAC? Dùng CMAC hay HMAC phải dựa trên vấn đề mà ta cần giải quyết. CMAC là hợp lý nếu ta đã có cơ sở mã hóa đảm bảo (ví dụ đảm bảo cho tính riêng tư). Chúng ta có thể sử dụng lại chính mã (code) chương trình hay thiết bị phần cứng đó để thực hiện xác thực. CMAC dựa trên mã khối nhưng với đầu vào nhỏ (so với hash) và đầu ra ở trật tự ngắn gọn, thời gian trễ cho tính toán nhỏ. Ví dụ với thông báo ngắn khoảng 16 hay 32 byte, CMAC sử dụng AES cho kết quả nhanh, ít trễ hơn HMAC. HMAC thắng thế khi áp dụng cho thông báo kích thước lớn. Hash xử lý dữ liệu với số vòng/byte ít hơn mã hóa. Hash cũng thường tạo ra dữ liệu thẻ MAC dài theo yêu cầu cụ thể. Nhưng HMAC yêu cầu cài đặt hàm hash.
Như vậy, nếu ta đã có hash, và thông báo không quá nhỏ thì nên sử dụng HMAC. Nếu ta đã có mã hóa và làm việc với thông báo nhỏ nên sử dụng CMAC.
3. Thứ tự thực hiện mã hóa và MAC
Thứ tự của mã hóa và MAC, nói chung không ảnh hưởng đến yêu cầu về độ an toàn, nhưng dẫu sao nó cũng có sự khác biệt nhỏ. Quan trọng nhất là khóa mã và khóa MAC không có liên hệ với nhau. Đơn giản nhất là sử dụng hàm tạo giữa khóa tách biệt khóa dành cho mã hóa và khóa dành cho MAC.
Mã hoá trước, MAC sau
Ở chế độ này mã hóa bản rõ trước sau đó MAC bản mã (cùng với con đếm hay tem thời gian). Vì mã hóa là ánh xạ một cách ngẫu nhiên hoàn toàn bản rõ (đòi hỏi lựa chọn IV thích hợp), thông báo đem MAC là thông báo ngẫu nhiên. Như vậy MAC không lộ thông tin về bản rõ, và người nhận không cần phải giải mã để từ chối gói dữ liệu không hợp lệ.
MAC trước, mã hoá sau
Ở đây trước tiên ta MAC bản rõ (cùng với con đếm hoặc tem thời gian) và sau đó mã bản rõ. Đầu vào của MAC không phải ngẫu nhiên và phần lớn thuật toán MAC (ít nhất là CMAC và HMAC) không sử dụng vectơ khởi tạo IV (Initial Vector), do vậy đầu ra của MAC cũng không ngẫu nhiên (nếu chúng ta không sử dụng chống tấn công lặp). Như vậy chúng ta đưa cho kẻ tấn công bản mã và thẻ MAC của bản rõ. Nếu bản rõ không đổi, bản mã có thể thay đổi (do lựa chọn IV tốt), nhưng thẻ MAC vẫn như cũ. Tuy nhiên thường ta có tem thời gian hoặc con đếm như một phần của đầu vào hàm MAC. Và vì MAC là PRF, nên nó chống được tấn công ngay cả khi bản rõ không đổi. Tốt nhất là áp dụng mã hóa đối với cả thẻ MAC cùng như bản rõ, như vậy giá trị thẻ MAC không bị kẻ tấn công tiếp cận. Hạn chế ở đây là người nhận phải giải mã để so sánh thẻ MAC.
4. Kết luận
Như vậy chúng ta thấy sử dụng MAC một cách hợp lý là một vấn đề khá phức tạp, nó phụ thuộc vào nhiệm vụ cụ thể, công việc cụ thể, môi trường ứng dụng thực tế. Chúng ta đều thống nhất với nhau rằng hậu quả rất khôn lường nếu không sử dụng MAC. Tuy nhiên, cần thận trọng trong sử dụng MAC để đạt mục tiêu là an toàn, thuận tiện và hiệu quả.