Hàm băm trong Python 3.3 trả về các kết quả khác nhau giữa các phiên


99

Tôi đã triển khai BloomFilter trong python 3.3 và nhận được kết quả khác nhau mỗi phiên. Tìm hiểu sâu về hành vi kỳ lạ này đã đưa tôi đến hàm hash () nội bộ - nó trả về các giá trị băm khác nhau cho cùng một chuỗi mỗi phiên.

Thí dụ:

>>> hash("235")
-310569535015251310

----- mở bảng điều khiển python mới -----

>>> hash("235")
-1900164331622581997

Tại sao chuyện này đang xảy ra? Tại sao điều này lại hữu ích?

Câu trả lời:


136

Python sử dụng một hạt băm ngẫu nhiên để ngăn những kẻ tấn công đục lỗ ứng dụng của bạn bằng cách gửi cho bạn các khóa được thiết kế để va chạm. Xem tiết lộ lỗ hổng ban đầu . Bằng cách bù trừ hàm băm bằng một hạt ngẫu nhiên (được đặt một lần khi khởi động), kẻ tấn công không còn có thể dự đoán các phím nào sẽ va chạm.

Bạn có thể đặt hạt giống cố định hoặc vô hiệu hóa tính năng bằng cách đặt PYTHONHASHSEEDbiến môi trường ; mặc định là randomnhưng bạn có thể đặt nó thành một giá trị nguyên dương cố định, với 0việc tắt hoàn toàn tính năng này.

Phiên bản Python 2.7 và 3.2 có tính năng bị vô hiệu hóa theo mặc định (sử dụng công -Rtắc hoặc thiết lập PYTHONHASHSEED=randomđể bật tính năng này); nó được bật theo mặc định trong Python 3.3 trở lên.

Nếu bạn đang dựa vào thứ tự các khóa trong một tập hợp Python, thì không. Python sử dụng bảng băm để triển khai các loại này và thứ tự của chúng phụ thuộc vào lịch sử chèn và xóa cũng như hạt băm ngẫu nhiên. Lưu ý rằng trong Python 3.5 trở lên, điều này cũng áp dụng cho từ điển.

Cũng xem object.__hash__()tài liệu phương pháp đặc biệt :

Lưu ý : Theo mặc định, __hash__()giá trị của các đối tượng str, byte và datetime là "muối" với một giá trị ngẫu nhiên không thể đoán trước. Mặc dù chúng không đổi trong một quy trình Python riêng lẻ, chúng không thể dự đoán được giữa các lần gọi Python lặp lại.

Điều này nhằm cung cấp khả năng bảo vệ chống lại sự từ chối dịch vụ gây ra bởi các đầu vào được lựa chọn cẩn thận khai thác hiệu suất trong trường hợp xấu nhất của việc chèn chính tả, độ phức tạp O (n ^ 2). Xem http://www.ocert.org/advisories/ocert-2011-003.html để biết thêm chi tiết.

Việc thay đổi giá trị băm ảnh hưởng đến thứ tự lặp lại của các phần, bộ và các ánh xạ khác. Python chưa bao giờ đảm bảo về thứ tự này (và nó thường thay đổi giữa các bản dựng 32 bit và 64 bit).

Xem thêm PYTHONHASHSEED.

Nếu bạn cần một triển khai băm ổn định, bạn có thể muốn xem xét hashlibmô-đun ; điều này thực hiện các hàm băm mật mã. Các dự án pybloom sử dụng phương pháp này .

Vì phần bù bao gồm tiền tố và hậu tố (giá trị bắt đầu và giá trị XORed cuối cùng, tương ứng) nên rất tiếc, bạn không thể chỉ lưu trữ phần bù. Mặt tích cực, điều này có nghĩa là những kẻ tấn công cũng không thể dễ dàng xác định được sự bù đắp với các cuộc tấn công định thời.


9
Tôi hy vọng điều này sẽ hiển thị trong tài liệu băm () và không chỉ trong __hash __ (). +1 cho một câu trả lời tuyệt vời. ps Không phải hashlib là quá mức cần thiết cho việc sử dụng các hàm băm không mật mã?
redlus

