siphash.h raw

   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
  73