summaryrefslogtreecommitdiffstats
path: root/bech32_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'bech32_test.go')
-rw-r--r--bech32_test.go139
1 files changed, 139 insertions, 0 deletions
diff --git a/bech32_test.go b/bech32_test.go
new file mode 100644
index 0000000..fb1260b
--- /dev/null
+++ b/bech32_test.go
@@ -0,0 +1,139 @@
1package nostr
2
3import (
4 "bytes"
5 "encoding/hex"
6 "testing"
7)
8
9func TestBech32Encode(t *testing.T) {
10 // Test vector: 32 bytes of data
11 data, _ := hex.DecodeString("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef")
12
13 encoded, err := Bech32Encode("npub", data)
14 if err != nil {
15 t.Fatalf("Bech32Encode() error = %v", err)
16 }
17
18 if encoded[:5] != "npub1" {
19 t.Errorf("Encoded string should start with 'npub1', got %s", encoded[:5])
20 }
21
22 // Decode it back
23 hrp, decoded, err := Bech32Decode(encoded)
24 if err != nil {
25 t.Fatalf("Bech32Decode() error = %v", err)
26 }
27
28 if hrp != "npub" {
29 t.Errorf("HRP = %s, want npub", hrp)
30 }
31
32 if !bytes.Equal(decoded, data) {
33 t.Errorf("Round-trip failed: got %x, want %x", decoded, data)
34 }
35}
36
37func TestBech32EncodeNsec(t *testing.T) {
38 data, _ := hex.DecodeString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef")
39
40 encoded, err := Bech32Encode("nsec", data)
41 if err != nil {
42 t.Fatalf("Bech32Encode() error = %v", err)
43 }
44
45 if encoded[:5] != "nsec1" {
46 t.Errorf("Encoded string should start with 'nsec1', got %s", encoded[:5])
47 }
48
49 // Decode it back
50 hrp, decoded, err := Bech32Decode(encoded)
51 if err != nil {
52 t.Fatalf("Bech32Decode() error = %v", err)
53 }
54
55 if hrp != "nsec" {
56 t.Errorf("HRP = %s, want nsec", hrp)
57 }
58
59 if !bytes.Equal(decoded, data) {
60 t.Errorf("Round-trip failed")
61 }
62}
63
64func TestBech32DecodeErrors(t *testing.T) {
65 tests := []struct {
66 name string
67 input string
68 }{
69 {"no separator", "npubabcdef"},
70 {"empty data", "npub1"},
71 {"invalid character", "npub1o"}, // 'o' is not in bech32 alphabet
72 {"invalid checksum", "npub1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpqqqqq"},
73 }
74
75 for _, tt := range tests {
76 t.Run(tt.name, func(t *testing.T) {
77 _, _, err := Bech32Decode(tt.input)
78 if err == nil {
79 t.Error("Bech32Decode() expected error, got nil")
80 }
81 })
82 }
83}
84
85func TestBech32KnownVectors(t *testing.T) {
86 // Test with known nostr npub/nsec values
87 // These can be verified with other nostr tools
88
89 // Generate a key and verify round-trip
90 key, err := GenerateKey()
91 if err != nil {
92 t.Fatalf("GenerateKey() error = %v", err)
93 }
94
95 npub := key.Npub()
96 nsec := key.Nsec()
97
98 // Verify npub decodes to public key
99 hrp, pubBytes, err := Bech32Decode(npub)
100 if err != nil {
101 t.Fatalf("Bech32Decode(npub) error = %v", err)
102 }
103 if hrp != "npub" {
104 t.Errorf("npub HRP = %s, want npub", hrp)
105 }
106 if hex.EncodeToString(pubBytes) != key.Public() {
107 t.Error("npub does not decode to correct public key")
108 }
109
110 // Verify nsec decodes to private key
111 hrp, privBytes, err := Bech32Decode(nsec)
112 if err != nil {
113 t.Fatalf("Bech32Decode(nsec) error = %v", err)
114 }
115 if hrp != "nsec" {
116 t.Errorf("nsec HRP = %s, want nsec", hrp)
117 }
118 if hex.EncodeToString(privBytes) != key.Private() {
119 t.Error("nsec does not decode to correct private key")
120 }
121}
122
123func TestBech32CaseInsensitive(t *testing.T) {
124 data, _ := hex.DecodeString("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef")
125 encoded, _ := Bech32Encode("npub", data)
126
127 // Test uppercase
128 upper := "NPUB1" + encoded[5:]
129 hrp, decoded, err := Bech32Decode(upper)
130 if err != nil {
131 t.Fatalf("Bech32Decode(uppercase) error = %v", err)
132 }
133 if hrp != "npub" {
134 t.Errorf("HRP = %s, want npub", hrp)
135 }
136 if !bytes.Equal(decoded, data) {
137 t.Error("Uppercase decode failed")
138 }
139}