mirror of
https://github.com/fiatjaf/nak.git
synced 2024-10-30 09:09:08 -04:00
--prompt-sec for getting a secret key from a prompt.
This commit is contained in:
parent
200e4e61f7
commit
d95b6f50ff
16
encode.go
16
encode.go
|
@ -1,9 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/nbd-wtf/go-nostr/nip19"
|
"github.com/nbd-wtf/go-nostr/nip19"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
@ -232,17 +230,3 @@ var encode = &cli.Command{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func validate32BytesHex(target string) error {
|
|
||||||
if _, err := hex.DecodeString(target); err != nil {
|
|
||||||
return fmt.Errorf("target '%s' is not valid hex: %s", target, err)
|
|
||||||
}
|
|
||||||
if len(target) != 64 {
|
|
||||||
return fmt.Errorf("expected '%s' to be 64 characters (32 bytes), got %d", target, len(target))
|
|
||||||
}
|
|
||||||
if strings.ToLower(target) != target {
|
|
||||||
return fmt.Errorf("expected target to be all lowercase hex. try again with '%s'", strings.ToLower(target))
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
38
event.go
38
event.go
|
@ -9,8 +9,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/bgentry/speakeasy"
|
||||||
"github.com/mailru/easyjson"
|
"github.com/mailru/easyjson"
|
||||||
"github.com/nbd-wtf/go-nostr"
|
"github.com/nbd-wtf/go-nostr"
|
||||||
|
"github.com/nbd-wtf/go-nostr/nip19"
|
||||||
"github.com/nbd-wtf/go-nostr/nson"
|
"github.com/nbd-wtf/go-nostr/nson"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
@ -35,10 +37,14 @@ example:
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "sec",
|
Name: "sec",
|
||||||
Usage: "secret key to sign the event",
|
Usage: "secret key to sign the event, as hex or nsec",
|
||||||
DefaultText: "the key '1'",
|
DefaultText: "the key '1'",
|
||||||
Value: "0000000000000000000000000000000000000000000000000000000000000001",
|
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{
|
&cli.BoolFlag{
|
||||||
Name: "envelope",
|
Name: "envelope",
|
||||||
Usage: "print the event enveloped in a [\"EVENT\", ...] message ready to be sent to a relay",
|
Usage: "print the event enveloped in a [\"EVENT\", ...] message ready to be sent to a relay",
|
||||||
|
@ -90,6 +96,34 @@ example:
|
||||||
},
|
},
|
||||||
ArgsUsage: "[relay...]",
|
ArgsUsage: "[relay...]",
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(c *cli.Context) error {
|
||||||
|
// 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")
|
||||||
|
}
|
||||||
|
|
||||||
|
// then process input and generate events
|
||||||
for stdinEvent := range getStdinLinesOrBlank() {
|
for stdinEvent := range getStdinLinesOrBlank() {
|
||||||
evt := nostr.Event{
|
evt := nostr.Event{
|
||||||
Tags: make(nostr.Tags, 0, 3),
|
Tags: make(nostr.Tags, 0, 3),
|
||||||
|
@ -164,7 +198,7 @@ example:
|
||||||
}
|
}
|
||||||
|
|
||||||
if evt.Sig == "" || mustRehashAndResign {
|
if evt.Sig == "" || mustRehashAndResign {
|
||||||
if err := evt.Sign(c.String("sec")); err != nil {
|
if err := evt.Sign(sec); err != nil {
|
||||||
return fmt.Errorf("error signing with provided key: %w", err)
|
return fmt.Errorf("error signing with provided key: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -5,6 +5,7 @@ go 1.21
|
||||||
toolchain go1.21.0
|
toolchain go1.21.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/bgentry/speakeasy v0.1.0
|
||||||
github.com/mailru/easyjson v0.7.7
|
github.com/mailru/easyjson v0.7.7
|
||||||
github.com/nbd-wtf/go-nostr v0.25.3
|
github.com/nbd-wtf/go-nostr v0.25.3
|
||||||
github.com/nbd-wtf/nostr-sdk v0.0.2
|
github.com/nbd-wtf/nostr-sdk v0.0.2
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -1,4 +1,6 @@
|
||||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||||
|
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
|
||||||
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
||||||
github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M=
|
github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M=
|
||||||
github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
|
github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
|
||||||
|
|
22
helpers.go
22
helpers.go
|
@ -3,6 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
@ -15,6 +16,11 @@ const (
|
||||||
LINE_PROCESSING_ERROR = iota
|
LINE_PROCESSING_ERROR = iota
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func isPiped() bool {
|
||||||
|
stat, _ := os.Stdin.Stat()
|
||||||
|
return stat.Mode()&os.ModeCharDevice == 0
|
||||||
|
}
|
||||||
|
|
||||||
func getStdinLinesOrBlank() chan string {
|
func getStdinLinesOrBlank() chan string {
|
||||||
multi := make(chan string)
|
multi := make(chan string)
|
||||||
if hasStdinLines := writeStdinLinesOrNothing(multi); !hasStdinLines {
|
if hasStdinLines := writeStdinLinesOrNothing(multi); !hasStdinLines {
|
||||||
|
@ -43,7 +49,7 @@ func getStdinLinesOrFirstArgument(c *cli.Context) chan string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeStdinLinesOrNothing(ch chan string) (hasStdinLines bool) {
|
func writeStdinLinesOrNothing(ch chan string) (hasStdinLines bool) {
|
||||||
if stat, _ := os.Stdin.Stat(); stat.Mode()&os.ModeCharDevice == 0 {
|
if isPiped() {
|
||||||
// piped
|
// piped
|
||||||
go func() {
|
go func() {
|
||||||
scanner := bufio.NewScanner(os.Stdin)
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
|
@ -78,6 +84,20 @@ func validateRelayURLs(wsurls []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validate32BytesHex(target string) error {
|
||||||
|
if _, err := hex.DecodeString(target); err != nil {
|
||||||
|
return fmt.Errorf("target '%s' is not valid hex: %s", target, err)
|
||||||
|
}
|
||||||
|
if len(target) != 64 {
|
||||||
|
return fmt.Errorf("expected '%s' to be 64 characters (32 bytes), got %d", target, len(target))
|
||||||
|
}
|
||||||
|
if strings.ToLower(target) != target {
|
||||||
|
return fmt.Errorf("expected target to be all lowercase hex. try again with '%s'", strings.ToLower(target))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func lineProcessingError(c *cli.Context, msg string, args ...any) {
|
func lineProcessingError(c *cli.Context, msg string, args ...any) {
|
||||||
c.Context = context.WithValue(c.Context, LINE_PROCESSING_ERROR, true)
|
c.Context = context.WithValue(c.Context, LINE_PROCESSING_ERROR, true)
|
||||||
fmt.Fprintf(os.Stderr, msg+"\n", args...)
|
fmt.Fprintf(os.Stderr, msg+"\n", args...)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user