implement the FNV64a nullAEAD

It is not used yet.
This commit is contained in:
Marten Seemann
2017-09-03 21:17:07 +08:00
parent 03f16814ec
commit 15e9e3658a
4 changed files with 118 additions and 8 deletions

View File

@@ -9,23 +9,23 @@ import (
)
// nullAEAD handles not-yet encrypted packets
type nullAEAD struct {
type nullAEADFNV128a struct {
perspective protocol.Perspective
version protocol.VersionNumber
}
var _ AEAD = &nullAEAD{}
var _ AEAD = &nullAEADFNV128a{}
// NewNullAEAD creates a NullAEAD
func NewNullAEAD(p protocol.Perspective, v protocol.VersionNumber) AEAD {
return &nullAEAD{
return &nullAEADFNV128a{
perspective: p,
version: v,
}
}
// Open and verify the ciphertext
func (n *nullAEAD) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) {
func (n *nullAEADFNV128a) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) {
if len(src) < 12 {
return nil, errors.New("NullAEAD: ciphertext cannot be less than 12 bytes long")
}
@@ -52,7 +52,7 @@ func (n *nullAEAD) Open(dst, src []byte, packetNumber protocol.PacketNumber, ass
}
// Seal writes hash and ciphertext to the buffer
func (n *nullAEAD) Seal(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte {
func (n *nullAEADFNV128a) Seal(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte {
if cap(dst) < 12+len(src) {
dst = make([]byte, 12+len(src))
} else {

View File

@@ -6,7 +6,7 @@ import (
. "github.com/onsi/gomega"
)
var _ = Describe("Crypto/NullAEAD", func() {
var _ = Describe("NullAEAD using FNV128a", func() {
aad := []byte("All human beings are born free and equal in dignity and rights.")
plainText := []byte("They are endowed with reason and conscience and should act towards one another in a spirit of brotherhood.")
hash36 := []byte{0x98, 0x9b, 0x33, 0x3f, 0xe8, 0xde, 0x32, 0x5c, 0xa6, 0x7f, 0x9c, 0xf7}
@@ -16,12 +16,12 @@ var _ = Describe("Crypto/NullAEAD", func() {
aead := NewNullAEAD(protocol.PerspectiveServer, protocol.Version36)
res, err := aead.Open(nil, cipherText, 0, aad)
Expect(err).ToNot(HaveOccurred())
Expect(res).To(Equal([]byte("They are endowed with reason and conscience and should act towards one another in a spirit of brotherhood.")))
Expect(res).To(Equal(plainText))
})
It("seals", func() {
aead := NewNullAEAD(protocol.PerspectiveServer, protocol.Version36)
Expect(aead.Seal(nil, plainText, 0, aad)).To(Equal(append(hash36, []byte("They are endowed with reason and conscience and should act towards one another in a spirit of brotherhood.")...)))
Expect(aead.Seal(nil, plainText, 0, aad)).To(Equal(append(hash36, plainText...)))
})
It("rejects short ciphertexts", func() {

View File

@@ -0,0 +1,46 @@
package crypto
import (
"encoding/binary"
"errors"
"hash/fnv"
"github.com/lucas-clemente/quic-go/internal/protocol"
)
type nullAEADFNV64a struct{}
var _ AEAD = &nullAEADFNV64a{}
// Open and verify the ciphertext
func (n *nullAEADFNV64a) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) {
if len(src) < 8 {
return nil, errors.New("NullAEAD: ciphertext cannot be less than 8 bytes long")
}
data := src[:len(src)-8]
hash := fnv.New64a()
hash.Write(associatedData)
hash.Write(data)
if hash.Sum64() != binary.BigEndian.Uint64(src[len(src)-8:]) {
return nil, errors.New("NullAEAD: failed to authenticate received data")
}
return data, nil
}
// Seal writes hash and ciphertext to the buffer
func (n *nullAEADFNV64a) Seal(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte {
if cap(dst) < 8+len(src) {
dst = make([]byte, 8+len(src))
} else {
dst = dst[:8+len(src)]
}
hash := fnv.New64a()
hash.Write(associatedData)
hash.Write(src)
copy(dst, src)
binary.BigEndian.PutUint64(dst[len(src):], hash.Sum64())
return dst
}

View File

@@ -0,0 +1,64 @@
package crypto
import (
"encoding/binary"
"hash/fnv"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("NullAEAD using FNV128a", func() {
var hash64 []byte
var aead AEAD
aad := []byte("All human beings are born free and equal in dignity and rights.")
plainText := []byte("They are endowed with reason and conscience and should act towards one another in a spirit of brotherhood.")
BeforeEach(func() {
aead = &nullAEADFNV64a{}
hash := fnv.New64a()
hash.Write(aad)
hash.Write(plainText)
hash64 = make([]byte, 8)
binary.BigEndian.PutUint64(hash64, hash.Sum64())
})
It("opens", func() {
data, err := aead.Open(nil, append(plainText, hash64...), 0, aad)
Expect(err).ToNot(HaveOccurred())
Expect(data).To(Equal(plainText))
})
It("fails", func() {
_, err := aead.Open(nil, append(plainText, hash64...), 0, append(aad, []byte{0x42}...))
Expect(err).To(MatchError("NullAEAD: failed to authenticate received data"))
})
It("rejects short ciphertexts", func() {
_, err := aead.Open(nil, []byte{1, 2, 3, 4, 5, 6, 7}, 0, []byte{})
Expect(err).To(MatchError("NullAEAD: ciphertext cannot be less than 8 bytes long"))
})
It("opens empty messages", func() {
hash := fnv.New64a()
h := make([]byte, 8)
binary.BigEndian.PutUint64(h, hash.Sum64())
data, err := aead.Open(nil, h, 0, []byte{})
Expect(err).ToNot(HaveOccurred())
Expect(data).To(BeEmpty())
})
It("seals", func() {
Expect(aead.Seal(nil, plainText, 0, aad)).To(Equal(append(plainText, hash64...)))
})
It("seals in-place", func() {
buf := make([]byte, 6, 6+8)
copy(buf, []byte("foobar"))
res := aead.Seal(buf[0:0], buf, 0, nil)
// buf = buf[:8+6]
Expect(buf[:6]).To(Equal([]byte("foobar")))
// Expect(res[:6]).To(Equal([]byte("foobar")))
Expect(buf[0 : 6+8]).To(Equal(res))
})
})