FAQ
I'm working on an implementation of CurveCP (http://curvecp.org) in Go,
using the box/secretbox operations that agl graciously wrote.

However, I'm puzzled as to why the APIs (
http://go.pkgdoc.org/code.google.com/p/go.crypto/nacl/box and
http://go.pkgdoc.org/code.google.com/p/go.crypto/nacl/secretbox) use
pointers to raw arrays, rather than slices, for keys and nonces. It makes
using the API a little clunky, as I have to allocate a bunch of raw arrays
and copy keys around, when I could just point at the key in the received
packets directly if I could pass in a slice.

And, in general, it's so rare to see raw arrays that the API feels
surprising. Is there a reason for not using slices, besides being able to
avoid an if len(k) != 32 { panic(...) } ?

- Dave

--

Search Discussions

  • Adam Langley at Nov 25, 2012 at 12:37 am

    On Sat, Nov 24, 2012 at 6:51 PM, David Anderson wrote:
    I'm working on an implementation of CurveCP (http://curvecp.org) in Go,
    using the box/secretbox operations that agl graciously wrote.

    However, I'm puzzled as to why the APIs
    (http://go.pkgdoc.org/code.google.com/p/go.crypto/nacl/box and
    http://go.pkgdoc.org/code.google.com/p/go.crypto/nacl/secretbox) use
    pointers to raw arrays, rather than slices, for keys and nonces. It makes
    using the API a little clunky, as I have to allocate a bunch of raw arrays
    and copy keys around, when I could just point at the key in the received
    packets directly if I could pass in a slice.

    And, in general, it's so rare to see raw arrays that the API feels
    surprising. Is there a reason for not using slices, besides being able to
    avoid an if len(k) != 32 { panic(...) } ?
    Avoiding lots of "if len(k) != x { panic" is a fair bit of it, as well
    as documenting the sizes of things in the type, rather than having to
    read the comments and also preventing typos where, say, the nonce and
    key are interchanged. (For example, the fact that the nonce is 24
    bytes for (secret)box is significant because the Salsa20 nonce is
    usually 8 bytes and hints that something more complex is happening
    under the covers.)

    Often a new type would be used for these things but crypto is
    something that generally happens at the edge of a process, where type
    information is lost in serialisation. So that doesn't work as well as
    it might otherwise.

    (And one of my Go nits is that casting from a slice to an array
    pointer doesn't work.)

    It's quite possible that I was an idiot and should just have used slices.


    Cheers

    AGL

    --
  • David Anderson at Nov 25, 2012 at 12:49 am

    On Sat, Nov 24, 2012 at 4:37 PM, Adam Langley wrote:
    On Sat, Nov 24, 2012 at 6:51 PM, David Anderson wrote:
    I'm working on an implementation of CurveCP (http://curvecp.org) in Go,
    using the box/secretbox operations that agl graciously wrote.

    However, I'm puzzled as to why the APIs
    (http://go.pkgdoc.org/code.google.com/p/go.crypto/nacl/box and
    http://go.pkgdoc.org/code.google.com/p/go.crypto/nacl/secretbox) use
    pointers to raw arrays, rather than slices, for keys and nonces. It makes
    using the API a little clunky, as I have to allocate a bunch of raw arrays
    and copy keys around, when I could just point at the key in the received
    packets directly if I could pass in a slice.

    And, in general, it's so rare to see raw arrays that the API feels
    surprising. Is there a reason for not using slices, besides being able to
    avoid an if len(k) != 32 { panic(...) } ?
    Avoiding lots of "if len(k) != x { panic" is a fair bit of it, as well
    as documenting the sizes of things in the type, rather than having to
    read the comments and also preventing typos where, say, the nonce and
    key are interchanged. (For example, the fact that the nonce is 24
    bytes for (secret)box is significant because the Salsa20 nonce is
    usually 8 bytes and hints that something more complex is happening
    under the covers.)
    Often a new type would be used for these things but crypto is
    something that generally happens at the edge of a process, where type
    information is lost in serialisation. So that doesn't work as well as
    it might otherwise.

    (And one of my Go nits is that casting from a slice to an array
    pointer doesn't work.)

    It's quite possible that I was an idiot and should just have used slices.
    Makes sense, I guess. As you say, with the inability to go back from slice
    to array, it uglifies things a little bit. That said, after remembering
    that you can stack-declare arrays, the code ends up being nice enough. I
    end up copying the nonces and keys a few more times than strictly
    necessary, but whatever.

    Thanks!
    - Dave


    Cheers

    AGL
    --
  • Dmitry Chestnykh at Nov 25, 2012 at 1:02 am
    I'd add that the speed difference between arrays and slices is currently
    significant.
    My first versions of Salsa20 and Poly1305 used slices for everything, and
    when I switched
    them to arrays, this eliminated a huge amount of bounds checking,
    increasing performance.
    (So even your copying of key won't have significant impact).

    Here's a piece of relevant git log:

    Date: Sat Jun 2 23:36:30 2012 +0200

    salsa20: use pointers to arrays instead of byte slices.

    Before:

    BenchmarkXOR1K 200000 11092 ns/op 92.31 MB/s
    BenchmarkXOR8K 200000 88136 ns/op 92.95 MB/s

    After.

    BenchmarkXOR1K 200000 9216 ns/op 111.11 MB/s
    BenchmarkXOR8K 50000 73743 ns/op 111.09 MB/s

    It's also easier to control allocations with arrays.

    But compile-time checking, as Adam mentioned, is still the most important
    factor for me.

    -Dmitry
    On Sunday, November 25, 2012 1:37:53 AM UTC+1, agl wrote:
    On Sat, Nov 24, 2012 at 6:51 PM, David Anderson wrote:
    I'm working on an implementation of CurveCP (http://curvecp.org) in Go,
    using the box/secretbox operations that agl graciously wrote.

    However, I'm puzzled as to why the APIs
    (http://go.pkgdoc.org/code.google.com/p/go.crypto/nacl/box and
    http://go.pkgdoc.org/code.google.com/p/go.crypto/nacl/secretbox) use
    pointers to raw arrays, rather than slices, for keys and nonces. It makes
    using the API a little clunky, as I have to allocate a bunch of raw arrays
    and copy keys around, when I could just point at the key in the received
    packets directly if I could pass in a slice.

    And, in general, it's so rare to see raw arrays that the API feels
    surprising. Is there a reason for not using slices, besides being able to
    avoid an if len(k) != 32 { panic(...) } ?
    Avoiding lots of "if len(k) != x { panic" is a fair bit of it, as well
    as documenting the sizes of things in the type, rather than having to
    read the comments and also preventing typos where, say, the nonce and
    key are interchanged. (For example, the fact that the nonce is 24
    bytes for (secret)box is significant because the Salsa20 nonce is
    usually 8 bytes and hints that something more complex is happening
    under the covers.)

    Often a new type would be used for these things but crypto is
    something that generally happens at the edge of a process, where type
    information is lost in serialisation. So that doesn't work as well as
    it might otherwise.

    (And one of my Go nits is that casting from a slice to an array
    pointer doesn't work.)

    It's quite possible that I was an idiot and should just have used slices.


    Cheers

    AGL
    --

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedNov 24, '12 at 11:52p
activeNov 25, '12 at 1:02a
posts4
users3
websitegolang.org

People

Translate

site design / logo © 2022 Grokbase