Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I change the default seed in std::hash<>?

Tags:

c++

c++11

hash

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 factor with unordered_map. But my question is about the seed of builtin hash function of C++11.

like image 528
Wizmann Avatar asked Mar 13 '23 12:03

Wizmann


2 Answers

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.

like image 26
Shoe Avatar answered Mar 24 '23 08:03

Shoe


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.

like image 108
Jan Müller Avatar answered Mar 24 '23 09:03

Jan Müller