1
pybloom sử dụng các hàm băm. Nhưng nếu bạn muốn thứ gì đó nhanh hơn, bạn có thể xem pyhash .
Håken Nắp

3
Tại sao tài liệu gọi nó disablekhi đặt nó thành 0? Tôi không thấy sự khác biệt hiệu quả khi đặt nó thành bất kỳ số hạt giống ổn định cũ nào, trừ khi tôi thiếu thứ gì đó. Ý tôi là khi tôi sử dụng, PYTHONHASHSEED=12345tôi nhận được cùng một hàm băm cho các chuỗi bằng nhau ngay cả trong các phiên - điều này cũng xảy ra khi tôi sử dụng PYTHONHASHSEED=0- hàm băm cho các chuỗi bằng nhau sẽ giống nhau trên các phiên (mặc dù khác 12345, nhưng điều đó rõ ràng, đó là cách hạt giống công việc).
blubberdiblub

@blubberdiblub: hoàn toàn 0không có hạt giống và hàm băm cho các đối tượng bằng với giá trị được tạo trong phiên bản Python cũ hơn mà không có bất kỳ hỗ trợ băm nào.
Martijn Pieters

1
@MartijnPieters Ý nghĩa của việc các băm bị ảnh hưởng là "không có hạt giống nào"? Sự khác biệt về ngữ nghĩa hoặc chất lượng khi có một hạt giống, ví dụ, 12345, ngoài thực tế là nó tạo ra hai nhóm phiên riêng biệt giữa các giá trị băm khác nhau và ngoài PYTHONHASHSEED = 0 bằng với các phiên bản cũ hơn? Bạn có thể liên kết tôi với một đoạn mã nguồn cụ thể không? Tôi đoán quan điểm của tôi là nếu không có sự khác biệt như vậy, tôi sẽ gọi nó là hạt giống của 0 và các phiên bản cũ hơn của Python chỉ hỗ trợ hạt giống bằng 0. Tài liệu về nó hiện tại khá khó hiểu đối với tôi.
blubberdiblub

10

Tính năng ngẫu nhiên băm được bật theo mặc định trong Python 3 . Đây là một tính năng bảo mật:

Việc ngẫu nhiên hóa băm nhằm mục đích cung cấp sự bảo vệ chống lại sự từ chối dịch vụ do các đầu vào được lựa chọn cẩn thận nhằm khai thác hiệu suất trong trường hợp xấu nhất của một cấu trúc dict

Trong các phiên bản trước từ 2.6.8, bạn có thể bật nó tại dòng lệnh với -R hoặc tùy chọn môi trường PYTHONHASHSEED .

Bạn có thể tắt nó bằng cách đặt PYTHONHASHSEEDvề 0.


-9

hash () là một hàm tích hợp sẵn trong Python và sử dụng nó để tính giá trị băm cho đối tượng , không phải cho chuỗi hoặc num.

Bạn có thể xem chi tiết trong trang này: https://docs.python.org/3.3/library/functions.html#hash .

và giá trị hash () đến từ phương thức __hash__ của đối tượng. Tài liệu nói những điều sau:

Theo mặc định, các giá trị băm () của str, byte và các đối tượng datetime là "muối" với một giá trị ngẫu nhiên không thể đoán trước. Mặc dù chúng không đổi trong một quy trình Python riêng lẻ, chúng không thể dự đoán được giữa các lần gọi Python lặp lại.

Đó là lý do tại sao bạn có giá trị băm khác nhau cho cùng một chuỗi trong bảng điều khiển khác nhau.

Những gì bạn thực hiện không phải là một cách tốt.

Khi bạn muốn tính toán một giá trị băm chuỗi, chỉ cần sử dụng hashlib

hash () nhằm mục đích nhận được một giá trị băm đối tượng, không phải là một sting.


6
hash()hoàn toàn hợp lệ cho các giá trị chuỗi hoặc số. Bạn đang bối rối này với __hash__phương pháp tùy chỉnh, sử dụng bằng cáchhash() cung cấp một cài đặt tùy chỉnh của giá trị băm.
Martijn Pieters
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.