versia-go/pkg/lysand/public_key.go
2024-08-13 01:18:14 +02:00

67 lines
1.5 KiB
Go

package lysand
import (
"crypto/ed25519"
"crypto/x509"
"encoding/base64"
"encoding/json"
"errors"
)
var (
ErrInvalidPublicKeyType = errors.New("invalid public key type")
)
// PublicKey represents a public key for a user. For more information, see the [Spec].
//
// [Spec]: https://lysand.org/security/keys#public-key-cryptography
type PublicKey struct {
PublicKey SPKIPublicKey `json:"public_key"`
Actor *URL `json:"actor"`
}
// SPKIPublicKey is a type that represents a [ed25519.PublicKey] in the SPKI
// format.
type SPKIPublicKey ed25519.PublicKey
// UnmarshalJSON decodes the public key from a base64 encoded string and then unmarshals it from the SPKI form.
func (k *SPKIPublicKey) UnmarshalJSON(raw []byte) error {
rawStr := ""
if err := json.Unmarshal(raw, &rawStr); err != nil {
return err
}
raw, err := base64.StdEncoding.DecodeString(rawStr)
if err != nil {
return err
}
parsed, err := x509.ParsePKIXPublicKey(raw)
if err != nil {
return err
}
edKey, ok := parsed.(ed25519.PublicKey)
if !ok {
return ErrInvalidPublicKeyType
}
*k = SPKIPublicKey(edKey)
return nil
}
// MarshalJSON marshals the SPKI-encoded public key to a base64 encoded string.
func (k SPKIPublicKey) MarshalJSON() ([]byte, error) {
raw, err := x509.MarshalPKIXPublicKey(ed25519.PublicKey(k))
if err != nil {
return nil, err
}
return json.Marshal(base64.StdEncoding.EncodeToString(raw))
}
func (k SPKIPublicKey) ToStd() ed25519.PublicKey {
return ed25519.PublicKey(k)
}