Bitcoin Core  31.0.0
P2P Digital Currency
siphash.cpp
Go to the documentation of this file.
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 #include <crypto/siphash.h>
6 
7 #include <uint256.h>
8 
9 #include <bit>
10 #include <cassert>
11 #include <span>
12 
13 #define SIPROUND do { \
14  v0 += v1; v1 = std::rotl(v1, 13); v1 ^= v0; \
15  v0 = std::rotl(v0, 32); \
16  v2 += v3; v3 = std::rotl(v3, 16); v3 ^= v2; \
17  v0 += v3; v3 = std::rotl(v3, 21); v3 ^= v0; \
18  v2 += v1; v1 = std::rotl(v1, 17); v1 ^= v2; \
19  v2 = std::rotl(v2, 32); \
20 } while (0)
21 
22 CSipHasher::CSipHasher(uint64_t k0, uint64_t k1) : m_state{k0, k1} {}
23 
25 {
26  uint64_t v0 = m_state.v[0], v1 = m_state.v[1], v2 = m_state.v[2], v3 = m_state.v[3];
27 
28  assert(m_count % 8 == 0);
29 
30  v3 ^= data;
31  SIPROUND;
32  SIPROUND;
33  v0 ^= data;
34 
35  m_state.v[0] = v0;
36  m_state.v[1] = v1;
37  m_state.v[2] = v2;
38  m_state.v[3] = v3;
39 
40  m_count += 8;
41  return *this;
42 }
43 
44 CSipHasher& CSipHasher::Write(std::span<const unsigned char> data)
45 {
46  uint64_t v0 = m_state.v[0], v1 = m_state.v[1], v2 = m_state.v[2], v3 = m_state.v[3];
47  uint64_t t = m_tmp;
48  uint8_t c = m_count;
49 
50  while (data.size() > 0) {
51  t |= uint64_t{data.front()} << (8 * (c % 8));
52  c++;
53  if ((c & 7) == 0) {
54  v3 ^= t;
55  SIPROUND;
56  SIPROUND;
57  v0 ^= t;
58  t = 0;
59  }
60  data = data.subspan(1);
61  }
62 
63  m_state.v[0] = v0;
64  m_state.v[1] = v1;
65  m_state.v[2] = v2;
66  m_state.v[3] = v3;
67  m_count = c;
68  m_tmp = t;
69 
70  return *this;
71 }
72 
73 uint64_t CSipHasher::Finalize() const
74 {
75  uint64_t v0 = m_state.v[0], v1 = m_state.v[1], v2 = m_state.v[2], v3 = m_state.v[3];
76 
77  uint64_t t = m_tmp | (((uint64_t)m_count) << 56);
78 
79  v3 ^= t;
80  SIPROUND;
81  SIPROUND;
82  v0 ^= t;
83  v2 ^= 0xFF;
84  SIPROUND;
85  SIPROUND;
86  SIPROUND;
87  SIPROUND;
88  return v0 ^ v1 ^ v2 ^ v3;
89 }
90 
91 uint64_t PresaltedSipHasher::operator()(const uint256& val) const noexcept
92 {
93  uint64_t v0 = m_state.v[0], v1 = m_state.v[1], v2 = m_state.v[2], v3 = m_state.v[3];
94  uint64_t d = val.GetUint64(0);
95  v3 ^= d;
96 
97  SIPROUND;
98  SIPROUND;
99  v0 ^= d;
100  d = val.GetUint64(1);
101  v3 ^= d;
102  SIPROUND;
103  SIPROUND;
104  v0 ^= d;
105  d = val.GetUint64(2);
106  v3 ^= d;
107  SIPROUND;
108  SIPROUND;
109  v0 ^= d;
110  d = val.GetUint64(3);
111  v3 ^= d;
112  SIPROUND;
113  SIPROUND;
114  v0 ^= d;
115  v3 ^= (uint64_t{4}) << 59;
116  SIPROUND;
117  SIPROUND;
118  v0 ^= (uint64_t{4}) << 59;
119  v2 ^= 0xFF;
120  SIPROUND;
121  SIPROUND;
122  SIPROUND;
123  SIPROUND;
124  return v0 ^ v1 ^ v2 ^ v3;
125 }
126 
128 uint64_t PresaltedSipHasher::operator()(const uint256& val, uint32_t extra) const noexcept
129 {
130  uint64_t v0 = m_state.v[0], v1 = m_state.v[1], v2 = m_state.v[2], v3 = m_state.v[3];
131  uint64_t d = val.GetUint64(0);
132  v3 ^= d;
133  SIPROUND;
134  SIPROUND;
135  v0 ^= d;
136  d = val.GetUint64(1);
137  v3 ^= d;
138  SIPROUND;
139  SIPROUND;
140  v0 ^= d;
141  d = val.GetUint64(2);
142  v3 ^= d;
143  SIPROUND;
144  SIPROUND;
145  v0 ^= d;
146  d = val.GetUint64(3);
147  v3 ^= d;
148  SIPROUND;
149  SIPROUND;
150  v0 ^= d;
151  d = ((uint64_t{36}) << 56) | extra;
152  v3 ^= d;
153  SIPROUND;
154  SIPROUND;
155  v0 ^= d;
156  v2 ^= 0xFF;
157  SIPROUND;
158  SIPROUND;
159  SIPROUND;
160  SIPROUND;
161  return v0 ^ v1 ^ v2 ^ v3;
162 }
assert(!tx.IsCoinBase())
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data.
Definition: siphash.cpp:24
std::array< uint64_t, 4 > v
Definition: siphash.h:22
CSipHasher(uint64_t k0, uint64_t k1)
Construct a SipHash calculator initialized with 128-bit key (k0, k1).
Definition: siphash.cpp:22
SipHashState m_state
Definition: siphash.h:28
#define SIPROUND
Definition: siphash.cpp:13
uint64_t m_tmp
Definition: siphash.h:29
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
Definition: siphash.cpp:73
uint64_t operator()(const uint256 &val) const noexcept
Equivalent to CSipHasher(k0, k1).Write(val).Finalize().
Definition: siphash.cpp:91
256-bit opaque blob.
Definition: uint256.h:195
General SipHash-2-4 implementation.
Definition: siphash.h:26
uint8_t m_count
Only the low 8 bits of the input size matter.
Definition: siphash.h:30