Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2016-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#ifndef BITCOIN_CRYPTO_SIPHASH_H6#define BITCOIN_CRYPTO_SIPHASH_H8#include <attributes.h>9#include <uint256.h>11#include <bit>12#include <cstdint>13#include <span>15/** Shared SipHash state (v0..v3) with its round, compression, and finalization primitives.16* Internal building block, only meant to be composed by the hasher classes below. */17class SipHashState18{19/** SipHash initialization constants. */20static constexpr uint64_t C0{0x736f6d6570736575}, C1{0x646f72616e646f6d}, C2{0x6c7967656e657261}, C3{0x7465646279746573};21/** SipHash v2 finalizer constant. */22static constexpr uint64_t FINALIZER{0xFF};23/** SipHash custom unpadded finalizer constant. */24static constexpr uint64_t FINALIZER_UNPADDED{0x6465646461706e75};25static_assert(FINALIZER_UNPADDED != FINALIZER);27/** Construct a SipHashState with the specified values as state. */28ALWAYS_INLINE SipHashState(uint64_t v0, uint64_t v1, uint64_t v2, uint64_t v3) noexcept : m_v0{v0}, m_v1{v1}, m_v2{v2}, m_v3{v3} {}30/** State variables. */31uint64_t m_v0, m_v1, m_v2, m_v3;33/** Mutably perform one SipRound on this state. */34ALWAYS_INLINE void SipRound() noexcept35{36m_v0 += m_v1; m_v1 = std::rotl(m_v1, 13); m_v1 ^= m_v0;37m_v0 = std::rotl(m_v0, 32);38m_v2 += m_v3; m_v3 = std::rotl(m_v3, 16); m_v3 ^= m_v2;39m_v0 += m_v3; m_v3 = std::rotl(m_v3, 21); m_v3 ^= m_v0;40m_v2 += m_v1; m_v1 = std::rotl(m_v1, 17); m_v1 ^= m_v2;41m_v2 = std::rotl(m_v2, 32);42}44public:45/** Construct a SipHashState initialized with the specified key. */46explicit ALWAYS_INLINE SipHashState(uint64_t k0, uint64_t k1) noexcept : SipHashState{C0 ^ k0, C1 ^ k1, C2 ^ k0, C3 ^ k1} {}47/** Construct a copy of this state. */48ALWAYS_INLINE SipHashState Copy() const noexcept { return {m_v0, m_v1, m_v2, m_v3}; }49/** Mutably compress one block into this state, with 1 SipRound. */50ALWAYS_INLINE SipHashState& Compress1(uint64_t data) noexcept51{52m_v3 ^= data;53SipRound();54m_v0 ^= data;55return *this;56}57/** Mutably compress one jumbo block into this state, with 1 SipRound. */58ALWAYS_INLINE SipHashState& Compress1Jumbo(const uint256& data) noexcept59{60const uint64_t d0{data.GetUint64(0)}, d1{data.GetUint64(1)}, d2{data.GetUint64(2)}, d3{data.GetUint64(3)};61m_v3 ^= d0; m_v0 ^= d1; m_v1 ^= d2; m_v2 ^= d3;62SipRound();63m_v0 ^= d0; m_v1 ^= d1; m_v2 ^= d2; m_v3 ^= d3;64return *this;65}66/** Mutably compress one block into this state, with 2 SipRounds. */67ALWAYS_INLINE SipHashState& Compress2(uint64_t data) noexcept68{69m_v3 ^= data;70SipRound();71SipRound();72m_v0 ^= data;73return *this;74}75/** Mutably finalize this state with 4 SipRounds, and return the resulting hash. */76ALWAYS_INLINE uint64_t Finalize4() noexcept77{78m_v2 ^= FINALIZER;79SipRound();80SipRound();81SipRound();82SipRound();83return m_v0 ^ m_v1 ^ m_v2 ^ m_v3;84}85/** Mutably finalize this state with 3 SipRounds using the unpadded finalizer, and return the86* resulting hash. */87ALWAYS_INLINE uint64_t Finalize3U() noexcept88{89m_v2 ^= FINALIZER_UNPADDED;90SipRound();91SipRound();92SipRound();93return m_v0 ^ m_v1 ^ m_v2 ^ m_v3;94}95};97/** General SipHash-2-4 implementation. */98class CSipHasher99{100SipHashState m_state;101uint64_t m_tmp{0};102uint8_t m_count{0}; //!< Only the low 8 bits of the input size matter.104public:105/** Construct a SipHash calculator initialized with 128-bit key (k0, k1). */106CSipHasher(uint64_t k0, uint64_t k1);107/** Hash a 64-bit integer worth of data.108* It is treated as if this was the little-endian interpretation of 8 bytes.109* This function can only be used when a multiple of 8 bytes have been written so far.110*/111CSipHasher& Write(uint64_t data);112/** Hash arbitrary bytes. */113CSipHasher& Write(std::span<const unsigned char> data);114/** Compute the 64-bit SipHash-2-4 of the data written so far. The object remains untouched. */115uint64_t Finalize() const;116};118/** A custom weaker variant of SipHash-1-3 without padding, and supporting "jumbo" inputs.119*120* Compared to the traditional SipHash-2-4, this incorporates 3 changes:121*122* - Use SipHash-1-3: This common variant reduces the number of rounds between input blocks from 2123* to 1, and the number of finalization rounds at the end from 4 to 3.124* It is a standard faster choice with weaker security guarantees. It is125* considered strong enough for use in hash tables and other applications with126* only weak security requirements, in particular when attackers cannot directly127* observe the hash function output, and cannot control k0 and k1.128*129* - Remove padding: Standard SipHash operates on byte-oriented inputs, which are converted into130* 8-byte blocks internally by adding a padding of 1-8 bytes to obtain a multiple131* of 8 bytes. In this variant, the input is a sequence of blocks instead, which132* are used without padding. This saves 1 round for inputs that are a multiple of133* 8 bytes already. The padding normally adds a commitment to the input's byte134* length, but since our input is block oriented, and there is one round per135* input, the function of that commitment is directly fulfilled by the number of136* rounds. The empty input is permitted; it yields the result of finalizing the137* initialization directly. Out of an abundance of caution the finalizing138* v2 ^= 0xff is changed to v2 ^= 0x6465646461706e75 ("unpadded" in LE64), to139* avoid collisions between standard SipHash-1-3 and this variant.140*141* - Jumbo blocks: We generalize the input to consist of a sequence of blocks which are each either142* exactly 8 bytes (normal blocks) or 32 bytes (jumbo blocks), and may be143* arbitrarily mixed. For hash-table use, cryptographic hash outputs must make up144* all but a small bounded number of retained jumbo blocks. Note that the block145* structure matters: hashing one jumbo block is not the same as hashing the same146* data split up into four normal blocks. Jumbo blocks are interpreted as 4 LE64 integers147* (d0,d1,d2,d3), and XOR'ed into the state before a round as148* (v0,v1,v2,v3) ^= (d1,d2,d3,d0), and XOR'ed into the state after a round as149* (v0,v1,v2,v3) ^= (d0,d1,d2,d3). This is a strict generalization of normal block150* processing, in the sense that if d1..d3=0, it is identical to processing a normal151* block d0 (a single LE64 integer). Of course, making d1..d3=0 should be impossible152* in the output of a cryptographic hash function. These jumbo blocks are acceptable153* because even though they may give the attacker more control within a single154* round, that control is limited by the cryptographic hash in between.155*156* Other components are unchanged: initialization constants, SipRound, and 64-bit output.157* This interface serves as an executable specification for fixed-width implementations.158* The Hash overloads optimize fixed-width inputs without modifying the accumulated state.159*/160class SipHasher13UJ161{162SipHashState m_state;164public:165/** Construct a SipHash-1-3-UJ calculator initialized with 128-bit key (k0, k1). */166SipHasher13UJ(uint64_t k0, uint64_t k1) noexcept : m_state{k0, k1} {}167/** Hash a normal 64-bit value. */168SipHasher13UJ& Write(uint64_t data) noexcept;169/** Hash a 256-bit value as a jumbo block. For hash-table use, non-hash inputs must remain few and bounded. */170SipHasher13UJ& WriteJumbo(const uint256& hash) noexcept;171/** Compute the 64-bit SipHash-1-3-UJ of the data written so far. The object remains untouched. */172uint64_t Finalize() const noexcept;174/** Hash a jumbo block after the data written so far and finalize without modifying the object. */175ALWAYS_INLINE uint64_t Hash(const uint256& hash) const noexcept176{177return m_state.Copy()178.Compress1Jumbo(hash)179.Finalize3U();180}182/**183* Hash a jumbo block followed by a normal block after the data written so far,184* and finalize without modifying the object.185*/186ALWAYS_INLINE uint64_t Hash(const uint256& hash, uint64_t extra) const noexcept187{188return m_state.Copy()189.Compress1Jumbo(hash)190.Compress1(extra)191.Finalize3U();192}193};195/**196* Optimized SipHash-2-4 implementation for uint256.197*198* This class caches the initial SipHash state (v0..v3) derived from (k0, k1)199* and implements a specialized hashing path for uint256 values, with or200* without an extra 32-bit word. The internal state is immutable, so201* PresaltedSipHasher instances can be reused for multiple hashes with the202* same key.203*/204class PresaltedSipHasher205{206const SipHashState m_state;208public:209explicit PresaltedSipHasher(uint64_t k0, uint64_t k1) noexcept : m_state{k0, k1} {}211/** Equivalent to CSipHasher(k0, k1).Write(val).Finalize(). */212uint64_t operator()(const uint256& val) const noexcept;214/**215* Equivalent to CSipHasher(k0, k1).Write(val).Write(extra).Finalize(),216* with `extra` encoded as 4 little-endian bytes.217*/218uint64_t operator()(const uint256& val, uint32_t extra) const noexcept;219};221#endif // BITCOIN_CRYPTO_SIPHASH_H