diff --git a/go.mod b/go.mod index 27cac9f48..1ba834aa3 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,6 @@ require ( github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect github.com/cenkalti/backoff/v4 v4.1.1 github.com/cespare/xxhash/v2 v2.1.1 - github.com/dchest/siphash v1.2.2 github.com/dnaeon/go-vcr v1.2.0 // indirect github.com/elithrar/simple-scrypt v1.3.0 github.com/go-ole/go-ole v1.2.5 diff --git a/go.sum b/go.sum index d9dc28725..0e5ba267a 100644 --- a/go.sum +++ b/go.sum @@ -89,8 +89,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dchest/siphash v1.2.2 h1:9DFz8tQwl9pTVt5iok/9zKyzA1Q6bRGiF3HPiEEVr9I= -github.com/dchest/siphash v1.2.2/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= diff --git a/internal/repository/indexmap.go b/internal/repository/indexmap.go index 8182d055e..f713a3304 100644 --- a/internal/repository/indexmap.go +++ b/internal/repository/indexmap.go @@ -1,12 +1,9 @@ package repository import ( - "crypto/rand" - "encoding/binary" + "hash/maphash" "github.com/restic/restic/internal/restic" - - "github.com/dchest/siphash" ) // An indexMap is a chained hash table that maps blob IDs to indexEntries. @@ -23,7 +20,7 @@ type indexMap struct { buckets []*indexEntry numentries uint - key0, key1 uint64 // Key for hash randomization. + mh maphash.Hash free *indexEntry // Free list. } @@ -113,25 +110,20 @@ func (m *indexMap) grow() { } func (m *indexMap) hash(id restic.ID) uint { - // We use siphash with a randomly generated 128-bit key, to prevent - // backups of specially crafted inputs from degrading performance. + // We use maphash to prevent backups of specially crafted inputs + // from degrading performance. // While SHA-256 should be collision-resistant, for hash table indices // we use only a few bits of it and finding collisions for those is // much easier than breaking the whole algorithm. - h := uint(siphash.Hash(m.key0, m.key1, id[:])) + m.mh.Reset() + _, _ = m.mh.Write(id[:]) + h := uint(m.mh.Sum64()) return h & uint(len(m.buckets)-1) } func (m *indexMap) init() { const initialBuckets = 64 m.buckets = make([]*indexEntry, initialBuckets) - - var buf [16]byte - if _, err := rand.Read(buf[:]); err != nil { - panic(err) // Very little we can do here. - } - m.key0 = binary.LittleEndian.Uint64(buf[:8]) - m.key1 = binary.LittleEndian.Uint64(buf[8:]) } func (m *indexMap) len() uint { return m.numentries } diff --git a/internal/repository/indexmap_test.go b/internal/repository/indexmap_test.go index 0d435387d..d803bf3c5 100644 --- a/internal/repository/indexmap_test.go +++ b/internal/repository/indexmap_test.go @@ -107,32 +107,6 @@ func TestIndexMapForeachWithID(t *testing.T) { } } -func TestIndexMapHash(t *testing.T) { - t.Parallel() - - var m1, m2 indexMap - - id := restic.NewRandomID() - // Add to both maps to initialize them. - m1.add(id, 0, 0, 0) - m2.add(id, 0, 0, 0) - - h1 := m1.hash(id) - h2 := m2.hash(id) - - rtest.Equals(t, len(m1.buckets), len(m2.buckets)) // just to be sure - - if h1 == h2 { - // The probability of the zero key should be 2^(-128). - if m1.key0 == 0 && m1.key1 == 0 { - t.Error("siphash key not set for m1") - } - if m2.key0 == 0 && m2.key1 == 0 { - t.Error("siphash key not set for m2") - } - } -} - func BenchmarkIndexMapHash(b *testing.B) { var m indexMap m.add(restic.ID{}, 0, 0, 0) // Trigger lazy initialization.