Nếu dữ liệu tôi muốn xác thực bao gồm nhiều giá trị và tôi tính toán MAC chỉ bằng cách ghép nối các giá trị, kẻ thù có thể "chuyển" các ký tự trong các giá trị đó mà không làm mất hiệu lực MAC. Làm thế nào là vấn đề này phổ biến và giải quyết tốt nhất?
tôi đã tìm được câu hỏi hiện có này về MACing nhiều tin nhắn, nhưng tôi cảm thấy các giải pháp được đề xuất không khái quát tốt cho nhiều hơn hai thông báo.
Hãy xem xét ví dụ giả tạo sau:
Giả sử tôi có một máy chủ lưu trữ các mục nhật ký xác thực cho khách hàng. Máy khách viết một mục nhật ký, xác thực nó bằng MAC và gửi nó đến máy chủ. Sau đó, khi máy khách truy xuất các mục nhật ký từ máy chủ, nó sẽ có thể xác minh tính xác thực của chúng.
Giả sử các mục nhật ký có cấu trúc sau:
{
được tạoTại: "1621012345",
thông báo: "mục nhập đầu tiên"
}
Một cách ngây thơ, tôi có thể tạo MAC cho một mục nhật ký tôi
như
$$
mac = \text{HMAC}(K, l.createdAt \| l.message)
$$
ở đâu $\|$ biểu thị nối và $K$ là chìa khóa bí mật.
Nếu tôi tiếp tục lưu trữ mục nhập nhật ký này và MAC trên máy chủ và truy xuất nó sau, máy chủ có thể quay lại
{
được tạoAt: "1621012",
thông báo: "345mục nhập đầu tiên",
mac: "<MAC được tính ở trên>"
}
Từ 1621012 || 345mục nhập đầu tiên
giống như 1621012345 || mục đầu tiên
Tôi sẽ không nhận thấy thao tác khi kiểm tra MAC.
Lưu ý rằng trong trường hợp này, tôi thực sự nên phát hiện thao tác bằng cách xác thực độ dài của đã tạoAt
. Nhưng điều đó chỉ hoạt động nếu độ dài là cố định chứ không phải nếu tôi có, chẳng hạn, tên tác giả
thay vì dấu thời gian.
Tôi có thể nghĩ ra những cách sau đây để giải quyết vấn đề này:
1. Xen kẽ một dấu phân cách
Nếu tôi tính MAC của mình là $mac = \text{HMAC}(K, l.createdAt \| \text{':'} \| l.message)$ Tôi tin rằng cuộc tấn công này sẽ không thể thực hiện được nữa. Thoạt nhìn có vẻ như có vấn đề khi ký tự phân cách có thể xuất hiện trong tin nhắn. Nhưng điều đó chỉ làm cho không thể tái cấu trúc rõ ràng các giá trị từ chuỗi được nối, điều này không liên quan trong trường hợp này. Tôi không thể nghĩ ra bất kỳ cách nào để làm cho việc tính toán MAC trở nên mơ hồ ở đây. Giải pháp đơn giản này có an toàn không?
2. Giá trị băm trước khi nối
Tôi có thể tính toán MAC, ví dụ, như $mac = \text{HMAC}(K, \text{SHA256}(l.createdAt) \| \text{SHA256}(l.message))$ (hoặc bất kỳ hàm băm mật mã nào khác). Điều này đảm bảo rằng kẻ thù không thể thao túng các giá trị mà tôi nối một cách có ý nghĩa. Nó cũng đảm bảo rằng các giá trị được nối luôn có độ dài cố định. Băm có thêm bất kỳ giá trị nào so với ý tưởng đầu tiên không?
3. Xác thực toàn bộ dữ liệu có cấu trúc
Tôi cũng có thể tính toán MAC trên toàn bộ đối tượng JSON của mục nhật ký. Thực tế, điều này có nghĩa là tôi có các dấu phân cách phức tạp hơn, có ý nghĩa hơn (các phím và cú pháp). Về cơ bản, giống như một JWT.
Lưu ý rằng cách tiếp cận này cũng có một số nhược điểm, chủ yếu là do mất tính linh hoạt của API và nhu cầu chuẩn hóa JSON. Có một bài viết blog tuyệt vời về điều này tại https://latacora.micro.blog/2019/07/24/how-not-to.html.
Tôi có thiếu bất kỳ giải pháp tốt nào cho vấn đề này không? Có một cách đề nghị để đối phó với điều này?