I get the impression that the thing you are missing is that appending to a slice does not modify it. That is, `append(s, x...)` modifies neither the length, nor the content of `s`, you have to type `x = append(s, x...)`. `Seal` (and `Open`) work exactly the same. They append to the `out` parameter - and to enable you to get at the slice, they return it. The docs could be slightly more clear, by explicitly stating that they return the appended-to slice.0
On Mon, Oct 9, 2023 at 3:46 PM Dean Schulze <dean.w.schu...@gmail.com> wrote: > If the docs are correct, how do you append to nil? That's what the docs > say. Take a look at them. > > Your code example shows the first parameter to Seal() can be nil. So what > does that parameter do? How do you append to it? > > On Sunday, October 8, 2023 at 11:19:13 PM UTC-6 Axel Wagner wrote: > >> For what it's worth, here is an example that demonstrates a typical >> encryption/decryption roundtrip, perhaps more clearly: >> https://go.dev/play/p/ZZry8IgTJQ_- >> The `out` parameter can be used to make this more efficient by using >> pre-allocated buffers (depending on use case) and there are cases where you >> don't have to send the nonce, because you can derive them from common data, >> which is why both of these parameters are there. But in the most common >> usage, you'd do what this example does. >> >> The example code from the docs tries to be a little bit more efficient >> and packs the `Box` struct into a single byte, perhaps at the cost of >> understandability. >> >> On Mon, Oct 9, 2023 at 7:06 AM Axel Wagner <axel.wa...@googlemail.com> >> wrote: >> >>> oh I forgot to emphasize: I don't believe the output is *really* >>> `<encryptedMessage><hash>`. That is, I don't believe you can really treat >>> the first N bytes as the encrypted text and decrypt it (say, if you didn't >>> care about the authentication). It's just that you ultimately need to add >>> 16 bytes of extra information to carry that authentication tag, which is >>> why the box needs to be 16 bytes longer than the message. In reality, the >>> two are probably cleverly mixed - I'm not a cryptographer. >>> I just wanted to demonstrate where all the information ultimately goes. >>> >>> On Mon, Oct 9, 2023 at 7:03 AM Axel Wagner <axel.wa...@googlemail.com> >>> wrote: >>> >>>> I don't really understand your issue. You call >>>> encrypted := secretbox.Seal(nonce[:], []byte(s), &nonce, &secretKey) >>>> That means you pass `nonce[:]` as the `out` argument, `s` as the >>>> `message` argument, and the nonce and key and assign the result to >>>> `encrypted`. >>>> According to the docs of `secretbox`, `Seal` will `append` the >>>> encrypted message to `nonce[:]` and that encrypted message will be 16 bytes >>>> longer than the message, which is 11 bytes long. Appending 37 (16+11) bytes >>>> to a 24 byte nonce gives you 51 bytes, which is what you observe as the >>>> length of `encrypted`. >>>> The length of `nonce` doesn't change (it's an array, after all) - but >>>> passing `append` to a slice does not change the length of the slice, it >>>> just returns a new slice, so that seems expected. >>>> >>>> So, from what I can tell, the code does exactly what the docs say it >>>> should do. >>>> >>>> > In their example code the out parameter is nil. So what does it do? >>>> >>>> Appending to `nil` allocates a new slice. The point of still accepting >>>> an `out` parameter is that you can potentially prevent an allocation by >>>> passing in a slice with 0 length and extra capacity (which can then be >>>> allocated on the stack, or which is from a `sync.Pool`). If you don't need >>>> that, passing in `nil` seems fine. >>>> >>>> > The second argument is encrypted[len(nonce):] which includes the >>>> Overhead at the start of the []byte. Apparently that Overhead is important. >>>> >>>> Yes, the Overhead is important. It is used to authenticate the message. >>>> You can imagine the process of `Seal` as "encrypt the message and attach a >>>> hash". The hash is the Overhead. The process also needs a random `nonce`, >>>> that both the sender and the receiver need to know. That's why the example >>>> code sends it along with the message (it doesn't have to be secret). So >>>> that `Seal` call does, effectively (again, for illustrative purposes): >>>> encrypted := append(append(nonce, <encryptedMessage>), <hash>) >>>> As `nonce` is an array, this allocates a new backing array for the >>>> returned slice, which ends up filled with >>>> <nonce><encryptedMessage><hash> >>>> >>>> The `Open` call then retrieves the `nonce` from the first 24 bytes (by >>>> copying it into `decryptNonce`) and passes the `<encryptedMessage><hash>` >>>> slice as the `box` argument. Which decrypts the message, authenticates the >>>> hash and appends the decrypted message to `out` (which is `nil` in the >>>> example code). >>>> >>>> So, the docs are correct. And it seems to me, the code works as >>>> expected. I'm not sure where the misunderstanding is. >>>> >>> -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/3d7d75e5-d79a-4f81-978d-cb6feb7b12efn%40googlegroups.com > <https://groups.google.com/d/msgid/golang-nuts/3d7d75e5-d79a-4f81-978d-cb6feb7b12efn%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAEkBMfEZ4qmHh%3Ds4Bs6oDZDB3%2BYYrMSNeuVbcBpD-8%2BKH20Q3A%40mail.gmail.com.