mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-08 05:27:14 +09:00
AK+Meta+LibCore+Tests: Remove unused SipHash
implementation
This is a homegrown implementation that wasn't actually used in dependent classes. If this is needed in the future, using OpenSSL would probably be a better option.
This commit is contained in:
parent
f1f7f68f36
commit
37998895d8
Notes:
github-actions[bot]
2025-04-05 23:48:44 +00:00
Author: https://github.com/rmg-x
Commit: 37998895d8
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4244
8 changed files with 0 additions and 261 deletions
|
@ -20,7 +20,6 @@ set(SOURCES
|
||||||
NumberFormat.cpp
|
NumberFormat.cpp
|
||||||
OptionParser.cpp
|
OptionParser.cpp
|
||||||
Random.cpp
|
Random.cpp
|
||||||
SipHash.cpp
|
|
||||||
StackInfo.cpp
|
StackInfo.cpp
|
||||||
Stream.cpp
|
Stream.cpp
|
||||||
String.cpp
|
String.cpp
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
#include <AK/Endian.h>
|
#include <AK/Endian.h>
|
||||||
#include <AK/Format.h>
|
#include <AK/Format.h>
|
||||||
#include <AK/Optional.h>
|
#include <AK/Optional.h>
|
||||||
#include <AK/SipHash.h>
|
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <AK/StringView.h>
|
#include <AK/StringView.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
@ -144,11 +143,6 @@ private:
|
||||||
|
|
||||||
static_assert(sizeof(IPv4Address) == 4);
|
static_assert(sizeof(IPv4Address) == 4);
|
||||||
|
|
||||||
template<>
|
|
||||||
struct Traits<IPv4Address> : public DefaultTraits<IPv4Address> {
|
|
||||||
static unsigned hash(IPv4Address const& address) { return secure_sip_hash(static_cast<u64>(address.to_u32())); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Formatter<IPv4Address> : Formatter<StringView> {
|
struct Formatter<IPv4Address> : Formatter<StringView> {
|
||||||
ErrorOr<void> format(FormatBuilder& builder, IPv4Address value)
|
ErrorOr<void> format(FormatBuilder& builder, IPv4Address value)
|
||||||
|
|
|
@ -267,12 +267,6 @@ private:
|
||||||
|
|
||||||
static_assert(sizeof(IPv6Address) == 16);
|
static_assert(sizeof(IPv6Address) == 16);
|
||||||
|
|
||||||
template<>
|
|
||||||
struct Traits<IPv6Address> : public DefaultTraits<IPv6Address> {
|
|
||||||
// SipHash-4-8 is considered conservatively secure, even if not cryptographically secure.
|
|
||||||
static unsigned hash(IPv6Address const& address) { return sip_hash_bytes<4, 8>({ &address.to_in6_addr_t(), sizeof(address.to_in6_addr_t()) }); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Formatter<IPv6Address> : Formatter<StringView> {
|
struct Formatter<IPv6Address> : Formatter<StringView> {
|
||||||
ErrorOr<void> format(FormatBuilder& builder, IPv6Address const& value)
|
ErrorOr<void> format(FormatBuilder& builder, IPv6Address const& value)
|
||||||
|
|
176
AK/SipHash.cpp
176
AK/SipHash.cpp
|
@ -1,176 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023, kleines Filmröllchen <filmroellchen@serenityos.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <AK/ByteReader.h>
|
|
||||||
#include <AK/Random.h>
|
|
||||||
#include <AK/Singleton.h>
|
|
||||||
#include <AK/SipHash.h>
|
|
||||||
#include <AK/Span.h>
|
|
||||||
#include <AK/UFixedBigInt.h>
|
|
||||||
|
|
||||||
namespace AK {
|
|
||||||
|
|
||||||
ALWAYS_INLINE constexpr u64 rotate_left(u64 x, u64 bits)
|
|
||||||
{
|
|
||||||
return static_cast<u64>(((x) << (bits)) | ((x) >> (64 - (bits))));
|
|
||||||
}
|
|
||||||
|
|
||||||
ALWAYS_INLINE constexpr void sipround(u64& v0, u64& v1, u64& v2, u64& v3)
|
|
||||||
{
|
|
||||||
v0 += v1;
|
|
||||||
v1 = rotate_left(v1, 13);
|
|
||||||
v1 ^= v0;
|
|
||||||
v0 = rotate_left(v0, 32);
|
|
||||||
v2 += v3;
|
|
||||||
v3 = rotate_left(v3, 16);
|
|
||||||
v3 ^= v2;
|
|
||||||
v0 += v3;
|
|
||||||
v3 = rotate_left(v3, 21);
|
|
||||||
v3 ^= v0;
|
|
||||||
v2 += v1;
|
|
||||||
v1 = rotate_left(v1, 17);
|
|
||||||
v1 ^= v2;
|
|
||||||
v2 = rotate_left(v2, 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can handle u64 or u128 output as per reference implementation.
|
|
||||||
// We currenly only use u64 and further fold it to u32 (unsigned) for use in Traits.
|
|
||||||
template<size_t message_block_rounds, size_t finalization_rounds>
|
|
||||||
static void do_siphash(ReadonlyBytes input, u128 key, Bytes output)
|
|
||||||
{
|
|
||||||
VERIFY((output.size() == 8) || (output.size() == 16));
|
|
||||||
|
|
||||||
u64 v0 = 0x736f6d6570736575ull;
|
|
||||||
u64 v1 = 0x646f72616e646f6dull;
|
|
||||||
u64 v2 = 0x6c7967656e657261ull;
|
|
||||||
u64 v3 = 0x7465646279746573ull;
|
|
||||||
u64 const length = input.size();
|
|
||||||
auto const left = length & 7;
|
|
||||||
// The end of 64-bit blocks.
|
|
||||||
auto const block_end = length - (length % sizeof(u64));
|
|
||||||
u64 b = length << 56;
|
|
||||||
v3 ^= key.high();
|
|
||||||
v2 ^= key.low();
|
|
||||||
v1 ^= key.high();
|
|
||||||
v0 ^= key.low();
|
|
||||||
|
|
||||||
if (output.size() == 16)
|
|
||||||
v1 ^= 0xee;
|
|
||||||
|
|
||||||
for (size_t input_index = 0; input_index < block_end; input_index += 8) {
|
|
||||||
u64 const m = bit_cast<LittleEndian<u64>>(ByteReader::load64(input.slice(input_index, sizeof(u64)).data()));
|
|
||||||
v3 ^= m;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < message_block_rounds; ++i)
|
|
||||||
sipround(v0, v1, v2, v3);
|
|
||||||
|
|
||||||
v0 ^= m;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (left) {
|
|
||||||
case 7:
|
|
||||||
b |= (static_cast<u64>(input[block_end + 6])) << 48;
|
|
||||||
[[fallthrough]];
|
|
||||||
case 6:
|
|
||||||
b |= (static_cast<u64>(input[block_end + 5])) << 40;
|
|
||||||
[[fallthrough]];
|
|
||||||
case 5:
|
|
||||||
b |= (static_cast<u64>(input[block_end + 4])) << 32;
|
|
||||||
[[fallthrough]];
|
|
||||||
case 4:
|
|
||||||
b |= (static_cast<u64>(input[block_end + 3])) << 24;
|
|
||||||
[[fallthrough]];
|
|
||||||
case 3:
|
|
||||||
b |= (static_cast<u64>(input[block_end + 2])) << 16;
|
|
||||||
[[fallthrough]];
|
|
||||||
case 2:
|
|
||||||
b |= (static_cast<u64>(input[block_end + 1])) << 8;
|
|
||||||
[[fallthrough]];
|
|
||||||
case 1:
|
|
||||||
b |= (static_cast<u64>(input[block_end + 0]));
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
v3 ^= b;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < message_block_rounds; ++i)
|
|
||||||
sipround(v0, v1, v2, v3);
|
|
||||||
|
|
||||||
v0 ^= b;
|
|
||||||
|
|
||||||
if (output.size() == 16)
|
|
||||||
v2 ^= 0xee;
|
|
||||||
else
|
|
||||||
v2 ^= 0xff;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < finalization_rounds; ++i)
|
|
||||||
sipround(v0, v1, v2, v3);
|
|
||||||
|
|
||||||
b = v0 ^ v1 ^ v2 ^ v3;
|
|
||||||
|
|
||||||
LittleEndian<u64> b_le { b };
|
|
||||||
output.overwrite(0, &b_le, sizeof(b_le));
|
|
||||||
|
|
||||||
if (output.size() == 8)
|
|
||||||
return;
|
|
||||||
|
|
||||||
v1 ^= 0xdd;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < finalization_rounds; ++i)
|
|
||||||
sipround(v0, v1, v2, v3);
|
|
||||||
|
|
||||||
b = v0 ^ v1 ^ v2 ^ v3;
|
|
||||||
b_le = b;
|
|
||||||
output.overwrite(sizeof(b_le), &b_le, sizeof(b_le));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SipHashKey {
|
|
||||||
SipHashKey()
|
|
||||||
{
|
|
||||||
// get_random is assumed to be secure, otherwise SipHash doesn't deliver on its promises!
|
|
||||||
key = get_random<u128>();
|
|
||||||
}
|
|
||||||
constexpr u128 operator*() const { return key; }
|
|
||||||
u128 key;
|
|
||||||
};
|
|
||||||
// Using a singleton is a little heavier than a plain static, but avoids an initialization order fiasco.
|
|
||||||
static Singleton<SipHashKey> static_sip_hash_key;
|
|
||||||
|
|
||||||
template<size_t message_block_rounds, size_t finalization_rounds>
|
|
||||||
unsigned sip_hash_u64(u64 input)
|
|
||||||
{
|
|
||||||
ReadonlyBytes input_bytes { &input, sizeof(input) };
|
|
||||||
u64 const output_u64 = sip_hash_bytes<message_block_rounds, finalization_rounds>(input_bytes);
|
|
||||||
return static_cast<unsigned>(output_u64 ^ (output_u64 >> 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned standard_sip_hash(u64 input)
|
|
||||||
{
|
|
||||||
return sip_hash_u64<1, 3>(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned secure_sip_hash(u64 input)
|
|
||||||
{
|
|
||||||
return sip_hash_u64<4, 8>(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<size_t message_block_rounds, size_t finalization_rounds>
|
|
||||||
u64 sip_hash_bytes(ReadonlyBytes input)
|
|
||||||
{
|
|
||||||
auto sip_hash_key = **static_sip_hash_key;
|
|
||||||
u64 output = 0;
|
|
||||||
Bytes output_bytes { &output, sizeof(output) };
|
|
||||||
do_siphash<message_block_rounds, finalization_rounds>(input, sip_hash_key, output_bytes);
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Instantiate all used SipHash variants here:
|
|
||||||
template u64 sip_hash_bytes<1, 3>(ReadonlyBytes);
|
|
||||||
template u64 sip_hash_bytes<4, 8>(ReadonlyBytes);
|
|
||||||
|
|
||||||
}
|
|
29
AK/SipHash.h
29
AK/SipHash.h
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023, kleines Filmröllchen <filmroellchen@serenityos.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <AK/Forward.h>
|
|
||||||
|
|
||||||
namespace AK {
|
|
||||||
|
|
||||||
// Ported from the SipHash reference implementation, released to the public domain:
|
|
||||||
// https://github.com/veorq/SipHash/blob/eee7d0d84dc7731df2359b243aa5e75d85f6eaef/siphash.c
|
|
||||||
// The standard is SipHash-2-4, but we use 1-3 for a little more speed.
|
|
||||||
// Cryptography should use 4-8 for (relative) conservative security,
|
|
||||||
// though SipHash itself is NOT a cryptographically secure hash algorithm.
|
|
||||||
template<size_t message_block_rounds, size_t finalization_rounds>
|
|
||||||
u64 sip_hash_bytes(ReadonlyBytes input);
|
|
||||||
unsigned standard_sip_hash(u64 input);
|
|
||||||
unsigned secure_sip_hash(u64 input);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USING_AK_GLOBALLY
|
|
||||||
using AK::secure_sip_hash;
|
|
||||||
using AK::sip_hash_bytes;
|
|
||||||
using AK::standard_sip_hash;
|
|
||||||
#endif
|
|
|
@ -140,11 +140,3 @@ struct AK::Formatter<Core::SocketAddress> : Formatter<ByteString> {
|
||||||
return Formatter<ByteString>::format(builder, value.to_byte_string());
|
return Formatter<ByteString>::format(builder, value.to_byte_string());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
|
||||||
struct AK::Traits<Core::SocketAddress> : public DefaultTraits<Core::SocketAddress> {
|
|
||||||
static unsigned hash(Core::SocketAddress const& socket_address)
|
|
||||||
{
|
|
||||||
return pair_int_hash(Traits<IPv4Address>::hash(socket_address.ipv4_address()), Traits<u16>::hash(socket_address.port()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
|
@ -154,8 +154,6 @@ shared_library("AK") {
|
||||||
"Singleton.h",
|
"Singleton.h",
|
||||||
"SinglyLinkedList.h",
|
"SinglyLinkedList.h",
|
||||||
"SinglyLinkedListSizePolicy.h",
|
"SinglyLinkedListSizePolicy.h",
|
||||||
"SipHash.cpp",
|
|
||||||
"SipHash.h",
|
|
||||||
"SourceGenerator.h",
|
"SourceGenerator.h",
|
||||||
"SourceLocation.h",
|
"SourceLocation.h",
|
||||||
"Span.h",
|
"Span.h",
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include <LibTest/TestCase.h>
|
#include <LibTest/TestCase.h>
|
||||||
|
|
||||||
#include <AK/HashFunctions.h>
|
#include <AK/HashFunctions.h>
|
||||||
#include <AK/SipHash.h>
|
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
|
||||||
TEST_CASE(int_hash)
|
TEST_CASE(int_hash)
|
||||||
|
@ -55,28 +54,6 @@ TEST_CASE(constexpr_ptr_hash)
|
||||||
static_assert(ptr_hash(FlatPtr(42)));
|
static_assert(ptr_hash(FlatPtr(42)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Testing concrete hash results is not possible due to SipHash's non-determinism.
|
|
||||||
// We instead perform some sanity checks and try to hit any asserts caused by programming errors.
|
|
||||||
TEST_CASE(sip_hash)
|
|
||||||
{
|
|
||||||
EXPECT_EQ(standard_sip_hash(42), standard_sip_hash(42));
|
|
||||||
EXPECT_EQ(secure_sip_hash(42), secure_sip_hash(42));
|
|
||||||
EXPECT_NE(standard_sip_hash(42), secure_sip_hash(42));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE(sip_hash_bytes)
|
|
||||||
{
|
|
||||||
constexpr Array<u8, 8> short_test_array { 1, 2, 3, 4, 5, 6, 7, 8 };
|
|
||||||
constexpr Array<u8, 16> common_prefix_array { 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
||||||
EXPECT_EQ((sip_hash_bytes<1, 3>(short_test_array.span())), (sip_hash_bytes<1, 3>(short_test_array.span())));
|
|
||||||
EXPECT_NE((sip_hash_bytes<1, 3>(short_test_array.span())), (sip_hash_bytes<1, 3>(common_prefix_array.span())));
|
|
||||||
|
|
||||||
for (size_t prefix_length = 1; prefix_length < 8; ++prefix_length) {
|
|
||||||
EXPECT_NE((sip_hash_bytes<1, 3>(short_test_array.span().trim(prefix_length))), (sip_hash_bytes<1, 3>(short_test_array.span())));
|
|
||||||
EXPECT_EQ((sip_hash_bytes<1, 3>(short_test_array.span().trim(prefix_length))), (sip_hash_bytes<1, 3>(common_prefix_array.span().trim(prefix_length))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename HashFunction>
|
template<typename HashFunction>
|
||||||
requires(IsCallableWithArguments<HashFunction, unsigned, u64>)
|
requires(IsCallableWithArguments<HashFunction, unsigned, u64>)
|
||||||
static void run_benchmark(HashFunction hash_function)
|
static void run_benchmark(HashFunction hash_function)
|
||||||
|
@ -94,13 +71,3 @@ BENCHMARK_CASE(deterministic_hash)
|
||||||
{
|
{
|
||||||
run_benchmark(u64_hash);
|
run_benchmark(u64_hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_CASE(fast_sip_hash)
|
|
||||||
{
|
|
||||||
run_benchmark(standard_sip_hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
BENCHMARK_CASE(secure_sip_hash)
|
|
||||||
{
|
|
||||||
run_benchmark(secure_sip_hash);
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue