Files
Nip-05-api/internal/nostr/keys.go
2026-04-29 02:35:00 +00:00

73 lines
1.5 KiB
Go

package nostr
import (
"encoding/hex"
"errors"
"strings"
gn "github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip19"
)
var (
ErrInvalidPubkey = errors.New("invalid pubkey")
ErrInvalidNsec = errors.New("invalid nsec")
)
// NormalizePubkey accepts npub bech32 or 64-char hex and returns lowercase hex.
func NormalizePubkey(in string) (string, error) {
in = strings.TrimSpace(in)
if in == "" {
return "", ErrInvalidPubkey
}
if strings.HasPrefix(in, "npub1") {
prefix, data, err := nip19.Decode(in)
if err != nil {
return "", ErrInvalidPubkey
}
if prefix != "npub" {
return "", ErrInvalidPubkey
}
s, ok := data.(string)
if !ok {
return "", ErrInvalidPubkey
}
return strings.ToLower(s), nil
}
if len(in) != 64 {
return "", ErrInvalidPubkey
}
if _, err := hex.DecodeString(in); err != nil {
return "", ErrInvalidPubkey
}
if !gn.IsValidPublicKey(in) {
return "", ErrInvalidPubkey
}
return strings.ToLower(in), nil
}
// HexToNpub converts hex pubkey to npub bech32. Empty string on error.
func HexToNpub(hexpk string) string {
npub, err := nip19.EncodePublicKey(hexpk)
if err != nil {
return ""
}
return npub
}
// NsecToHex decodes nsec1... to hex private key.
func NsecToHex(nsec string) (string, error) {
prefix, data, err := nip19.Decode(strings.TrimSpace(nsec))
if err != nil {
return "", ErrInvalidNsec
}
if prefix != "nsec" {
return "", ErrInvalidNsec
}
s, ok := data.(string)
if !ok {
return "", ErrInvalidNsec
}
return strings.ToLower(s), nil
}