/ src / crypto / siphash.h
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