move fnv128a implementation to separate package

This commit is contained in:
Lucas Clemente
2016-05-04 17:26:44 +02:00
parent 15c2c725a3
commit df2e6e32eb
3 changed files with 3 additions and 114 deletions

View File

@@ -1,88 +0,0 @@
package crypto
// Implements FNV-1 and FNV-1a, non-cryptographic hash functions
// created by Glenn Fowler, Landon Curt Noll, and Phong Vo.
// See https://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function.
// Write() algorithm taken and modified from github.com/romain-jacotin/quic
import "hash"
// Hash128 is the common interface implemented by all 128-bit hash functions.
type Hash128 interface {
hash.Hash
Sum128() (uint64, uint64)
}
type sum128a struct {
v0, v1, v2, v3 uint64
}
var _ Hash128 = &sum128a{}
// New128a returns a new 128-bit FNV-1a hash.Hash.
func New128a() Hash128 {
s := &sum128a{}
s.Reset()
return s
}
func (s *sum128a) Reset() {
s.v0 = 0x6295C58D
s.v1 = 0x62B82175
s.v2 = 0x07BB0142
s.v3 = 0x6C62272E
}
func (s *sum128a) Sum128() (uint64, uint64) {
return s.v3<<32 | s.v2, s.v1<<32 | s.v0
}
func (s *sum128a) Write(data []byte) (int, error) {
var t0, t1, t2, t3 uint64
const fnv128PrimeLow = 0x0000013B
const fnv128PrimeShift = 24
for _, v := range data {
// xor the bottom with the current octet
s.v0 ^= uint64(v)
// multiply by the 128 bit FNV magic prime mod 2^128
// fnv_prime = 309485009821345068724781371 (decimal)
// = 0x0000000001000000000000000000013B (hexadecimal)
// = 0x00000000 0x01000000 0x00000000 0x0000013B (in 4*32 words)
// = 0x0 1<<fnv128PrimeShift 0x0 fnv128PrimeLow
//
// fnv128PrimeLow = 0x0000013B
// fnv128PrimeShift = 24
// multiply by the lowest order digit base 2^32 and by the other non-zero digit
t0 = s.v0 * fnv128PrimeLow
t1 = s.v1 * fnv128PrimeLow
t2 = s.v2*fnv128PrimeLow + s.v0<<fnv128PrimeShift
t3 = s.v3*fnv128PrimeLow + s.v1<<fnv128PrimeShift
// propagate carries
t1 += (t0 >> 32)
t2 += (t1 >> 32)
t3 += (t2 >> 32)
s.v0 = t0 & 0xffffffff
s.v1 = t1 & 0xffffffff
s.v2 = t2 & 0xffffffff
s.v3 = t3 // & 0xffffffff
// Doing a s.v3 &= 0xffffffff is not really needed since it simply
// removes multiples of 2^128. We can discard these excess bits
// outside of the loop when writing the hash in Little Endian.
}
return len(data), nil
}
func (s *sum128a) Size() int { return 16 }
func (s *sum128a) BlockSize() int { return 1 }
func (s *sum128a) Sum(in []byte) []byte {
panic("FNV: not supported")
}

View File

@@ -1,24 +0,0 @@
package crypto
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("FNV", func() {
It("gives proper null hash", func() {
hash := New128a()
h, l := hash.Sum128()
Expect(l).To(Equal(uint64(0x62b821756295c58d)))
Expect(h).To(Equal(uint64(0x6c62272e07bb0142)))
})
It("calculates hash", func() {
hash := New128a()
_, err := hash.Write([]byte("foobar"))
Expect(err).ToNot(HaveOccurred())
h, l := hash.Sum128()
Expect(l).To(Equal(uint64(0x6f0d3597ba446f18)))
Expect(h).To(Equal(uint64(0x343e1662793c64bf)))
})
})

View File

@@ -4,6 +4,7 @@ import (
"encoding/binary"
"errors"
"github.com/lucas-clemente/fnv128a"
"github.com/lucas-clemente/quic-go/protocol"
)
@@ -18,7 +19,7 @@ func (*NullAEAD) Open(packetNumber protocol.PacketNumber, associatedData []byte,
return nil, errors.New("NullAEAD: ciphertext cannot be less than 12 bytes long")
}
hash := New128a()
hash := fnv128a.New()
hash.Write(associatedData)
hash.Write(ciphertext[12:])
testHigh, testLow := hash.Sum128()
@@ -36,7 +37,7 @@ func (*NullAEAD) Open(packetNumber protocol.PacketNumber, associatedData []byte,
func (*NullAEAD) Seal(packetNumber protocol.PacketNumber, associatedData []byte, plaintext []byte) []byte {
res := make([]byte, 12+len(plaintext))
hash := New128a()
hash := fnv128a.New()
hash.Write(associatedData)
hash.Write(plaintext)
high, low := hash.Sum128()