go.crypto/nacl/secretbox: fix append behaviour.

secretbox is supposed to append to the given slice, like hash.Sum() and
append(). However, I had a complete brain-fart: I've really no idea what
I was thinking of at the time.

R=golang-dev, sfrithjof, rsc
CC=agl, golang-dev
https://golang.org/cl/10099043
This commit is contained in:
Adam Langley
2013-06-10 18:03:26 -04:00
parent aa0f5b4081
commit c2ba5865a8
2 changed files with 37 additions and 25 deletions
+19 -25
View File
@@ -37,6 +37,21 @@ func setup(subKey *[32]byte, counter *[16]byte, nonce *[24]byte, key *[32]byte)
copy(counter[:], nonce[16:])
}
// sliceForAppend takes a slice and a requested number of bytes. It returns a
// slice with the contents of the given slice followed by that many bytes and a
// second slice that aliases into it and contains only the extra bytes. If the
// original slice has sufficient capacity then no allocation is performed.
func sliceForAppend(in []byte, n int) (head, tail []byte) {
if total := len(in) + n; cap(in) >= total {
head = in[:total]
} else {
head = make([]byte, total)
copy(head, in)
}
tail = head[len(in):]
return
}
// Seal appends an encrypted and authenticated copy of message to out, which
// must not overlap message. The key and nonce pair must be unique for each
// distinct message and the output will be Overhead bytes longer than message.
@@ -54,17 +69,7 @@ func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte {
var poly1305Key [32]byte
copy(poly1305Key[:], firstBlock[:])
out = out[len(out):]
outLen := len(message) + poly1305.TagSize
if cap(out) >= outLen {
out = out[:outLen]
} else if out == nil {
out = make([]byte, outLen)
} else {
for i := 0; i < outLen; i++ {
out = append(out, 0)
}
}
ret, out := sliceForAppend(out, len(message)+poly1305.TagSize)
// We XOR up to 32 bytes of message with the keystream generated from
// the first block.
@@ -90,7 +95,7 @@ func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte {
poly1305.Sum(&tag, ciphertext, &poly1305Key)
copy(tagOut, tag[:])
return tagOut
return ret
}
// Open authenticates and decrypts a box produced by Seal and appends the
@@ -120,17 +125,7 @@ func Open(out []byte, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool)
return nil, false
}
out = out[len(out):]
outLen := len(box) - Overhead
if cap(out) >= outLen {
out = out[:outLen]
} else if out == nil {
out = make([]byte, outLen)
} else {
for i := 0; i < outLen; i++ {
out = append(out, 0)
}
}
ret, out := sliceForAppend(out, len(box)-Overhead)
// We XOR up to 32 bytes of box with the keystream generated from
// the first block.
@@ -144,12 +139,11 @@ func Open(out []byte, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool)
}
box = box[len(firstMessageBlock):]
plaintext := out
out = out[len(firstMessageBlock):]
// Now decrypt the rest.
counter[8] = 1
salsa.XORKeyStream(out, box, &counter, &subKey)
return plaintext, true
return ret, true
}
+18
View File
@@ -71,3 +71,21 @@ func TestSecretBox(t *testing.T) {
t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected)
}
}
func TestAppend(t *testing.T) {
var key [32]byte
var nonce [24]byte
var message [8]byte
out := make([]byte, 4)
box := Seal(out, message[:], &nonce, &key)
if !bytes.Equal(box[:4], out[:4]) {
t.Fatalf("Seal didn't correctly append")
}
out = make([]byte, 4, 100)
box = Seal(out, message[:], &nonce, &key)
if !bytes.Equal(box[:4], out[:4]) {
t.Fatalf("Seal didn't correctly append with sufficient capacity.")
}
}