first commit
This commit is contained in:
87
internal/dm/encrypt.go
Normal file
87
internal/dm/encrypt.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package dm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
gn "github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/keyer"
|
||||
"github.com/nbd-wtf/go-nostr/nip04"
|
||||
"github.com/nbd-wtf/go-nostr/nip59"
|
||||
)
|
||||
|
||||
var ErrUnsupportedKind = errors.New("unsupported DM kind")
|
||||
|
||||
// BuildEvent builds the kind-4 or kind-1059 event(s) for a DM.
|
||||
// For kind 1059 it returns the gift wrap addressed to the recipient.
|
||||
// For kind 4 it returns a single signed event.
|
||||
func BuildEvent(kind int, senderSk, recipientHex, content string) ([]gn.Event, error) {
|
||||
switch kind {
|
||||
case 4:
|
||||
return buildNip04(senderSk, recipientHex, content)
|
||||
case 1059:
|
||||
return buildNip17(senderSk, recipientHex, content)
|
||||
default:
|
||||
return nil, fmt.Errorf("%w: %d", ErrUnsupportedKind, kind)
|
||||
}
|
||||
}
|
||||
|
||||
func buildNip04(sk, recipient, content string) ([]gn.Event, error) {
|
||||
shared, err := nip04.ComputeSharedSecret(recipient, sk)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("nip04 shared: %w", err)
|
||||
}
|
||||
enc, err := nip04.Encrypt(content, shared)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("nip04 encrypt: %w", err)
|
||||
}
|
||||
pk, err := gn.GetPublicKey(sk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ev := gn.Event{
|
||||
PubKey: pk,
|
||||
CreatedAt: gn.Now(),
|
||||
Kind: 4,
|
||||
Tags: gn.Tags{{"p", recipient}},
|
||||
Content: enc,
|
||||
}
|
||||
if err := ev.Sign(sk); err != nil {
|
||||
return nil, fmt.Errorf("sign: %w", err)
|
||||
}
|
||||
return []gn.Event{ev}, nil
|
||||
}
|
||||
|
||||
func buildNip17(sk, recipient, content string) ([]gn.Event, error) {
|
||||
ks, err := keyer.NewPlainKeySigner(sk)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("keyer: %w", err)
|
||||
}
|
||||
ctx := context.Background()
|
||||
ourPubkey, err := ks.GetPublicKey(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rumor := gn.Event{
|
||||
Kind: gn.KindDirectMessage,
|
||||
Content: content,
|
||||
Tags: gn.Tags{{"p", recipient}},
|
||||
CreatedAt: gn.Now(),
|
||||
PubKey: ourPubkey,
|
||||
}
|
||||
rumor.ID = rumor.GetID()
|
||||
|
||||
wrap, err := nip59.GiftWrap(
|
||||
rumor,
|
||||
recipient,
|
||||
func(s string) (string, error) { return ks.Encrypt(ctx, s, recipient) },
|
||||
func(e *gn.Event) error { return ks.SignEvent(ctx, e) },
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("nip17 giftwrap: %w", err)
|
||||
}
|
||||
return []gn.Event{wrap}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user