From f4cf2420843b16d1a4127e4b59a2cc59e701f880 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Fri, 1 Mar 2024 15:54:28 -0300 Subject: [PATCH] validating/parsing nip05 and nip46. --- nip05/nip05.go | 29 +++++++++++++++++------------ nip05/nip05_test.go | 37 +++++++++++++++++++++++++++++++++++++ nip46/nip46.go | 7 +++++++ nip46/nip46_test.go | 21 +++++++++++++++++++++ 4 files changed, 82 insertions(+), 12 deletions(-) create mode 100644 nip05/nip05_test.go create mode 100644 nip46/nip46_test.go diff --git a/nip05/nip05.go b/nip05/nip05.go index 83ec599..f2551e2 100644 --- a/nip05/nip05.go +++ b/nip05/nip05.go @@ -5,17 +5,31 @@ import ( "encoding/json" "fmt" "net/http" + "regexp" "strings" "github.com/nbd-wtf/go-nostr" ) +var NIP05_REGEX = regexp.MustCompile(`^(?:([\w.+-]+)@)?([\w_-]+(\.[\w_-]+)+)$`) + type WellKnownResponse struct { Names map[string]string `json:"names"` Relays map[string][]string `json:"relays,omitempty"` NIP46 map[string][]string `json:"nip46,omitempty"` } +func ParseIdentifier(fullname string) (name string, domain string, err error) { + res := NIP05_REGEX.FindStringSubmatch(fullname) + if len(res) == 0 { + return "", "", fmt.Errorf("invalid identifier") + } + if res[1] == "" { + res[1] = "_" + } + return res[1], res[2], nil +} + func QueryIdentifier(ctx context.Context, fullname string) (*nostr.ProfilePointer, error) { result, name, err := Fetch(ctx, fullname) if err != nil { @@ -39,18 +53,9 @@ func QueryIdentifier(ctx context.Context, fullname string) (*nostr.ProfilePointe } func Fetch(ctx context.Context, fullname string) (resp WellKnownResponse, name string, err error) { - spl := strings.Split(fullname, "@") - - var domain string - switch len(spl) { - case 1: - name = "_" - domain = spl[0] - case 2: - name = spl[0] - domain = spl[1] - default: - return resp, name, fmt.Errorf("not a valid nip-05 identifier") + name, domain, err := ParseIdentifier(fullname) + if err != nil { + return resp, name, fmt.Errorf("failed to parse '%s': %w", fullname, err) } req, err := http.NewRequestWithContext(ctx, "GET", diff --git a/nip05/nip05_test.go b/nip05/nip05_test.go new file mode 100644 index 0000000..5f60c2e --- /dev/null +++ b/nip05/nip05_test.go @@ -0,0 +1,37 @@ +package nip05 + +import ( + "testing" +) + +func TestParse(t *testing.T) { + name, domain, _ := ParseIdentifier("saknd@yyq.com") + if name != "saknd" || domain != "yyq.com" { + t.Fatalf("wrong parsing") + } + + name, domain, _ = ParseIdentifier("287354gkj+asbdfo8gw3rlicbsopifbcp3iougb5piseubfdikswub5ks@yyq.com") + if name != "287354gkj+asbdfo8gw3rlicbsopifbcp3iougb5piseubfdikswub5ks" || domain != "yyq.com" { + t.Fatalf("wrong parsing") + } + + name, domain, _ = ParseIdentifier("asdn.com") + if name != "_" || domain != "asdn.com" { + t.Fatalf("wrong parsing") + } + + name, domain, _ = ParseIdentifier("_@uxux.com.br") + if name != "_" || domain != "uxux.com.br" { + t.Fatalf("wrong parsing") + } + + _, _, err := ParseIdentifier("821yh498ig21") + if err == nil { + t.Fatalf("should have errored") + } + + _, _, err = ParseIdentifier("////") + if err == nil { + t.Fatalf("should have errored") + } +} diff --git a/nip46/nip46.go b/nip46/nip46.go index 7d82f88..4e22a9f 100644 --- a/nip46/nip46.go +++ b/nip46/nip46.go @@ -3,11 +3,14 @@ package nip46 import ( "encoding/json" "fmt" + "regexp" "github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr/nip04" ) +var BUNKER_REGEX = regexp.MustCompile(`^bunker:\/\/([0-9a-f]{64})\??([?\/\w:.=&%]*)$`) + type Request struct { ID string `json:"id"` Method string `json:"method"` @@ -77,3 +80,7 @@ func (s Session) MakeResponse( return resp, evt, nil } + +func IsValidBunkerURL(input string) bool { + return BUNKER_REGEX.MatchString(input) +} diff --git a/nip46/nip46_test.go b/nip46/nip46_test.go new file mode 100644 index 0000000..eef3960 --- /dev/null +++ b/nip46/nip46_test.go @@ -0,0 +1,21 @@ +package nip46 + +import "testing" + +func TestValidBunkerURL(t *testing.T) { + if !IsValidBunkerURL("bunker://3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d?relay=wss%3A%2F%2Frelay.damus.io&relay=wss%3A%2F%2Frelay.snort.social&relay=wss%3A%2F%2Frelay.nsecbunker.com") { + t.Fatalf("should be valid") + } + if IsValidBunkerURL("askjdbkajdbv") { + t.Fatalf("should be invalid") + } + if IsValidBunkerURL("asdjasbndksa@asjdnksa.com") { + t.Fatalf("should be invalid") + } + if IsValidBunkerURL("https://hello.com?relays=wss://xxxxxx.xxxx") { + t.Fatalf("should be invalid") + } + if IsValidBunkerURL("bunker://fa883d107ef9e558472c4eb9aaaefa459d?relay=wss%3A%2F%2Frelay.damus.io&relay=wss%3A%2F%2Frelay.snort.social&relay=wss%3A%2F%2Frelay.nsecbunker.com") { + t.Fatalf("should be invalid") + } +}