Commit f0551863 authored by Francis Dupont's avatar Francis Dupont
Browse files

[5502] Added FNV-1a 64 bit hash and replaced MD5 in CQL host dats source

parent a7ee7ea3
......@@ -17,7 +17,7 @@ if HAVE_PGSQL
AM_CPPFLAGS += $(PGSQL_CPPFLAGS)
endif
if HAVE_CQL
AM_CPPFLAGS += $(CQL_CPPFLAGS) $(CRYPTO_INCLUDES)
AM_CPPFLAGS += $(CQL_CPPFLAGS)
endif
AM_CXXFLAGS = $(KEA_CXXFLAGS)
......
......@@ -28,13 +28,10 @@
#include <dhcpsrv/db_exceptions.h>
#include <dhcpsrv/dhcpsrv_log.h>
#include <util/buffer.h>
#include <util/hash.h>
#include <util/optional_value.h>
#include <asiolink/io_address.h>
/// @todo: With this include, Cassandra backend requires compilation with openssl.
/// Kea supports two crypto libs: openssl and botan. The abstraction layer provided
/// is via cryptolink.
#include <openssl/md5.h> // for MD5_DIGEST_LENGTH
#include <stdint.h> // for uint64_t
#include <boost/algorithm/string/classification.hpp> // for boost::is_any_of
......@@ -185,9 +182,8 @@ public:
/// @brief Create unique hash for storage in table id.
///
/// Hash function used for creating a pseudo-unique hash from member
/// values which uniquely determine an entry in the table. Uses OpenSSL's
/// MD5 implementation.
/// @todo: This must be generic and use cryptolink wrapper. See ticket #5502.
/// values which uniquely determine an entry in the table. Uses FNV-1a
/// on 64 bits.
///
/// The primary key aggregates: host_ipv4_subnet_id, host_ipv6_subnet_id,
/// host_ipv4_address, reserved_ipv6_prefix_address,
......@@ -859,50 +855,25 @@ CqlHostExchange::createBindForMutation(const HostPtr& host,
}
}
uint64_t
md5Hash(const std::string& input) {
/// @todo: Convert this code to cryptolink calls and replace the
/// direct use fromn md5.
// Prepare structures for MD5().
const size_t word_size = MD5_DIGEST_LENGTH / sizeof(uint64_t);
uint64_t hash[word_size];
unsigned char* digest = reinterpret_cast<unsigned char*>(hash);
unsigned char* string = reinterpret_cast<unsigned char*>(const_cast<char*>(input.c_str()));
std::fill(hash, hash + word_size, 0);
// Get MD5 hash value.
MD5(string, input.size(), digest);
// Return the first part of the hash value which still retains all
// properties of the full hash value.
return (hash[0]);
}
cass_int64_t
CqlHostExchange::hashIntoId() const {
// Allocates a fixed maximum length in the stringstream for each
// aggregated field to avoid collisions between distinct entries.
// Add a separator between aggregated field to avoid collisions
// between distinct entries.
// Get key.
std::stringstream key_stream;
key_stream << std::setw(10) << std::setfill('-') << host_ipv4_subnet_id_;
key_stream << std::setw(10) << std::setfill('-') << host_ipv6_subnet_id_;
key_stream << std::setw(V4ADDRESS_TEXT_MAX_LEN) << std::setfill('-')
<< host_ipv4_address_;
key_stream << std::setw(V6ADDRESS_TEXT_MAX_LEN) << std::setfill('-')
<< reserved_ipv6_prefix_address_;
key_stream << std::setw(4) << std::setfill('-')
<< reserved_ipv6_prefix_length_;
key_stream << std::setw(4) << std::setfill('-') << option_code_;
key_stream << std::setw(OPTION_SPACE_MAX_LENGTH) << std::setfill('-')
<< option_space_;
key_stream << host_ipv4_subnet_id_ << "-";
key_stream << host_ipv6_subnet_id_ << "-";
key_stream << host_ipv4_address_ << "-";
key_stream << reserved_ipv6_prefix_address_ << "/";
key_stream << reserved_ipv6_prefix_length_ << "-";
key_stream << option_code_ << "-";
key_stream << option_space_;
const std::string key = key_stream.str();
const cass_int64_t md5 = static_cast<cass_int64_t>(md5Hash(key));
const cass_int64_t hash = static_cast<cass_int64_t>(Hash64::hash(key));
return (md5);
return (hash);
}
boost::any
......@@ -1287,7 +1258,7 @@ private:
/// @brief hash function for HostMap
///
/// Returns a 64-bits key value. The key is generated with MD5 hash
/// Returns a 64-bits key value. The key is generated with FNV-1a 64 bit
/// algorithm.
///
/// @param key being hashed
......@@ -1298,21 +1269,16 @@ hash_value(const HostKey& key) {
// Get key.
std::stringstream key_stream;
HostIdentifier host_identifier = std::get<HOST_IDENTIFIER>(key);
key_stream << std::setw(DUID::MAX_DUID_LEN) << std::setfill('0')
<< DUID(host_identifier).toText();
key_stream << std::setw(2) << std::setfill('0')
<< std::get<HOST_IDENTIFIER_TYPE>(key);
key_stream << std::setw(10) << std::setfill('0')
<< std::get<IPv4_SUBNET_ID>(key);
key_stream << std::setw(10) << std::setfill('0')
<< std::get<IPv6_SUBNET_ID>(key);
key_stream << std::setw(V4ADDRESS_TEXT_MAX_LEN) << std::setfill('0')
<< std::get<IPv4_RESERVATION>(key);
key_stream << DUID(host_identifier).toText() << "-";
key_stream << std::get<HOST_IDENTIFIER_TYPE>(key) << "-";
key_stream << std::get<IPv4_SUBNET_ID>(key) << "-";
key_stream << std::get<IPv6_SUBNET_ID>(key) << "-";
key_stream << std::get<IPv4_RESERVATION>(key);
const std::string key_string = key_stream.str();
const uint64_t md5 = md5Hash(key_string);
const uint64_t hash = Hash64::hash(key_string);
return (static_cast<std::size_t>(md5));
return (static_cast<std::size_t>(hash));
}
/// @brief equals operator for HostKey
......
......@@ -11,6 +11,7 @@ libkea_util_la_SOURCES = boost_time_utils.h boost_time_utils.cc
libkea_util_la_SOURCES += buffer.h io_utilities.h
libkea_util_la_SOURCES += csv_file.h csv_file.cc
libkea_util_la_SOURCES += filename.h filename.cc
libkea_util_la_SOURCES += hash.h
libkea_util_la_SOURCES += labeled_value.h labeled_value.cc
libkea_util_la_SOURCES += memory_segment.h
libkea_util_la_SOURCES += memory_segment_local.h memory_segment_local.cc
......@@ -50,6 +51,7 @@ libkea_util_include_HEADERS = \
buffer.h \
csv_file.h \
filename.h \
hash.h \
io_utilities.h \
labeled_value.h \
memory_segment.h \
......
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef HASH_H
#define HASH_H
#include <cstddef>
#include <cstdint>
#include <string>
namespace isc {
namespace util {
/// @brief Hash implementation based on Fowler-Noll-Vo hash function
///
struct Hash64 {
/// @brief Compute the hash
///
/// FNV-1a hash function
///
/// @param data data to hash
/// @param length length of data
/// @return the hash value
static uint64_t hash(const uint8_t* data, size_t length) {
uint64_t hash = FNV_offset_basis;
for (size_t i = 0; i < length; ++i) {
hash = hash ^ data[i];
hash = hash * FNV_prime;
}
return (hash);
}
/// @brief Compute the hash
///
/// FNV-1a hash function
///
/// @param str not empty string to hash
/// @return the hash value
static uint64_t hash(const std::string& str) {
return (hash(reinterpret_cast<const uint8_t*>(str.c_str()),
str.size()));
}
/// @brief Offset basis
static const uint64_t FNV_offset_basis = 14695981039346656037ull;
/// @brief Prime
static const uint64_t FNV_prime = 1099511628211ull;
};
} // end of namespace isc::util
} // end of namespace isc
#endif
......@@ -36,6 +36,7 @@ run_unittests_SOURCES += csv_file_unittest.cc
run_unittests_SOURCES += fd_share_tests.cc
run_unittests_SOURCES += fd_tests.cc
run_unittests_SOURCES += filename_unittest.cc
run_unittests_SOURCES += hash_unittest.cc
run_unittests_SOURCES += hex_unittest.cc
run_unittests_SOURCES += io_utilities_unittest.cc
run_unittests_SOURCES += labeled_value_unittest.cc
......
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <util/hash.h>
#include <gtest/gtest.h>
#include <cstring>
#include <vector>
using namespace isc::util;
using namespace std;
namespace {
TEST(HashTest, empty) {
EXPECT_EQ(14695981039346656037ull, Hash64::hash(0, 0));
}
TEST(HashTest, foobar) {
EXPECT_EQ(9625390261332436968ull, Hash64::hash(string("foobar")));
}
TEST(HashTest, chongo) {
EXPECT_EQ(5080352029159061781ull,
Hash64::hash(string("chongo was here!\n")));
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment