diff --git a/types/key/nl.go b/types/key/nl.go index 4e3801e22..6503ca66f 100644 --- a/types/key/nl.go +++ b/types/key/nl.go @@ -16,6 +16,10 @@ const ( // nlPrivateHexPrefix is the prefix used to identify a // hex-encoded network-lock key. nlPrivateHexPrefix = "nlpriv:" + + // nlPublicHexPrefix is the prefix used to identify the public + // side of a hex-encoded network-lock key. + nlPublicHexPrefix = "nlpub:" ) // NLPrivate is a node-managed network-lock key, used for signing @@ -50,15 +54,18 @@ func (k NLPrivate) MarshalText() ([]byte, error) { } // Public returns the public component of this key. -func (k NLPrivate) Public() ed25519.PublicKey { - return ed25519.PrivateKey(k.k[:]).Public().(ed25519.PublicKey) +func (k NLPrivate) Public() NLPublic { + var out NLPublic + copy(out.k[:], ed25519.PrivateKey(k.k[:]).Public().(ed25519.PublicKey)) + return out } // KeyID returns an identifier for this key. func (k NLPrivate) KeyID() tka.KeyID { + pub := k.Public() return tka.Key{ Kind: tka.Key25519, - Public: k.Public(), + Public: pub.k[:], }.ID() } @@ -72,3 +79,24 @@ func (k NLPrivate) SignAUM(a *tka.AUM) error { }) return nil } + +// NLPublic is the public portion of a a NLPrivate. +type NLPublic struct { + k [ed25519.PublicKeySize]byte +} + +// MarshalText implements encoding.TextUnmarshaler. +func (k *NLPublic) UnmarshalText(b []byte) error { + return parseHex(k.k[:], mem.B(b), mem.S(nlPublicHexPrefix)) +} + +// MarshalText implements encoding.TextMarshaler. +func (k NLPublic) MarshalText() ([]byte, error) { + return toHex(k.k[:], nlPublicHexPrefix), nil +} + +// Verifier returns a ed25519.PublicKey that can be used to +// verify signatures. +func (k NLPublic) Verifier() ed25519.PublicKey { + return ed25519.PublicKey(k.k[:]) +} diff --git a/types/key/nl_test.go b/types/key/nl_test.go index fe0f71191..ed69a1fd1 100644 --- a/types/key/nl_test.go +++ b/types/key/nl_test.go @@ -26,9 +26,23 @@ func TestNLPrivate(t *testing.T) { t.Error("decoded and generated NLPrivate bytes differ") } + // Test NLPublic + pub := p.Public() + encoded, err = pub.MarshalText() + if err != nil { + t.Fatal(err) + } + var decodedPub NLPublic + if err := decodedPub.UnmarshalText(encoded); err != nil { + t.Fatal(err) + } + if !bytes.Equal(decodedPub.k[:], pub.k[:]) { + t.Error("decoded and generated NLPublic bytes differ") + } + // Test that NLPrivate implements tka.Signer by making a new // authority. - k := tka.Key{Kind: tka.Key25519, Public: p.Public(), Votes: 1} + k := tka.Key{Kind: tka.Key25519, Public: pub.Verifier(), Votes: 1} _, aum, err := tka.Create(&tka.Mem{}, tka.State{ Keys: []tka.Key{k}, DisablementSecrets: [][]byte{bytes.Repeat([]byte{1}, 32)},