Add msgpack wire protocol with halfsiphash checksums

This commit is contained in:
Ian Gulliver
2026-04-03 16:59:11 +09:00
parent b076cce34a
commit db6f005bef
33 changed files with 5928 additions and 3 deletions

View File

@@ -0,0 +1,74 @@
package halfsiphash
import "encoding/binary"
func rotl(x uint32, b uint) uint32 {
return (x << b) | (x >> (32 - b))
}
func sipround(v0, v1, v2, v3 *uint32) {
*v0 += *v1
*v1 = rotl(*v1, 5)
*v1 ^= *v0
*v0 = rotl(*v0, 16)
*v2 += *v3
*v3 = rotl(*v3, 8)
*v3 ^= *v2
*v0 += *v3
*v3 = rotl(*v3, 7)
*v3 ^= *v0
*v2 += *v1
*v1 = rotl(*v1, 13)
*v1 ^= *v2
*v2 = rotl(*v2, 16)
}
// Sum32 computes HalfSipHash-2-4 with an 8-byte key and returns a 4-byte hash.
func Sum32(data []byte, key [8]byte) uint32 {
k0 := binary.LittleEndian.Uint32(key[0:4])
k1 := binary.LittleEndian.Uint32(key[4:8])
v0 := uint32(0) ^ k0
v1 := uint32(0) ^ k1
v2 := uint32(0x6c796765) ^ k0
v3 := uint32(0x74656462) ^ k1
// Process full 4-byte blocks.
nblocks := len(data) / 4
for i := 0; i < nblocks; i++ {
m := binary.LittleEndian.Uint32(data[i*4:])
v3 ^= m
for j := 0; j < 2; j++ {
sipround(&v0, &v1, &v2, &v3)
}
v0 ^= m
}
// Process remaining bytes.
b := uint32(len(data)) << 24
tail := data[nblocks*4:]
switch len(tail) {
case 3:
b |= uint32(tail[2]) << 16
fallthrough
case 2:
b |= uint32(tail[1]) << 8
fallthrough
case 1:
b |= uint32(tail[0])
}
v3 ^= b
for i := 0; i < 2; i++ {
sipround(&v0, &v1, &v2, &v3)
}
v0 ^= b
v2 ^= 0xff
for i := 0; i < 4; i++ {
sipround(&v0, &v1, &v2, &v3)
}
return v1 ^ v3
}

View File

@@ -0,0 +1,31 @@
package halfsiphash
import "testing"
// Test vectors from the reference implementation.
// Key: 00 01 02 03 04 05 06 07
// Input: sequence 00, 00 01, 00 01 02, ...
var vectors32 = []uint32{
0x5b9f35a9,
0xb85a4727,
0x03a662fa,
0x04e7fe8a,
0x89466e2a,
0x69b6fac5,
0x23fc6358,
0xc563cf8b,
}
func TestSum32(t *testing.T) {
key := [8]byte{0, 1, 2, 3, 4, 5, 6, 7}
for i, want := range vectors32 {
data := make([]byte, i)
for j := range data {
data[j] = byte(j)
}
got := Sum32(data, key)
if got != want {
t.Errorf("Sum32(len=%d) = %08x, want %08x", i, got, want)
}
}
}