mirror of
https://github.com/fiatjaf/nak.git
synced 2024-12-22 01:55:51 -05:00
nsecbunker work-in-progress.
This commit is contained in:
parent
5657fdc6a7
commit
bc7cd0939c
31
event.go
31
event.go
|
@ -9,10 +9,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bgentry/speakeasy"
|
||||
"github.com/mailru/easyjson"
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
"github.com/nbd-wtf/go-nostr/nson"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/exp/slices"
|
||||
|
@ -106,31 +104,10 @@ example:
|
|||
}
|
||||
}
|
||||
|
||||
// gather the secret key first
|
||||
sec := c.String("sec")
|
||||
if c.Bool("prompt-sec") {
|
||||
if isPiped() {
|
||||
return fmt.Errorf("can't prompt for a secret key when processing data from a pipe, try again without --prompt-sec")
|
||||
}
|
||||
var err error
|
||||
sec, err = speakeasy.FAsk(os.Stderr, "type your secret key as nsec or hex: ")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get secret key: %w", err)
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(sec, "nsec1") {
|
||||
_, hex, err := nip19.Decode(sec)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid nsec: %w", err)
|
||||
}
|
||||
sec = hex.(string)
|
||||
}
|
||||
if len(sec) > 64 {
|
||||
return fmt.Errorf("invalid secret key: too large")
|
||||
}
|
||||
sec = strings.Repeat("0", 64-len(sec)) + sec // left-pad
|
||||
if err := validate32BytesHex(sec); err != nil {
|
||||
return fmt.Errorf("invalid secret key")
|
||||
// gather the secret key
|
||||
sec, err := gatherSecretKeyFromArguments(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// then process input and generate events
|
||||
|
|
2
go.mod
2
go.mod
|
@ -7,7 +7,7 @@ toolchain go1.21.0
|
|||
require (
|
||||
github.com/bgentry/speakeasy v0.1.0
|
||||
github.com/mailru/easyjson v0.7.7
|
||||
github.com/nbd-wtf/go-nostr v0.26.1
|
||||
github.com/nbd-wtf/go-nostr v0.26.2
|
||||
github.com/nbd-wtf/nostr-sdk v0.0.2
|
||||
github.com/urfave/cli/v2 v2.25.3
|
||||
golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53
|
||||
|
|
4
go.sum
4
go.sum
|
@ -80,8 +80,8 @@ github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlT
|
|||
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/nbd-wtf/go-nostr v0.26.1 h1:aqvXYdPycETozrRPp2roSNALNk2XMxRkBrHu3jXmhxA=
|
||||
github.com/nbd-wtf/go-nostr v0.26.1/go.mod h1:bkffJI+x914sPQWum9ZRUn66D7NpDnAoWo1yICvj3/0=
|
||||
github.com/nbd-wtf/go-nostr v0.26.2 h1:VI47qW7jqLrofB9DbDqH9lQH38eYgLYI7lBPYywIS78=
|
||||
github.com/nbd-wtf/go-nostr v0.26.2/go.mod h1:bkffJI+x914sPQWum9ZRUn66D7NpDnAoWo1yICvj3/0=
|
||||
github.com/nbd-wtf/nostr-sdk v0.0.2 h1:mZIeti+DOF0D1179q+NLL/h0LVMMOPRQAYpOuUrn5Zk=
|
||||
github.com/nbd-wtf/nostr-sdk v0.0.2/go.mod h1:KQZOtzcrXBlVhpZYG1tw83ADIONNMMPjUU3ZAH5U2RY=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
|
|
35
helpers.go
35
helpers.go
|
@ -9,12 +9,17 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/bgentry/speakeasy"
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
LINE_PROCESSING_ERROR = iota
|
||||
|
||||
BOLD_ON = "\033[1m"
|
||||
BOLD_OFF = "\033[21m"
|
||||
)
|
||||
|
||||
var log = func(msg string, args ...any) {
|
||||
|
@ -129,3 +134,33 @@ func exitIfLineProcessingError(c *cli.Context) {
|
|||
os.Exit(123)
|
||||
}
|
||||
}
|
||||
|
||||
func gatherSecretKeyFromArguments(c *cli.Context) (string, error) {
|
||||
sec := c.String("sec")
|
||||
if c.Bool("prompt-sec") {
|
||||
if isPiped() {
|
||||
return "", fmt.Errorf("can't prompt for a secret key when processing data from a pipe, try again without --prompt-sec")
|
||||
}
|
||||
var err error
|
||||
sec, err = speakeasy.FAsk(os.Stderr, "type your secret key as nsec or hex: ")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get secret key: %w", err)
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(sec, "nsec1") {
|
||||
_, hex, err := nip19.Decode(sec)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid nsec: %w", err)
|
||||
}
|
||||
sec = hex.(string)
|
||||
}
|
||||
if len(sec) > 64 {
|
||||
return "", fmt.Errorf("invalid secret key: too large")
|
||||
}
|
||||
sec = strings.Repeat("0", 64-len(sec)) + sec // left-pad
|
||||
if err := validate32BytesHex(sec); err != nil {
|
||||
return "", fmt.Errorf("invalid secret key")
|
||||
}
|
||||
|
||||
return sec, nil
|
||||
}
|
||||
|
|
1
main.go
1
main.go
|
@ -19,6 +19,7 @@ var app = &cli.App{
|
|||
encode,
|
||||
verify,
|
||||
relay,
|
||||
nsecbunker,
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
|
|
124
nsecbunker.go
Normal file
124
nsecbunker.go
Normal file
|
@ -0,0 +1,124 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
"github.com/bgentry/speakeasy"
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
"github.com/nbd-wtf/go-nostr/nip46"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var nsecbunker = &cli.Command{
|
||||
Name: "nsecbunker",
|
||||
Usage: "starts a NIP-46 signer daemon with the given --sec key",
|
||||
ArgsUsage: "[relay...]",
|
||||
Description: ``,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "sec",
|
||||
Usage: "secret key to sign the event, as hex or nsec",
|
||||
DefaultText: "the key '1'",
|
||||
Value: "0000000000000000000000000000000000000000000000000000000000000001",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "prompt-sec",
|
||||
Usage: "prompt the user to paste a hex or nsec with which to sign the event",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "yes",
|
||||
Aliases: []string{"y"},
|
||||
Usage: "always respond to any NIP-46 requests from anyone",
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
// try to connect to the relays here
|
||||
qs := url.Values{}
|
||||
relayURLs := make([]string, 0, c.Args().Len())
|
||||
if relayUrls := c.Args().Slice(); len(relayUrls) > 0 {
|
||||
_, relays := connectToAllRelays(c.Context, relayUrls)
|
||||
if len(relays) == 0 {
|
||||
log("failed to connect to any of the given relays.\n")
|
||||
os.Exit(3)
|
||||
}
|
||||
for _, relay := range relays {
|
||||
relayURLs = append(relayURLs, relay.URL)
|
||||
qs.Add("relay", relay.URL)
|
||||
}
|
||||
}
|
||||
if len(relayURLs) == 0 {
|
||||
return fmt.Errorf("not connected to any relays: please specify at least one")
|
||||
}
|
||||
|
||||
// gather the secret key
|
||||
sec, err := gatherSecretKeyFromArguments(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pubkey, err := nostr.GetPublicKey(sec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
npub, _ := nip19.EncodePublicKey(pubkey)
|
||||
code := fmt.Sprintf("%s#secret?%s", npub, qs.Encode())
|
||||
log("listening at %s%v%s:\n %spubkey:%s %s\n %snpub:%s %s\n %sconnection code:%s %s\n\n",
|
||||
BOLD_ON, relayURLs, BOLD_OFF,
|
||||
BOLD_ON, BOLD_OFF, pubkey,
|
||||
BOLD_ON, BOLD_OFF, npub,
|
||||
BOLD_ON, BOLD_OFF, code,
|
||||
)
|
||||
|
||||
alwaysYes := c.Bool("yes")
|
||||
|
||||
// subscribe to relays
|
||||
pool := nostr.NewSimplePool(c.Context)
|
||||
events := pool.SubMany(c.Context, relayURLs, nostr.Filters{
|
||||
{
|
||||
Kinds: []int{24133},
|
||||
Tags: nostr.TagMap{"p": []string{pubkey}},
|
||||
},
|
||||
})
|
||||
|
||||
signer := nip46.NewSigner(sec)
|
||||
for ie := range events {
|
||||
req, resp, eventResponse, harmless, err := signer.HandleRequest(ie.Event)
|
||||
if err != nil {
|
||||
log("< failed to handle request from %s: %w", ie.Event.PubKey, err)
|
||||
continue
|
||||
}
|
||||
|
||||
jreq, _ := json.MarshalIndent(req, " ", " ")
|
||||
log("- got request from '%s': %s\n", ie.Event.PubKey, string(jreq))
|
||||
jresp, _ := json.MarshalIndent(resp, " ", " ")
|
||||
log("~ responding with %s\n", string(jresp))
|
||||
|
||||
if alwaysYes || harmless || askUserIfWeCanRespond() {
|
||||
_, err := ie.Relay.Publish(c.Context, eventResponse)
|
||||
if err == nil {
|
||||
log("* sent response!\n")
|
||||
} else {
|
||||
log("* failed to send response: %s\n", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func askUserIfWeCanRespond() bool {
|
||||
answer, err := speakeasy.FAsk(os.Stderr,
|
||||
fmt.Sprintf("proceed? y/n"))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if answer == "y" || answer == "yes" {
|
||||
return true
|
||||
}
|
||||
|
||||
return askUserIfWeCanRespond()
|
||||
}
|
Loading…
Reference in New Issue
Block a user