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:
+19
-25
@@ -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
|
||||
}
|
||||
|
||||
@@ -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.")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user