如何在std :: hash<>?中更改默认种子?

时间:2016-01-24 12:22:03

标签: c++ c++11 hash

我从this problem了解到std::unordered_map中使用的默认哈希函数是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/

我的问题是如何更改该哈希函数的默认种子,因为常量哈希种子很容易被黑客攻击。

P.S。我知道我可以使用自己的哈希因子unordered_map。但我的问题是关于C ++ 11的内置哈希函数的种子。

2 个答案:

答案 0 :(得分:3)

std::unordered_map的第三个模板参数是要使用的哈希函子,可以设置为你想要的任何哈希函数。

答案 1 :(得分:3)

请注意,根据维基百科,MurmurHash(https://en.wikipedia.org/wiki/MurmurHash)是一种非加密哈希函数,因此如果需要强加密,则不适用。

但是,在std::unordered_map中,出于安全原因不使用散列,而是将键/值对组织到内存桶中。此外,例如在gcc中,基本类型根本没有哈希,而是reinterpret_cast<size_t>size_t。来自http://en.cppreference.com/w/cpp/utility/hash

  

值得注意的是,某些实现使用了普通(标识)哈希函数   将整数映射到自身。换句话说,这些哈希函数   设计用于处理无序的关联容器,但不是   例如,加密哈希。

如果您仍想更改哈希的种子,则需要实现一个仿函数对象并提供自己的哈希算法。下面的代码应该让您了解如何挂钩您自己的哈希实现或如何直接使用MurmurHash2并提供种子。

//HACK表示的行将使用gcc库实现(std::_Hash_impl::hash)中的散列函数,并取决于特定的编译器/库实现。正如其他人所指出的那样,不鼓励直接使用这个功能。

如果需要对除std::string以外的其他类型进行哈希处理,则需要实现不同的模板专业化。

#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;
};

从github获取MurmurHash。