aboutsummaryrefslogtreecommitdiff
path: root/test/functional/test_framework/siphash.py
diff options
context:
space:
mode:
authorSebastian Falbesoner <sebastian.falbesoner@gmail.com>2022-10-19 18:57:09 +0200
committerSebastian Falbesoner <sebastian.falbesoner@gmail.com>2022-10-20 01:32:48 +0200
commit25ee74dd11401ce2bfb0b24c4ce70578c5b99e51 (patch)
tree1cfcdc433d73b5679ef9db56bcefe0d1b071281c /test/functional/test_framework/siphash.py
parenta97791d9fb977cf2a0d19268253238b0fee173f6 (diff)
test: add SipHash implementation for generic data in Python
We will need this in the next commit to calculate ranged hashes of scriptPubKeys as defined in BIP158.
Diffstat (limited to 'test/functional/test_framework/siphash.py')
-rw-r--r--test/functional/test_framework/siphash.py56
1 files changed, 29 insertions, 27 deletions
diff --git a/test/functional/test_framework/siphash.py b/test/functional/test_framework/siphash.py
index 85836845d4..5ad245cf1b 100644
--- a/test/functional/test_framework/siphash.py
+++ b/test/functional/test_framework/siphash.py
@@ -1,15 +1,17 @@
#!/usr/bin/env python3
-# Copyright (c) 2016-2018 The Bitcoin Core developers
+# Copyright (c) 2016-2022 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-"""Specialized SipHash-2-4 implementations.
+"""SipHash-2-4 implementation.
-This implements SipHash-2-4 for 256-bit integers.
+This implements SipHash-2-4. For convenience, an interface taking 256-bit
+integers is provided in addition to the one accepting generic data.
"""
def rotl64(n, b):
return n >> (64 - b) | (n & ((1 << (64 - b)) - 1)) << b
+
def siphash_round(v0, v1, v2, v3):
v0 = (v0 + v1) & ((1 << 64) - 1)
v1 = rotl64(v1, 13)
@@ -27,37 +29,37 @@ def siphash_round(v0, v1, v2, v3):
v2 = rotl64(v2, 32)
return (v0, v1, v2, v3)
-def siphash256(k0, k1, h):
- n0 = h & ((1 << 64) - 1)
- n1 = (h >> 64) & ((1 << 64) - 1)
- n2 = (h >> 128) & ((1 << 64) - 1)
- n3 = (h >> 192) & ((1 << 64) - 1)
+
+def siphash(k0, k1, data):
+ assert(type(data) == bytes)
v0 = 0x736f6d6570736575 ^ k0
v1 = 0x646f72616e646f6d ^ k1
v2 = 0x6c7967656e657261 ^ k0
- v3 = 0x7465646279746573 ^ k1 ^ n0
- v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
- v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
- v0 ^= n0
- v3 ^= n1
- v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
- v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
- v0 ^= n1
- v3 ^= n2
+ v3 = 0x7465646279746573 ^ k1
+ c = 0
+ t = 0
+ for d in data:
+ t |= d << (8 * (c % 8))
+ c = (c + 1) & 0xff
+ if (c & 7) == 0:
+ v3 ^= t
+ v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
+ v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
+ v0 ^= t
+ t = 0
+ t = t | (c << 56)
+ v3 ^= t
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
- v0 ^= n2
- v3 ^= n3
- v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
- v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
- v0 ^= n3
- v3 ^= 0x2000000000000000
- v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
- v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
- v0 ^= 0x2000000000000000
- v2 ^= 0xFF
+ v0 ^= t
+ v2 ^= 0xff
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
return v0 ^ v1 ^ v2 ^ v3
+
+
+def siphash256(k0, k1, num):
+ assert(type(num) == int)
+ return siphash(k0, k1, num.to_bytes(32, 'little'))