Now I started to read in depth about hashes and hash tables. And there was one question that puzzled me.
As you know, in python, the hash of an integer is the number itself. However, if I understand correctly, such a hash function should be considered very bad – it does not have the avalanche property at all, and hashes from consecutive keys will be consecutive numbers.
What's the matter? Am I misunderstanding something about the concept of a good hash function? Or is the result of the hash() function not directly used in Python dictionaries and sets, but is somehow additionally processed?
The built-in hash function has completely different tasks, not related to cryptography. It is used for quick and easy comparison of dictionary keys.
Hash values are integers. They are used to quickly compare dictionary keys during a dictionary lookup. Numeric values that compare equal have the same hash value (even if they are of different types, as is the case for 1 and 1.0).
Regarding consecutive keys:
In : hash('aaaa') Out: 5927745366728125705 In : hash('aaab') Out: 3762861188151674483 In : hash('aaac') Out: -5197229166136799781
For "cryptographic" purposes, it is worth paying attention to the hashlib module:
In : hashlib.sha512(b'aaa').hexdigest() Out: 'd6f644b19812e97b5d871658d6d3400ecd4787faeb9b8990c1e7608288664be77257104a58d033bcf1a0e0945ff06468ebe53e2dff36e248424c7273117dac09' In : hashlib.sha512(b'123').hexdigest() Out: '3c9909afec25354d551dae21590bb26e38d53f2173b8d3dc3eee4c047e7ab1c1eb8b85103e3be7ba613b31bb5c9c36214dc9f14a42fd7a2fdb84856bca5c44c2'
Example from the docs using "salt":
>>> import os >>> from hashlib import blake2b >>> msg = b'some message' >>> # Calculate the first hash with a random salt. >>> salt1 = os.urandom(blake2b.SALT_SIZE) >>> h1 = blake2b(salt=salt1) >>> h1.update(msg) >>> # Calculate the second hash with a different random salt. >>> salt2 = os.urandom(blake2b.SALT_SIZE) >>> h2 = blake2b(salt=salt2) >>> h2.update(msg) >>> # The digests are different. >>> h1.digest() != h2.digest() True