4

I learn from this problem that the default hash function used in std::unordered_map is murmurhash2.

// This file defines Hash_bytes, a primitive used for defining hash
// functions. Based on public domain MurmurHashUnaligned2, by Austin
// Appleby.  http://murmurhash.googlepages.com/

My problem is how can I change the default seed of that hash function, as a constant hash seed is prone to be hacked.

p.s. I know I can use my own hash functor with unordered_map. But my question is about the seed of builtin hash function of C++11.

Wizmann
  • 839
  • 1
  • 9
  • 14

2 Answers2

4

Note that, according to Wikipedia, MurmurHash (https://en.wikipedia.org/wiki/MurmurHash) is a non-cryptographic hash function, thus not suited if strong cryptography is needed.

However, in a std::unordered_map, the hash is not used for security reasons but to organize the key/value pairs into buckets of memory. Moreover, for example in gcc, basic types are not hashed at all, but reinterpret_cast<size_t> to size_t. From http://en.cppreference.com/w/cpp/utility/hash :

Notably, some implementations use trivial (identity) hash functions which map an integer to itself. In other words, these hash functions are designed to work with unordered associative containers, but not as cryptographic hashes, for example.

If you nevertheless want to change the seed of the hash, you need to implement a functor object and provide your own hash algorithm. The code below should give you an idea how to hook in your own hash implementation or how to directly use MurmurHash2 and provide a seed.

The line indicated with //HACK will use the hash function from the gcc library implementation (std::_Hash_impl::hash) and will depend on a particular compiler/library implementation. As others pointed out, direct use of this function is discouraged.

If other types than std::string need to be hashed, different template specializations need to be implemented.

#include <string>
#include <unordered_map>
#include "MurmurHash2.h"

template <class T> struct MyHash;
template<> struct MyHash<std::string>
{
    std::size_t operator()(std::string const& s) const noexcept
    {
        size_t seed = static_cast<size_t>(0xdeadbeef);
        //return std::_Hash_impl::hash(s.data(), s.length(), seed); //HACK
        return MurmurHash2 ( s.data(), s.length(), seed );
    }
};


int main()
{
    std::unordered_map<std::string,std::string,MyHash<std::string> >
            u_map { {"s1","A"} , {"s2","B"} };
    return 0;
};

Get MurmurHash from github.

Jan Müller
  • 413
  • 3
  • 18
  • 5
    one should **not** use [implementation reserved identifiers](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier) – m.s. Jan 24 '16 at 14:19
  • 1
    As m.s. pointed out, using _Hash_impl directly is probably quite a hack :-) But the code should give you simply an idea how to hook in your own hash implementation or how to directly use MurmurHash2 and provide a seed. I changed that in the code. – Jan Müller Jan 24 '16 at 15:01
  • @JanMüller the previous answer is perfectly fine for me. Plz add it to the answer. Thanks. – Wizmann Jan 24 '16 at 15:29
3

The third template argument of std::unordered_map is the hash functor to be used, which can be set to whatever hash function you want.

Shoe
  • 74,840
  • 36
  • 166
  • 272
  • I know that. But I don't want to write my own hash function as murmur hash is good enough. Is there any easy way to change the seed of the hash function? – Wizmann Jan 24 '16 at 14:23