p8k.mx raw
1 // Package p8k provides a signer.I implementation using the secp256k1/schnorr packages.
2 package p8k
3
4 import (
5 "crypto/sha256"
6 "fmt"
7
8 "smesh.lol/pkg/nostr/ec/secp256k1"
9 "smesh.lol/pkg/nostr/ec/schnorr"
10 "smesh.lol/pkg/nostr/signer"
11 )
12
13 type Signer struct {
14 sec *secp256k1.SecretKey
15 pub *secp256k1.PublicKey
16 }
17
18 var _ signer.I = (*Signer)(nil)
19
20 func New() (*Signer, error) {
21 return &Signer{}, nil
22 }
23
24 func MustNew() *Signer {
25 return &Signer{}
26 }
27
28 func (s *Signer) Generate() error {
29 sk, err := secp256k1.GenerateSecretKey()
30 if err != nil {
31 return err
32 }
33 s.sec = sk
34 s.pub = sk.PubKey()
35 return nil
36 }
37
38 func (s *Signer) InitSec(sec []byte) error {
39 sk := secp256k1.SecKeyFromBytes(sec)
40 if sk == nil {
41 return fmt.Errorf("invalid secret key")
42 }
43 s.sec = sk
44 s.pub = sk.PubKey()
45 return nil
46 }
47
48 func (s *Signer) InitPub(pub []byte) error {
49 pk, err := schnorr.ParsePubKey(pub)
50 if err != nil {
51 return err
52 }
53 s.pub = pk
54 return nil
55 }
56
57 func (s *Signer) Sec() []byte {
58 if s.sec == nil {
59 return nil
60 }
61 return s.sec.Serialize()
62 }
63
64 func (s *Signer) Pub() []byte {
65 if s.pub == nil {
66 return nil
67 }
68 return schnorr.SerializePubKey(s.pub)
69 }
70
71 func (s *Signer) Sign(msg []byte) ([]byte, error) {
72 if s.sec == nil {
73 return nil, fmt.Errorf("no secret key")
74 }
75 sig, err := schnorr.Sign(s.sec, msg)
76 if err != nil {
77 return nil, err
78 }
79 return sig.Serialize(), nil
80 }
81
82 func (s *Signer) Verify(msg, sig []byte) (bool, error) {
83 if s.pub == nil {
84 return false, fmt.Errorf("no public key")
85 }
86 parsed, err := schnorr.ParseSignature(sig)
87 if err != nil {
88 return false, err
89 }
90 return parsed.Verify(msg, s.pub), nil
91 }
92
93 func (s *Signer) Zero() {
94 if s.sec != nil {
95 s.sec.Zero()
96 s.sec = nil
97 }
98 s.pub = nil
99 }
100
101 func (s *Signer) ECDH(pub []byte) ([]byte, error) {
102 raw, err := s.ECDHRaw(pub)
103 if err != nil {
104 return nil, err
105 }
106 h := sha256.Sum256(raw)
107 return h[:], nil
108 }
109
110 func (s *Signer) ECDHRaw(pub []byte) ([]byte, error) {
111 if s.sec == nil {
112 return nil, fmt.Errorf("no secret key")
113 }
114 pk, err := schnorr.ParsePubKey(pub)
115 if err != nil {
116 return nil, err
117 }
118 return secp256k1.GenerateSharedSecret(s.sec, pk), nil
119 }
120