diff --git a/src/crypto/siphash.cpp b/src/crypto/siphash.cpp index 27b82093c..a29274034 100644 --- a/src/crypto/siphash.cpp +++ b/src/crypto/siphash.cpp @@ -1,177 +1,177 @@ // Copyright (c) 2016-2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b)))) #define SIPROUND \ do { \ v0 += v1; \ v1 = ROTL(v1, 13); \ v1 ^= v0; \ v0 = ROTL(v0, 32); \ v2 += v3; \ v3 = ROTL(v3, 16); \ v3 ^= v2; \ v0 += v3; \ v3 = ROTL(v3, 21); \ v3 ^= v0; \ v2 += v1; \ v1 = ROTL(v1, 17); \ v1 ^= v2; \ v2 = ROTL(v2, 32); \ } while (0) CSipHasher::CSipHasher(uint64_t k0, uint64_t k1) { v[0] = 0x736f6d6570736575ULL ^ k0; v[1] = 0x646f72616e646f6dULL ^ k1; v[2] = 0x6c7967656e657261ULL ^ k0; v[3] = 0x7465646279746573ULL ^ k1; count = 0; tmp = 0; } CSipHasher &CSipHasher::Write(uint64_t data) { uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3]; assert(count % 8 == 0); v3 ^= data; SIPROUND; SIPROUND; v0 ^= data; v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3; count += 8; return *this; } CSipHasher &CSipHasher::Write(const uint8_t *data, size_t size) { uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3]; uint64_t t = tmp; - int c = count; + uint8_t c = count; while (size--) { t |= uint64_t(*(data++)) << (8 * (c % 8)); c++; if ((c & 7) == 0) { v3 ^= t; SIPROUND; SIPROUND; v0 ^= t; t = 0; } } v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3; count = c; tmp = t; return *this; } uint64_t CSipHasher::Finalize() const { uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3]; uint64_t t = tmp | (uint64_t(count) << 56); v3 ^= t; SIPROUND; SIPROUND; v0 ^= t; v2 ^= 0xFF; SIPROUND; SIPROUND; SIPROUND; SIPROUND; return v0 ^ v1 ^ v2 ^ v3; } uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256 &val) { /* Specialized implementation for efficiency */ uint64_t d = val.GetUint64(0); uint64_t v0 = 0x736f6d6570736575ULL ^ k0; uint64_t v1 = 0x646f72616e646f6dULL ^ k1; uint64_t v2 = 0x6c7967656e657261ULL ^ k0; uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ d; SIPROUND; SIPROUND; v0 ^= d; d = val.GetUint64(1); v3 ^= d; SIPROUND; SIPROUND; v0 ^= d; d = val.GetUint64(2); v3 ^= d; SIPROUND; SIPROUND; v0 ^= d; d = val.GetUint64(3); v3 ^= d; SIPROUND; SIPROUND; v0 ^= d; v3 ^= uint64_t(4) << 59; SIPROUND; SIPROUND; v0 ^= uint64_t(4) << 59; v2 ^= 0xFF; SIPROUND; SIPROUND; SIPROUND; SIPROUND; return v0 ^ v1 ^ v2 ^ v3; } uint64_t SipHashUint256Extra(uint64_t k0, uint64_t k1, const uint256 &val, uint32_t extra) { /* Specialized implementation for efficiency */ uint64_t d = val.GetUint64(0); uint64_t v0 = 0x736f6d6570736575ULL ^ k0; uint64_t v1 = 0x646f72616e646f6dULL ^ k1; uint64_t v2 = 0x6c7967656e657261ULL ^ k0; uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ d; SIPROUND; SIPROUND; v0 ^= d; d = val.GetUint64(1); v3 ^= d; SIPROUND; SIPROUND; v0 ^= d; d = val.GetUint64(2); v3 ^= d; SIPROUND; SIPROUND; v0 ^= d; d = val.GetUint64(3); v3 ^= d; SIPROUND; SIPROUND; v0 ^= d; d = (uint64_t(36) << 56) | extra; v3 ^= d; SIPROUND; SIPROUND; v0 ^= d; v2 ^= 0xFF; SIPROUND; SIPROUND; SIPROUND; SIPROUND; return v0 ^ v1 ^ v2 ^ v3; } diff --git a/src/crypto/siphash.h b/src/crypto/siphash.h index 597ddc88f..38f11a7de 100644 --- a/src/crypto/siphash.h +++ b/src/crypto/siphash.h @@ -1,50 +1,51 @@ // Copyright (c) 2016-2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_CRYPTO_SIPHASH_H #define BITCOIN_CRYPTO_SIPHASH_H #include #include /** SipHash-2-4 */ class CSipHasher { private: uint64_t v[4]; uint64_t tmp; - int count; + // Only the low 8 bits of the input size matter. + uint8_t count; public: /** Construct a SipHash calculator initialized with 128-bit key (k0, k1) */ CSipHasher(uint64_t k0, uint64_t k1); /** * Hash a 64-bit integer worth of data. * It is treated as if this was the little-endian interpretation of 8 bytes. * This function can only be used when a multiple of 8 bytes have been * written so far. */ CSipHasher &Write(uint64_t data); /** Hash arbitrary bytes. */ CSipHasher &Write(const uint8_t *data, size_t size); /** Compute the 64-bit SipHash-2-4 of the data written so far. The object * remains untouched. */ uint64_t Finalize() const; }; /** Optimized SipHash-2-4 implementation for uint256. * * It is identical to: * SipHasher(k0, k1) * .Write(val.GetUint64(0)) * .Write(val.GetUint64(1)) * .Write(val.GetUint64(2)) * .Write(val.GetUint64(3)) * .Finalize() */ uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256 &val); uint64_t SipHashUint256Extra(uint64_t k0, uint64_t k1, const uint256 &val, uint32_t extra); #endif // BITCOIN_CRYPTO_SIPHASH_H