From 40a934e3f9602ec422f9c4523800f16786b32fb3 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Sat, 20 Jun 2026 20:30:37 -0300 Subject: [PATCH] fix conflicts with running bunker connections (client and server apparently) through auth-required relays, clarify "connect-as" and use a special flag for it, let's see. hopefully fixes https://github.com/fiatjaf/nak/issues/116 --- flags.go | 39 +++++++++++++++++++++++++++++++++++++++ go.mod | 2 +- go.sum | 4 ++-- helpers.go | 13 +++++++++++++ helpers_key.go | 50 ++++++++++++++++++-------------------------------- main.go | 5 +++-- 6 files changed, 76 insertions(+), 37 deletions(-) diff --git a/flags.go b/flags.go index 2c9d022..fd7b504 100644 --- a/flags.go +++ b/flags.go @@ -131,6 +131,45 @@ func getNaturalDate(cmd *cli.Command, name string) nostr.Timestamp { // // +type ( + SecretKeyFlag = cli.FlagBase[nostr.SecretKey, struct{}, secretkeyValue] +) + +type secretkeyValue struct { + secretkey nostr.SecretKey + hasBeenSet bool +} + +var _ cli.ValueCreator[nostr.SecretKey, struct{}] = secretkeyValue{} + +func (t secretkeyValue) Create(val nostr.SecretKey, p *nostr.SecretKey, c struct{}) cli.Value { + *p = val + return &secretkeyValue{ + secretkey: val, + } +} + +func (t secretkeyValue) ToString(b nostr.SecretKey) string { return t.secretkey.String() } + +func (t *secretkeyValue) Set(value string) error { + secretkey, err := parseSecretKey(value) + t.secretkey = secretkey + t.hasBeenSet = true + return err +} + +func (t *secretkeyValue) String() string { return fmt.Sprintf("%#v", t.secretkey) } +func (t *secretkeyValue) Value() nostr.SecretKey { return t.secretkey } +func (t *secretkeyValue) Get() any { return t.secretkey } + +func getSecretKey(cmd *cli.Command, name string) nostr.SecretKey { + return cmd.Value(name).(nostr.SecretKey) +} + +// +// +// + type ( PubKeyFlag = cli.FlagBase[nostr.PubKey, struct{}, pubkeyValue] ) diff --git a/go.mod b/go.mod index b6c3953..9ecb731 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/fiatjaf/nak go 1.25 require ( - fiatjaf.com/nostr v0.0.0-20260615112943-0616b30ab35c + fiatjaf.com/nostr v0.0.0-20260620232658-8389bac80c5f github.com/AlecAivazis/survey/v2 v2.3.7 github.com/bep/debounce v1.2.1 github.com/btcsuite/btcd/btcec/v2 v2.3.6 diff --git a/go.sum b/go.sum index 97a8933..0c84f09 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ fiatjaf.com/lib v0.3.7 h1:mXZOn7NrUcjSdy4oNvwQyAmes7Ueb+Zr5hjqMIe2dxI= fiatjaf.com/lib v0.3.7/go.mod h1:UlHaZvPHj25PtKLh9GjZkUHRmQ2xZ8Jkoa4VRaLeeQ8= -fiatjaf.com/nostr v0.0.0-20260615112943-0616b30ab35c h1:LyUM+6Z8e51OyIRriZooY3+W0ogWBUJe0B/nU1uD04o= -fiatjaf.com/nostr v0.0.0-20260615112943-0616b30ab35c/go.mod h1:b1EIUDnd133Ie8Pg8O/biaKdFyCMz28aD4n64g1GqvM= +fiatjaf.com/nostr v0.0.0-20260620232658-8389bac80c5f h1:dl17ebu+HhtHTS9AdOc27TDUGfSjYVEO4qYLHEwjxOw= +fiatjaf.com/nostr v0.0.0-20260620232658-8389bac80c5f/go.mod h1:b1EIUDnd133Ie8Pg8O/biaKdFyCMz28aD4n64g1GqvM= github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ= github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo= github.com/FastFilter/xorfilter v0.2.1 h1:lbdeLG9BdpquK64ZsleBS8B4xO/QW1IM0gMzF7KaBKc= diff --git a/helpers.go b/helpers.go index 2d40507..920ee81 100644 --- a/helpers.go +++ b/helpers.go @@ -478,6 +478,19 @@ func parsePubKey(value string) (nostr.PubKey, error) { return nostr.PubKey{}, fmt.Errorf("invalid pubkey (\"%s\"): expected hex, npub, or nprofile", value) } +func parseSecretKey(input string) (nostr.SecretKey, error) { + if prefix, ski, err := nip19.Decode(input); err == nil && prefix == "nsec" { + return ski.(nostr.SecretKey), nil + } + + sk, err := nostr.SecretKeyFromHex(input) + if err != nil { + return nostr.SecretKey{}, fmt.Errorf("invalid secret key: %w", err) + } + + return sk, nil +} + func parseEventID(value string) (nostr.ID, error) { id, err := nostr.IDFromHex(value) if err == nil { diff --git a/helpers_key.go b/helpers_key.go index f862d14..07ddd39 100644 --- a/helpers_key.go +++ b/helpers_key.go @@ -9,7 +9,6 @@ import ( "fiatjaf.com/nostr" "fiatjaf.com/nostr/keyer" - "fiatjaf.com/nostr/nip19" "fiatjaf.com/nostr/nip42" "fiatjaf.com/nostr/nip46" "fiatjaf.com/nostr/nip49" @@ -41,10 +40,10 @@ func gatherKeyerFromArguments(ctx context.Context, c *cli.Command) (nostr.Keyer, } var kr nostr.Keyer - if bunker != nil { - kr = keyer.NewBunkerSignerFromBunkerClient(bunker) - } else { + if bunker == nil { kr = keyer.NewPlainKeySigner(key) + } else { + kr = keyer.NewBunkerSignerFromBunkerClient(bunker) } return kr, key, nil @@ -52,25 +51,15 @@ func gatherKeyerFromArguments(ctx context.Context, c *cli.Command) (nostr.Keyer, func gatherSecretKeyOrBunkerFromArguments(ctx context.Context, c *cli.Command) (nostr.SecretKey, *nip46.BunkerClient, error) { sec := c.String("sec") + if strings.HasPrefix(sec, "bunker://") { // it's a bunker bunkerURL := sec - clientKeyHex := c.String("connect-as") - var clientKey nostr.SecretKey - - if clientKeyHex != "" { - var err error - clientKey, err = nostr.SecretKeyFromHex(clientKeyHex) - if err != nil { - return nostr.SecretKey{}, nil, fmt.Errorf("bunker client key '%s' is invalid: %w", clientKeyHex, err) - } - } else { - clientKey = defaultKey() - } + clientKey := getSecretKey(c, "connect-as") logverbose("[nip46]: connecting to %s with client key %s\n", bunkerURL, clientKey.Hex()) - bunker, err := nip46.ConnectBunker(ctx, clientKey, bunkerURL, nil, func(s string) { + bunker, err := nip46.ConnectBunker(ctx, clientKey, bunkerURL, sys.Pool, func(s string) { log(color.CyanString("[nip46]: open the following URL: %s"), s) }) if err != nil { @@ -96,16 +85,8 @@ func gatherSecretKeyOrBunkerFromArguments(ctx context.Context, c *cli.Command) ( return sk, nil, nil } - if prefix, ski, err := nip19.Decode(sec); err == nil && prefix == "nsec" { - return ski.(nostr.SecretKey), nil, nil - } - - sk, err := nostr.SecretKeyFromHex(sec) - if err != nil { - return nostr.SecretKey{}, nil, fmt.Errorf("invalid secret key: %w", err) - } - - return sk, nil, nil + sk, err := parseSecretKey(sec) + return sk, nil, err } func authSigner(ctx context.Context, c *cli.Command, log func(s string, args ...any), authEvent *nostr.Event) (err error) { @@ -120,14 +101,19 @@ func authSigner(ctx context.Context, c *cli.Command, log func(s string, args ... return fmt.Errorf("auth required, but --auth flag not given") } - kr, _, err := gatherKeyerFromArguments(ctx, c) - if err != nil { - return err + var kr nostr.Keyer + + if nip46.IsBunkerClientOperation(ctx) { + kr = keyer.NewPlainKeySigner(getSecretKey(c, "connect-as")) + } else { + kr, _, err = gatherKeyerFromArguments(ctx, c) + if err != nil { + return err + } } pk, _ := kr.GetPublicKey(ctx) - npub := nip19.EncodeNpub(pk) - log("authenticating as %s... ", color.YellowString("%s…%s", npub[0:7], npub[58:])) + log("authenticating as %s... ", color.YellowString("%s…", pk.Hex()[0:16])) return kr.SignEvent(ctx, authEvent) } diff --git a/main.go b/main.go index 732b155..623afd8 100644 --- a/main.go +++ b/main.go @@ -43,12 +43,13 @@ var defaultKeyFlags = []cli.Flag{ Usage: "prompt the user to paste a hex or nsec with which to sign the event", Category: CATEGORY_SIGNER, }, - &cli.StringFlag{ + &SecretKeyFlag{ Name: "connect-as", Usage: "private key to use when communicating with nip46 bunkers", - DefaultText: "the default key (see `nak key default`)", Category: CATEGORY_SIGNER, Sources: cli.EnvVars("NOSTR_CLIENT_KEY"), + Value: defaultKey(), + DefaultText: "the default key (see `nak key default`)", }, }