Tại sao std :: hash không được đảm bảo là xác định?


28

Sau đây, chúng tôi sử dụng N4140 (Tiêu chuẩn C ++ 14).


Theo § 17.6.3.4 Yêu cầu băm ,

Giá trị được trả về sẽ chỉ phụ thuộc vào đối số k trong suốt thời gian của chương trình .

[Lưu ý: Do đó, tất cả các đánh giá của biểu thức h(k)có cùng giá trị cho kkết quả giống nhau cho một lần thực hiện chương trình đã cho . - lưu ý cuối]

§ 20.9.12 Băm mẫu lớp nói

...

việc khởi tạo hash<Key>sẽ:

(1.1) - đáp ứng các yêu cầu Hash (17.6.3.4) ...

(1.2) - ...


Điều này có nghĩa là giá trị băm của value(nghĩa là hash<decltype(value)>(value)) có thể lấy một giá trị khác nếu bạn khởi động lại chương trình.

Nhưng tại sao? Giới hạn này không nằm trong Tiêu chuẩn của C ++ 11, mà là trong Tiêu chuẩn của C ++ 14, C ++ 17 và C ++ 20. Là người dùng (không phải là nhà phát triển STL), nó sẽ khá hữu ích nếu mang tính std::hashquyết định. Có bất kỳ khó khăn toán học trong việc thực hiện một hàm băm xác định? Nhưng các hàm băm mà chúng ta sử dụng hàng ngày (ví dụ như không dùng nữa md5sumhoặc an toàn hơn sha256) đều mang tính quyết định. Có một vấn đề về hiệu quả?


7
"... Các hàm Hash chỉ được yêu cầu để tạo ra cùng một kết quả cho cùng một đầu vào trong một lần thực hiện chương trình; điều này cho phép băm muối ngăn chặn các cuộc tấn công từ chối dịch vụ va chạm ." nguồn: en.cppreference.com/w/cpp/utility/hash
Richard Critten

5
Nó cho phép một thuật toán xác định lấy các đầu vào không xác định. Giá trị con trỏ, ví dụ. Một cấu trúc dữ liệu bất biến có thể băm các địa chỉ của dữ liệu nội bộ của nó, có thể nhanh hơn rất nhiều so với băm nội dung.
John Kugelman

4
Câu trả lời này có một số liên kết tốt đẹp về lý do tại sao bạn không muốn xác định.
NathanOliver

3
Đừng đe dọa điều này như giới hạn, nhưng làm cho các ràng buộc tiêu chuẩn bớt nghiêm ngặt hơn một chút.
Marek R

4
Dưới đây là giải thích đầy đủ tại sao các ràng buộc đã được nới lỏng.
Marek R

Câu trả lời:


17

Không cần hàm băm có thể xác định giữa các lần chạy, nhưng bạn vẫn có thể cung cấp hàm băm của riêng mình, ví dụ như đối với các container không có thứ tự nếu đó là hành vi mà bạn dựa vào.

Về lý do, cppreference nói:

Các hàm băm chỉ được yêu cầu để tạo ra cùng một kết quả cho cùng một đầu vào trong một lần thực hiện chương trình; điều này cho phép băm muối ngăn chặn các cuộc tấn công từ chối dịch vụ va chạm.

Nếu Hash yêu cầu bảo nó là xác định, thì bạn sẽ không thể cung cấp hàm băm mặn mà không phá vỡ yêu cầu.

Dưới đây là lời giải thích thực tế tại sao


7

Câu trả lời này (và các liên kết trong đó) được đề xuất bởi @NathanOliver cuối cùng là hữu ích. Hãy để tôi trích dẫn những phần quan trọng.

Đối với hàm băm không mã hóa, có thể tính toán trước các đầu vào lớn có cùng giá trị băm để làm chậm thuật toán các container không có thứ tự và dẫn đến một cuộc tấn công từ chối dịch vụ.

(từ Số phát hành 2291. std :: hash dễ bị tấn công DoS )

Vì lý do này, các nhà thiết kế ngôn ngữ đang chuyển sang băm ngẫu nhiên. Trong quá trình băm ngẫu nhiên, giá trị băm của chuỗi Hồi giáo có thể thay đổi mỗi khi bạn chạy chương trình của mình. Băm ngẫu nhiên hiện là mặc định trong Python (kể từ phiên bản 3.3), Ruby (kể từ phiên bản 1.9) và Perl (kể từ phiên bản 5.18).

(từ Bạn có nhận ra rằng bạn đang sử dụng băm ngẫu nhiên không? )

Di chuyển đến Sẵn sàng, thay vì Ngay lập tức, vì ngay cả sự cho phép đã gây tranh cãi trong cuộc thảo luận phản xạ

(từ Số phát hành 2291. std :: hash dễ bị tấn công DoS )

Trong thực tế, theo như tôi hiểu, không có triển std::hashkhai thực hiện băm ngẫu nhiên nhưng bạn có thể tự viếtmy::secure_hash .

(từ câu trả lời này )


PS

Tôi vừa googled "bảng băm dos" và tìm thấy một trang thông tin: Thời điểm bạn nhận ra mọi máy chủ trên thế giới đều dễ bị tấn công .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.