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