bech32.go raw
1 // Package bech32 encodes and decodes segwit addresses.
2 //
3 // It implements only the part a swap wallet needs: P2WPKH and P2WSH, which are witness
4 // version 0 and therefore the original BIP173 checksum. A future witness version needs the
5 // BIP350 checksum instead, so this package refuses any version but 0 rather than encoding
6 // an address another wallet would reject.
7 package bech32
8
9 import (
10 "fmt"
11 "strings"
12 )
13
14 // charset is the bech32 alphabet, in the order the checksum depends on.
15 const charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
16
17 // reverse maps a character to its value, built once.
18 var reverse = func() map[byte]int {
19 out := make(map[byte]int, len(charset))
20
21 for i := 0; i < len(charset); i++ {
22 out[charset[i]] = i
23 }
24
25 return out
26 }()
27
28 // generator holds the bech32 checksum constants.
29 var generator = [5]uint32{0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3}
30
31 // polymod is the bech32 checksum function.
32 func polymod(values []int) uint32 {
33 checksum := uint32(1)
34
35 for _, value := range values {
36 top := checksum >> 25
37 checksum = (checksum&0x1ffffff)<<5 ^ uint32(value)
38
39 for i := 0; i < 5; i++ {
40 if (top>>uint(i))&1 == 1 {
41 checksum ^= generator[i]
42 }
43 }
44 }
45
46 return checksum
47 }
48
49 // expandHRP spreads the human-readable part into the values the checksum covers.
50 func expandHRP(hrp string) []int {
51 out := make([]int, 0, len(hrp)*2+1)
52
53 for i := 0; i < len(hrp); i++ {
54 out = append(out, int(hrp[i])>>5)
55 }
56
57 out = append(out, 0)
58
59 for i := 0; i < len(hrp); i++ {
60 out = append(out, int(hrp[i])&31)
61 }
62
63 return out
64 }
65
66 // convertBits regroups a byte slice into 5-bit groups, or back.
67 func convertBits(data []byte, from, to uint, pad bool) ([]int, error) {
68 acc := uint32(0)
69 bits := uint(0)
70 maxValue := uint32(1)<<to - 1
71
72 var out []int
73
74 for _, value := range data {
75 if uint32(value)>>from != 0 {
76 return nil, fmt.Errorf("value %d does not fit in %d bits", value, from)
77 }
78
79 acc = acc<<from | uint32(value)
80 bits += from
81
82 for bits >= to {
83 bits -= to
84 out = append(out, int((acc>>bits)&maxValue))
85 }
86 }
87
88 if pad {
89 if bits > 0 {
90 out = append(out, int((acc<<(to-bits))&maxValue))
91 }
92
93 return out, nil
94 }
95
96 if bits >= from {
97 return nil, fmt.Errorf("excess padding")
98 }
99
100 if (acc<<(to-bits))&maxValue != 0 {
101 return nil, fmt.Errorf("non-zero padding")
102 }
103
104 return out, nil
105 }
106
107 // Encode turns a human-readable part and a payload into a bech32 string with the BIP173
108 // checksum.
109 func Encode(hrp string, data []int) (string, error) {
110 if hrp == "" {
111 return "", fmt.Errorf("a bech32 string needs a human-readable part")
112 }
113
114 for i := 0; i < len(hrp); i++ {
115 if hrp[i] < 33 || hrp[i] > 126 {
116 return "", fmt.Errorf("the human-readable part contains %q", hrp[i])
117 }
118
119 if hrp[i] >= 'A' && hrp[i] <= 'Z' {
120 return "", fmt.Errorf("the human-readable part must be lowercase")
121 }
122 }
123
124 values := append(expandHRP(hrp), data...)
125 values = append(values, 0, 0, 0, 0, 0, 0)
126
127 checksum := polymod(values) ^ 1
128
129 var out strings.Builder
130
131 out.WriteString(hrp)
132 out.WriteByte('1')
133
134 for _, value := range data {
135 out.WriteByte(charset[value])
136 }
137
138 for i := 0; i < 6; i++ {
139 out.WriteByte(charset[(checksum>>uint(5*(5-i)))&31])
140 }
141
142 return out.String(), nil
143 }
144
145 // Decode splits a bech32 string into its human-readable part and payload values.
146 func Decode(text string) (string, []int, error) {
147 if len(text) < 8 {
148 return "", nil, fmt.Errorf("a bech32 string is at least 8 characters")
149 }
150
151 if len(text) > 90 {
152 return "", nil, fmt.Errorf("a bech32 address is at most 90 characters, not %d",
153 len(text))
154 }
155
156 // Mixed case is not valid: the checksum is defined over one case, and accepting both
157 // would let two different strings be the same address.
158 lower := strings.ToLower(text)
159
160 if lower != text && strings.ToUpper(text) != text {
161 return "", nil, fmt.Errorf("a bech32 string may not mix upper and lower case")
162 }
163
164 text = lower
165
166 separator := strings.LastIndexByte(text, '1')
167
168 if separator < 1 || separator+7 > len(text) {
169 return "", nil, fmt.Errorf("a bech32 string needs a separator and a checksum")
170 }
171
172 hrp := text[:separator]
173 data := make([]int, 0, len(text)-separator-1)
174
175 for i := separator + 1; i < len(text); i++ {
176 value, ok := reverse[text[i]]
177
178 if !ok {
179 return "", nil, fmt.Errorf("%q is not a bech32 character", text[i])
180 }
181
182 data = append(data, value)
183 }
184
185 if polymod(append(expandHRP(hrp), data...)) != 1 {
186 return "", nil, fmt.Errorf("the bech32 checksum does not match")
187 }
188
189 return hrp, data[:len(data)-6], nil
190 }
191
192 // EncodeSegwit builds a witness version 0 address: P2WPKH for a 20-byte program, P2WSH for
193 // a 32-byte one.
194 func EncodeSegwit(hrp string, version byte, program []byte) (string, error) {
195 if version != 0 {
196 return "", fmt.Errorf(
197 "this wallet encodes witness version 0 only; version %d needs the BIP350 "+
198 "checksum", version,
199 )
200 }
201
202 if len(program) != 20 && len(program) != 32 {
203 return "", fmt.Errorf(
204 "a witness version 0 program is 20 or 32 bytes, not %d", len(program),
205 )
206 }
207
208 grouped, err := convertBits(program, 8, 5, true)
209
210 if err != nil {
211 return "", err
212 }
213
214 return Encode(hrp, append([]int{int(version)}, grouped...))
215 }
216
217 // DecodeSegwit reads a witness address and returns its version and program.
218 func DecodeSegwit(address string) (string, byte, []byte, error) {
219 hrp, data, err := Decode(address)
220
221 if err != nil {
222 return "", 0, nil, err
223 }
224
225 if len(data) < 1 {
226 return "", 0, nil, fmt.Errorf("the address has no witness version")
227 }
228
229 if data[0] != 0 {
230 return "", 0, nil, fmt.Errorf(
231 "this wallet reads witness version 0 only; the address is version %d", data[0],
232 )
233 }
234
235 program, err := convertBits(intsToBytes(data[1:]), 5, 8, false)
236
237 if err != nil {
238 return "", 0, nil, err
239 }
240
241 if len(program) != 20 && len(program) != 32 {
242 return "", 0, nil, fmt.Errorf("the witness program is %d bytes", len(program))
243 }
244
245 out := make([]byte, len(program))
246
247 for i, value := range program {
248 out[i] = byte(value)
249 }
250
251 return hrp, 0, out, nil
252 }
253
254 // intsToBytes narrows the 5-bit values into a byte slice.
255 func intsToBytes(values []int) []byte {
256 out := make([]byte, len(values))
257
258 for i, value := range values {
259 out[i] = byte(value)
260 }
261
262 return out
263 }
264