package nebula import ( "crypto/ed25519" "crypto/rand" "fmt" ) var ( sigPrivKeyPrefix = []byte("s0") sigPubKeyPrefix = []byte("S0") ) // SigningPrivateKey wraps an ed25519.PrivateKey to provide convenient text // (un)marshaling methods. type SigningPrivateKey ed25519.PrivateKey // MarshalText implements the encoding.TextMarshaler interface. func (k SigningPrivateKey) MarshalText() ([]byte, error) { return encodeWithPrefix(sigPrivKeyPrefix, k), nil } // UnmarshalText implements the encoding.TextUnmarshaler interface. func (k *SigningPrivateKey) UnmarshalText(b []byte) error { b, err := decodeWithPrefix(sigPrivKeyPrefix, b) if err != nil { return fmt.Errorf("unmarshaling: %w", err) } *k = SigningPrivateKey(b) return nil } func (k SigningPrivateKey) String() string { b, err := k.MarshalText() if err != nil { panic(err) } return string(b) } // SigningPublicKey wraps an ed25519.PublicKey to provide convenient text // (un)marshaling methods. type SigningPublicKey ed25519.PublicKey // MarshalText implements the encoding.TextMarshaler interface. func (pk SigningPublicKey) MarshalText() ([]byte, error) { return encodeWithPrefix(sigPubKeyPrefix, pk), nil } // UnmarshalText implements the encoding.TextUnmarshaler interface. func (pk *SigningPublicKey) UnmarshalText(b []byte) error { b, err := decodeWithPrefix(sigPubKeyPrefix, b) if err != nil { return fmt.Errorf("unmarshaling: %w", err) } *pk = SigningPublicKey(b) return nil } func (pk SigningPublicKey) String() string { b, err := pk.MarshalText() if err != nil { panic(err) } return string(b) } // GenerateSigningPair generates and returns a new key pair which can be used // for signing arbitrary blobs of bytes. func GenerateSigningPair() (SigningPublicKey, SigningPrivateKey) { pub, priv, err := ed25519.GenerateKey(rand.Reader) if err != nil { panic(fmt.Errorf("generating ed25519 key: %w", err)) } return SigningPublicKey(pub), SigningPrivateKey(priv) }