1

In the package golang.org/x/crypto/nacl/sign the Sign function has both an out []byte argument and it returns a byte slice.

Reading the source code, i am struggling figuring out how to correctly use them, they are head and tail, though in following example, the resulting out byte slice is zero len.

Please see following example,


package main

import (
    "crypto/rand"
    "encoding/base64"
    "fmt"

    "golang.org/x/crypto/nacl/sign"
)

func main() {
    _, priv, err := sign.GenerateKey(rand.Reader)
    if err != nil {
        panic(err)
    }
    msg := []byte("hello world!")
    out := make([]byte, 0, len(msg)+sign.Overhead)
    ret := sign.Sign(out, msg, priv)

    fmt.Printf("len(msg): %v %s\n", len(msg), msg)
    fmt.Printf("len(out): %v %v\n", len(out), base64.StdEncoding.EncodeToString(out))
    fmt.Printf("len(ret): %v %v\n", len(ret), base64.StdEncoding.EncodeToString(ret))
}
// Output:
// len(msg): 12 hello world!
// len(out): 0 
// len(ret): 76 h+ZkFoWxuxOj7zV3tekiQz/z/yfuvXNUHxBjklo4iGBy7PfCEwvAiy3gi7GnuYGWB3SMxuxHtV5tNuUL1b3kAGhlbGxvIHdvcmxkIQ==

I dont understand why Sign returns both out and ret. I am unsure how long should be the out buffer to sign.Sign.

Conversely this examples works, though, is it correct ?

package main

import (
    "crypto/rand"
    "encoding/base64"
    "fmt"

    "golang.org/x/crypto/nacl/sign"
)

func main() {
    pub, priv, err := sign.GenerateKey(rand.Reader)
    if err != nil {
        panic(err)
    }
    msg := []byte("hello world!")
    out := make([]byte, 0, len(msg)+sign.Overhead)
    ret := sign.Sign(out, msg, priv)

    fmt.Printf("len(msg): %v %s\n", len(msg), msg)
    fmt.Printf("len(out): %v %v\n", len(out), base64.StdEncoding.EncodeToString(out))
    fmt.Printf("len(ret): %v %v\n", len(ret), base64.StdEncoding.EncodeToString(ret))

    openOut := make([]byte, 0, len(ret)-sign.Overhead)
    res, ok := sign.Open(openOut, ret, pub)
    if !ok {
        panic("failed to open signed message")
    }
    fmt.Printf("len(res): %v %s\n", len(res), res)
}
// Output:
// len(msg): 12 hello world!
// len(out): 0 
// len(ret): 76 h+ZkFoWxuxOj7zV3tekiQz/z/yfuvXNUHxBjklo4iGBy7PfCEwvAiy3gi7GnuYGWB3SMxuxHtV5tNuUL1b3kAGhlbGxvIHdvcmxkIQ==
// len(res): 12 hello world!

Looking forward for some explanations and correctness help.

  • 1
    It is dead simple. You can ignore out if you want. You probably could even pass in nil. The out parameter exists because a) it is very common to prepend the signed message with data and b) as an optimization where you can have a single out with enough cap and reuse that for signing lots of messages. If you need neither a nor b just use nil as the value for out. – Volker Sep 22 '20 at 13:03
  • OK thank you, i did not even thought i could pass in nil.... –  Sep 22 '20 at 13:08

0 Answers0