The
docs for secretbox.Seal say:
func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte
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.
Using their example code below I find that
the first argument out is unchanged
the return value is len(nonce) + Overhead longer than the input message, not Overhead longer
It's not clear what the first argument to Seal does. Nothing is appended to it and it is not changed, but it has to be there. Does it have to be the nonce[:]?
Likewise the docs for Open say
func Open(out, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool)
Open authenticates and decrypts a box produced by Seal and appends the message to out, which must not overlap box. The output will be Overhead bytes smaller than box.
In their example code the out parameter is nil. So what does it do? The second argument is encrypted[len(nonce):] which includes the Overhead at the start of the []byte. Apparently that Overhead is important.
The docs seem wildly wrong.
Here's code based on their example:
func main() {
secretKeyBytes, err := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574")
if err != nil {
panic(err)
}
var secretKey [32]byte
copy(secretKey[:], secretKeyBytes)
var nonce [24]byte
if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
panic(err)
}
nonceOrig := nonce
fmt.Printf("len(nonce): %v\n", len(nonce))
s := "hello world"
encrypted := secretbox.Seal(nonce[:], []byte(s), &nonce, &secretKey)
fmt.Printf("len(nonce): %v\n", len(nonce))
fmt.Printf("len(s): %v\n", len(s))
fmt.Printf("len(encrypted): %v\n", len(encrypted))
if !reflect.DeepEqual(nonceOrig, nonce) {
fmt.Println("nonce changed")
}
var decryptNonce [24]byte
copy(decryptNonce[:], encrypted[:24])
if !reflect.DeepEqual(decryptNonce, nonce) {
fmt.Println("decryptNonce, nonce differ")
}
decrypted, ok := secretbox.Open(nil, encrypted[24:], &decryptNonce, &secretKey)
if !ok {
panic("decryption error")
}
fmt.Println(string(decrypted))
encrypted2 := secretbox.Seal([]byte{}, []byte(s), &nonce, &secretKey)
copy(decryptNonce[:], encrypted2[:24])
decrypted2, ok := secretbox.Open(nil, encrypted2[24:], &decryptNonce, &secretKey)
if !ok {
fmt.Printf("decryption error 2: %v\n", decrypted2)
//panic("decryption error 2")
}
fmt.Printf("decrypted2: %v\n", decrypted2)
encrypted3 := secretbox.Seal(nil, []byte(s), &nonce, &secretKey)
decrypted3, ok := secretbox.Open(nil, encrypted3[24:], &nonce, &secretKey)
if !ok {
fmt.Printf("decryption error 3: %v\n", decrypted3)
}
fmt.Printf("decrypted3: %v\n", decrypted3)
}