tka,types/key: implement direct node-key signatures

Signed-off-by: Tom DNetto <tom@tailscale.com>
This commit is contained in:
Tom DNetto
2022-07-21 14:45:43 -07:00
committed by Tom
parent c13fab2a67
commit 8cfd775885
5 changed files with 191 additions and 0 deletions

View File

@@ -10,6 +10,7 @@ import (
"crypto/subtle"
"encoding/hex"
"errors"
"fmt"
"go4.org/mem"
"golang.org/x/crypto/curve25519"
@@ -34,6 +35,10 @@ const (
// changed.
nodePublicHexPrefix = "nodekey:"
// nodePublicBinaryPrefix is the prefix used to identify a
// binary-encoded node public key.
nodePublicBinaryPrefix = "np"
// NodePublicRawLen is the length in bytes of a NodePublic, when
// serialized with AppendTo, Raw32 or WriteRawWithoutAllocating.
NodePublicRawLen = 32
@@ -297,6 +302,28 @@ func (k *NodePublic) UnmarshalText(b []byte) error {
return parseHex(k.k[:], mem.B(b), mem.S(nodePublicHexPrefix))
}
// MarshalBinary implements encoding.BinaryMarshaler.
func (k NodePublic) MarshalBinary() (data []byte, err error) {
b := make([]byte, len(nodePublicBinaryPrefix)+NodePublicRawLen)
copy(b[:len(nodePublicBinaryPrefix)], nodePublicBinaryPrefix)
copy(b[len(nodePublicBinaryPrefix):], k.k[:])
return b, nil
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler.
func (k *NodePublic) UnmarshalBinary(in []byte) error {
data := mem.B(in)
if !mem.HasPrefix(data, mem.S(nodePublicBinaryPrefix)) {
return fmt.Errorf("missing/incorrect type prefix %s", nodePublicBinaryPrefix)
}
if want, got := len(nodePublicBinaryPrefix)+NodePublicRawLen, data.Len(); want != got {
return fmt.Errorf("incorrect len for NodePublic (%d != %d)", got, want)
}
data.SliceFrom(len(nodePublicBinaryPrefix)).Copy(k.k[:])
return nil
}
// WireGuardGoString prints k in the same format used by wireguard-go.
func (k NodePublic) WireGuardGoString() string {
// This implementation deliberately matches the overly complicated

View File

@@ -30,6 +30,20 @@ func TestNodeKey(t *testing.T) {
if full, got := string(bs), ":"+p.UntypedHexString(); !strings.HasSuffix(full, got) {
t.Fatalf("NodePublic.UntypedHexString is not a suffix of the typed serialization, got %q want suffix of %q", got, full)
}
bs, err = p.MarshalBinary()
if err != nil {
t.Fatal(err)
}
if got, want := bs, append([]byte(nodePublicBinaryPrefix), p.k[:]...); !bytes.Equal(got, want) {
t.Fatalf("Binary-encoded NodePublic = %x, want %x", got, want)
}
var decoded NodePublic
if err := decoded.UnmarshalBinary(bs); err != nil {
t.Fatalf("NodePublic.UnmarshalBinary(%x) failed: %v", bs, err)
}
if decoded != p {
t.Errorf("unmarshaled and original NodePublic differ:\noriginal = %v\ndecoded = %v", p, decoded)
}
z := NodePublic{}
if !z.IsZero() {