nws/protocol/signer.go

94 lines
3.1 KiB
Go
Raw Normal View History

2024-07-22 21:00:21 +00:00
package protocol
import (
2024-08-02 08:56:54 +00:00
"fmt"
"log/slog"
2024-07-22 21:00:21 +00:00
"github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip04"
)
// KindEphemeralEvent represents the unique identifier for ephemeral events.
2024-08-02 15:54:18 +00:00
const KindEphemeralEvent int = 28333
// KindAnnouncementEvent represents the unique identifier for announcement events.
const KindAnnouncementEvent int = 38333
// KindCertificateEvent represents the unique identifier for certificate events.
const KindCertificateEvent int = 38334
// KindPrivateKeyEvent represents the unique identifier for private key events.
const KindPrivateKeyEvent int = 38335
2024-07-22 21:00:21 +00:00
// EventSigner represents a signer that can create and sign events.
//
2024-07-26 19:21:50 +00:00
// EventSigner provides methods for creating unsigned events, creating signed events
2024-07-22 21:00:21 +00:00
type EventSigner struct {
PublicKey string
privateKey string
}
// NewEventSigner creates a new EventSigner
func NewEventSigner(privateKey string) (*EventSigner, error) {
myPublicKey, err := nostr.GetPublicKey(privateKey)
if err != nil {
slog.Error("could not generate pubkey")
2024-08-02 08:56:54 +00:00
return nil, fmt.Errorf("could not generate public key: %w", err)
2024-07-22 21:00:21 +00:00
}
signer := &EventSigner{
privateKey: privateKey,
PublicKey: myPublicKey,
}
return signer, nil
}
// CreateEvent creates a new Event with the provided tags. The Public Key and the
2024-08-02 08:56:54 +00:00
// current timestamp are set automatically. The Kind is set to KindEphemeralEvent
func (s *EventSigner) CreateEvent(kind int, tags nostr.Tags) nostr.Event {
2024-07-22 21:00:21 +00:00
return nostr.Event{
PubKey: s.PublicKey,
CreatedAt: nostr.Now(),
Kind: kind,
2024-07-22 21:00:21 +00:00
Tags: tags,
}
}
// CreateSignedEvent creates a signed Nostr event with the provided target public key, tags, and options.
// It computes the shared key between the target public key and the private key of the EventSigner.
// Then, it creates a new message with the provided options.
// The message is serialized to JSON and encrypted using the shared key.
// The method then calls CreateEvent to create a new unsigned event with the provided tags.
// The encrypted message is set as the content of the event.
// Finally, the event is signed with the private key of the EventSigner, setting the event ID and event Sig fields.
2024-08-02 08:56:54 +00:00
// The signed event is returned along with any error that occurs
func (s *EventSigner) CreateSignedEvent(
targetPublicKey string,
kind int,
tags nostr.Tags,
opts ...MessageOption,
) (nostr.Event, error) {
2024-07-22 21:00:21 +00:00
sharedKey, err := nip04.ComputeSharedSecret(targetPublicKey, s.privateKey)
if err != nil {
2024-08-02 08:56:54 +00:00
return nostr.Event{}, fmt.Errorf("could not compute shared key: %w", err)
2024-07-22 21:00:21 +00:00
}
message := NewMessage(
opts...,
)
2024-08-02 08:56:54 +00:00
messageJSON, err := MarshalJSON(message)
if err != nil {
return nostr.Event{}, fmt.Errorf("could not marshal message: %w", err)
}
encryptedMessage, err := nip04.Encrypt(string(messageJSON), sharedKey)
2024-07-22 21:00:21 +00:00
if err != nil {
2024-08-02 08:56:54 +00:00
return nostr.Event{}, fmt.Errorf("could not encrypt message: %w", err)
2024-07-22 21:00:21 +00:00
}
2024-08-02 08:56:54 +00:00
event := s.CreateEvent(kind, tags)
event.Content = encryptedMessage
2024-07-22 21:00:21 +00:00
// calling Sign sets the event ID field and the event Sig field
2024-08-02 08:56:54 +00:00
err = event.Sign(s.privateKey)
2024-07-22 21:00:21 +00:00
if err != nil {
2024-08-02 08:56:54 +00:00
return nostr.Event{}, fmt.Errorf("could not sign event: %w", err)
2024-07-22 21:00:21 +00:00
}
2024-08-02 08:56:54 +00:00
return event, nil
2024-07-22 21:00:21 +00:00
}