mirror of
https://github.com/fiatjaf/nak.git
synced 2025-12-08 16:48:51 +00:00
view: nsec, ncryptsec, event signing things.
This commit is contained in:
1
go.mod
1
go.mod
@@ -20,7 +20,6 @@ require (
|
|||||||
github.com/mattn/go-isatty v0.0.20
|
github.com/mattn/go-isatty v0.0.20
|
||||||
github.com/mattn/go-tty v0.0.7
|
github.com/mattn/go-tty v0.0.7
|
||||||
github.com/mdp/qrterminal/v3 v3.2.1
|
github.com/mdp/qrterminal/v3 v3.2.1
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
|
||||||
github.com/puzpuzpuz/xsync/v3 v3.5.1
|
github.com/puzpuzpuz/xsync/v3 v3.5.1
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
github.com/therecipe/qt v0.0.0-20200904063919-c0c124a5770d
|
github.com/therecipe/qt v0.0.0-20200904063919-c0c124a5770d
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -163,8 +163,6 @@ github.com/mdp/qrterminal/v3 v3.2.1 h1:6+yQjiiOsSuXT5n9/m60E54vdgFsw0zhADHhHLrFe
|
|||||||
github.com/mdp/qrterminal/v3 v3.2.1/go.mod h1:jOTmXvnBsMy5xqLniO0R++Jmjs2sTm9dFSuQ5kpz/SU=
|
github.com/mdp/qrterminal/v3 v3.2.1/go.mod h1:jOTmXvnBsMy5xqLniO0R++Jmjs2sTm9dFSuQ5kpz/SU=
|
||||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
|
||||||
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
|
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
|
||||||
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
|||||||
@@ -48,19 +48,40 @@ func updateEvent() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final := nostr.Event{
|
result := nostr.Event{
|
||||||
Kind: kind,
|
Kind: kind,
|
||||||
Content: event.contentEdit.ToPlainText(),
|
Content: event.contentEdit.ToPlainText(),
|
||||||
CreatedAt: nostr.Timestamp(event.createdAtEdit.DateTime().ToMSecsSinceEpoch() / 1000),
|
CreatedAt: nostr.Timestamp(event.createdAtEdit.DateTime().ToMSecsSinceEpoch() / 1000),
|
||||||
Tags: tags,
|
Tags: tags,
|
||||||
}
|
}
|
||||||
|
|
||||||
if currentKeyer != nil {
|
finalize := func() {
|
||||||
currentKeyer.SignEvent(context.Background(), &final)
|
jsonBytes, _ := json.MarshalIndent(result, "", " ")
|
||||||
|
event.outputEdit.SetPlainText(string(jsonBytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonBytes, _ := json.MarshalIndent(event, "", " ")
|
if currentKeyer != nil {
|
||||||
event.outputEdit.SetPlainText(string(jsonBytes))
|
signAndFinalize := func() {
|
||||||
|
if currentKeyer != nil {
|
||||||
|
if err := currentKeyer.SignEvent(context.Background(), &result); err == nil {
|
||||||
|
finalize()
|
||||||
|
} else {
|
||||||
|
statusLabel.SetText("failed to sign: " + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if currentSec == [32]byte{} {
|
||||||
|
// empty key, we must have a bunker
|
||||||
|
debounced.Call(signAndFinalize)
|
||||||
|
} else {
|
||||||
|
// we have a key, can sign immediately
|
||||||
|
signAndFinalize()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupEventTab() *widgets.QWidget {
|
func setupEventTab() *widgets.QWidget {
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ func handleSecretKeyOrBunker(sec string) (nostr.SecretKey, nostr.Keyer, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if prefix, ski, err := nip19.Decode(sec); err == nil && prefix == "nsec" {
|
if prefix, ski, err := nip19.Decode(sec); err == nil && prefix == "nsec" {
|
||||||
return ski.(nostr.SecretKey), nil, nil
|
sk := ski.(nostr.SecretKey)
|
||||||
|
return sk, keyer.NewPlainKeySigner(sk), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sk, err := nostr.SecretKeyFromHex(sec)
|
sk, err := nostr.SecretKeyFromHex(sec)
|
||||||
|
|||||||
82
view/main.go
82
view/main.go
@@ -1,9 +1,15 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"fiatjaf.com/lib/debouncer"
|
||||||
"fiatjaf.com/nostr"
|
"fiatjaf.com/nostr"
|
||||||
|
"fiatjaf.com/nostr/nip19"
|
||||||
|
"fiatjaf.com/nostr/nip49"
|
||||||
"github.com/therecipe/qt/widgets"
|
"github.com/therecipe/qt/widgets"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -11,6 +17,7 @@ var (
|
|||||||
currentSec nostr.SecretKey
|
currentSec nostr.SecretKey
|
||||||
currentKeyer nostr.Keyer
|
currentKeyer nostr.Keyer
|
||||||
statusLabel *widgets.QLabel
|
statusLabel *widgets.QLabel
|
||||||
|
debounced = debouncer.New(800 * time.Millisecond)
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -29,33 +36,87 @@ func main() {
|
|||||||
// private key input
|
// private key input
|
||||||
secLabel := widgets.NewQLabel2("private key (hex or nsec):", nil, 0)
|
secLabel := widgets.NewQLabel2("private key (hex or nsec):", nil, 0)
|
||||||
mainLayout.AddWidget(secLabel, 0, 0)
|
mainLayout.AddWidget(secLabel, 0, 0)
|
||||||
secEdit := widgets.NewQLineEdit(nil)
|
|
||||||
mainLayout.AddWidget(secEdit, 0, 0)
|
|
||||||
|
|
||||||
secEdit.ConnectTextChanged(func(text string) {
|
secHBox := widgets.NewQHBoxLayout()
|
||||||
|
mainLayout.AddLayout(secHBox, 0)
|
||||||
|
secEdit := widgets.NewQLineEdit(nil)
|
||||||
|
secHBox.AddWidget(secEdit, 0, 0)
|
||||||
|
generateButton := widgets.NewQPushButton2("generate", nil)
|
||||||
|
secHBox.AddWidget(generateButton, 0, 0)
|
||||||
|
|
||||||
|
// password input
|
||||||
|
passwordHBox := widgets.NewQHBoxLayout()
|
||||||
|
passwordWidget := widgets.NewQWidget(nil, 0)
|
||||||
|
passwordWidget.SetLayout(passwordHBox)
|
||||||
|
passwordWidget.SetVisible(false)
|
||||||
|
mainLayout.AddWidget(passwordWidget, 0, 0)
|
||||||
|
passwordLabel := widgets.NewQLabel2("password:", nil, 0)
|
||||||
|
passwordHBox.AddWidget(passwordLabel, 0, 0)
|
||||||
|
secPasswordEdit := widgets.NewQLineEdit(nil)
|
||||||
|
secPasswordEdit.SetEchoMode(widgets.QLineEdit__Password)
|
||||||
|
passwordHBox.AddWidget(secPasswordEdit, 0, 0)
|
||||||
|
keyChanged := func(text string) {
|
||||||
|
text = strings.TrimSpace(text)
|
||||||
|
|
||||||
|
var sk nostr.SecretKey
|
||||||
|
var keyer nostr.Keyer
|
||||||
|
var err error
|
||||||
|
|
||||||
if text == "" {
|
if text == "" {
|
||||||
currentSec = nostr.SecretKey{}
|
passwordWidget.SetVisible(false)
|
||||||
currentKeyer = nil
|
goto empty
|
||||||
statusLabel.SetText("")
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
sk, bunker, err := handleSecretKeyOrBunker(text)
|
|
||||||
|
if strings.HasPrefix(text, "ncryptsec1") {
|
||||||
|
passwordWidget.SetVisible(true)
|
||||||
|
password := secPasswordEdit.Text()
|
||||||
|
if password != "" {
|
||||||
|
sk, err = nip49.Decrypt(text, password)
|
||||||
|
if err != nil {
|
||||||
|
statusLabel.SetText("decryption failed: " + err.Error())
|
||||||
|
goto empty
|
||||||
|
}
|
||||||
|
text = hex.EncodeToString(sk[:])
|
||||||
|
} else {
|
||||||
|
goto empty
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
passwordWidget.SetVisible(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
sk, keyer, err = handleSecretKeyOrBunker(text)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
statusLabel.SetText(err.Error())
|
statusLabel.SetText(err.Error())
|
||||||
currentSec = nostr.SecretKey{}
|
currentSec = nostr.SecretKey{}
|
||||||
currentKeyer = nil
|
currentKeyer = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
currentSec = sk
|
currentSec = sk
|
||||||
currentKeyer = bunker
|
currentKeyer = keyer
|
||||||
statusLabel.SetText("")
|
statusLabel.SetText("")
|
||||||
updateEvent()
|
updateEvent()
|
||||||
|
return
|
||||||
|
|
||||||
|
empty:
|
||||||
|
currentSec = nostr.SecretKey{}
|
||||||
|
currentKeyer = nil
|
||||||
|
statusLabel.SetText("")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
secEdit.ConnectTextChanged(keyChanged)
|
||||||
|
secPasswordEdit.ConnectTextChanged(keyChanged)
|
||||||
|
generateButton.ConnectClicked(func(bool) {
|
||||||
|
sk := nostr.Generate()
|
||||||
|
nsec := nip19.EncodeNsec(sk)
|
||||||
|
secEdit.SetText(nsec)
|
||||||
|
keyChanged(nsec)
|
||||||
})
|
})
|
||||||
|
|
||||||
tabWidget := widgets.NewQTabWidget(nil)
|
tabWidget := widgets.NewQTabWidget(nil)
|
||||||
|
|
||||||
eventTab := setupEventTab()
|
eventTab := setupEventTab()
|
||||||
reqTab := widgets.NewQWidget(nil, 0)
|
reqTab := setupReqTab()
|
||||||
|
|
||||||
tabWidget.AddTab(eventTab, "event")
|
tabWidget.AddTab(eventTab, "event")
|
||||||
tabWidget.AddTab(reqTab, "req")
|
tabWidget.AddTab(reqTab, "req")
|
||||||
@@ -67,6 +128,7 @@ func main() {
|
|||||||
|
|
||||||
// initial render
|
// initial render
|
||||||
updateEvent()
|
updateEvent()
|
||||||
|
updateReq()
|
||||||
|
|
||||||
window.Show()
|
window.Show()
|
||||||
app.Exec()
|
app.Exec()
|
||||||
|
|||||||
Reference in New Issue
Block a user