siphash.h
1 // Copyright (c) 2016-present The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 #ifndef BITCOIN_CRYPTO_SIPHASH_H 6 #define BITCOIN_CRYPTO_SIPHASH_H 7 8 #include <array> 9 #include <cstdint> 10 #include <span> 11 12 class uint256; 13 14 /** Shared SipHash internal state v[0..3], initialized from (k0, k1). */ 15 class SipHashState 16 { 17 static constexpr uint64_t C0{0x736f6d6570736575ULL}, C1{0x646f72616e646f6dULL}, C2{0x6c7967656e657261ULL}, C3{0x7465646279746573ULL}; 18 19 public: 20 explicit SipHashState(uint64_t k0, uint64_t k1) noexcept : v{C0 ^ k0, C1 ^ k1, C2 ^ k0, C3 ^ k1} {} 21 22 std::array<uint64_t, 4> v{}; 23 }; 24 25 /** General SipHash-2-4 implementation. */ 26 class CSipHasher 27 { 28 SipHashState m_state; 29 uint64_t m_tmp{0}; 30 uint8_t m_count{0}; //!< Only the low 8 bits of the input size matter. 31 32 public: 33 /** Construct a SipHash calculator initialized with 128-bit key (k0, k1). */ 34 CSipHasher(uint64_t k0, uint64_t k1); 35 /** Hash a 64-bit integer worth of data. 36 * It is treated as if this was the little-endian interpretation of 8 bytes. 37 * This function can only be used when a multiple of 8 bytes have been written so far. 38 */ 39 CSipHasher& Write(uint64_t data); 40 /** Hash arbitrary bytes. */ 41 CSipHasher& Write(std::span<const unsigned char> data); 42 /** Compute the 64-bit SipHash-2-4 of the data written so far. The object remains untouched. */ 43 uint64_t Finalize() const; 44 }; 45 46 /** 47 * Optimized SipHash-2-4 implementation for uint256. 48 * 49 * This class caches the initial SipHash v[0..3] state derived from (k0, k1) 50 * and implements a specialized hashing path for uint256 values, with or 51 * without an extra 32-bit word. The internal state is immutable, so 52 * PresaltedSipHasher instances can be reused for multiple hashes with the 53 * same key. 54 */ 55 class PresaltedSipHasher 56 { 57 const SipHashState m_state; 58 59 public: 60 explicit PresaltedSipHasher(uint64_t k0, uint64_t k1) noexcept : m_state{k0, k1} {} 61 62 /** Equivalent to CSipHasher(k0, k1).Write(val).Finalize(). */ 63 uint64_t operator()(const uint256& val) const noexcept; 64 65 /** 66 * Equivalent to CSipHasher(k0, k1).Write(val).Write(extra).Finalize(), 67 * with `extra` encoded as 4 little-endian bytes. 68 */ 69 uint64_t operator()(const uint256& val, uint32_t extra) const noexcept; 70 }; 71 72 #endif // BITCOIN_CRYPTO_SIPHASH_H