1
2
3
4
5
6 package base32
7
8 import (
9 "io"
10 "slices"
11 "strconv"
12 )
13
14
17
18
19
20
21
22 type Encoding struct {
23 encode [32]byte
24 decodeMap [256]uint8
25 padChar rune
26 }
27
28 const (
29 StdPadding rune = '='
30 NoPadding rune = -1
31 )
32
33 const (
34 decodeMapInitialize = "" +
35 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
36 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
37 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
38 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
39 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
40 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
41 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
42 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
43 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
44 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
45 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
46 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
47 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
48 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
49 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
50 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
51 invalidIndex = '\xff'
52 )
53
54
55
56
57
58
59
60
61 func NewEncoding(encoder string) *Encoding {
62 if len(encoder) != 32 {
63 panic("encoding alphabet is not 32-bytes long")
64 }
65
66 e := new(Encoding)
67 e.padChar = StdPadding
68 copy(e.encode[:], encoder)
69 copy(e.decodeMap[:], decodeMapInitialize)
70
71 for i := 0; i < len(encoder); i++ {
72
73
74
75 switch {
76 case encoder[i] == '\n' || encoder[i] == '\r':
77 panic("encoding alphabet contains newline character")
78 case e.decodeMap[encoder[i]] != invalidIndex:
79 panic("encoding alphabet includes duplicate symbols")
80 }
81 e.decodeMap[encoder[i]] = uint8(i)
82 }
83 return e
84 }
85
86
87 var StdEncoding = NewEncoding("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567")
88
89
90
91 var HexEncoding = NewEncoding("0123456789ABCDEFGHIJKLMNOPQRSTUV")
92
93
94
95
96
97
98
99
100 func (enc Encoding) WithPadding(padding rune) *Encoding {
101 switch {
102 case padding < NoPadding || padding == '\r' || padding == '\n' || padding > 0xff:
103 panic("invalid padding")
104 case padding != NoPadding && enc.decodeMap[byte(padding)] != invalidIndex:
105 panic("padding contained in alphabet")
106 }
107 enc.padChar = padding
108 return &enc
109 }
110
111
114
115
116
117
118
119
120
121 func (enc *Encoding) Encode(dst, src []byte) {
122 if len(src) == 0 {
123 return
124 }
125
126
127
128 _ = enc.encode
129
130 di, si := 0, 0
131 n := (len(src) / 5) * 5
132 for si < n {
133
134
135 hi := uint32(src[si+0])<<24 | uint32(src[si+1])<<16 | uint32(src[si+2])<<8 | uint32(src[si+3])
136 lo := hi<<8 | uint32(src[si+4])
137
138 dst[di+0] = enc.encode[(hi>>27)&0x1F]
139 dst[di+1] = enc.encode[(hi>>22)&0x1F]
140 dst[di+2] = enc.encode[(hi>>17)&0x1F]
141 dst[di+3] = enc.encode[(hi>>12)&0x1F]
142 dst[di+4] = enc.encode[(hi>>7)&0x1F]
143 dst[di+5] = enc.encode[(hi>>2)&0x1F]
144 dst[di+6] = enc.encode[(lo>>5)&0x1F]
145 dst[di+7] = enc.encode[(lo)&0x1F]
146
147 si += 5
148 di += 8
149 }
150
151
152 remain := len(src) - si
153 if remain == 0 {
154 return
155 }
156
157
158 val := uint32(0)
159 switch remain {
160 case 4:
161 val |= uint32(src[si+3])
162 dst[di+6] = enc.encode[val<<3&0x1F]
163 dst[di+5] = enc.encode[val>>2&0x1F]
164 fallthrough
165 case 3:
166 val |= uint32(src[si+2]) << 8
167 dst[di+4] = enc.encode[val>>7&0x1F]
168 fallthrough
169 case 2:
170 val |= uint32(src[si+1]) << 16
171 dst[di+3] = enc.encode[val>>12&0x1F]
172 dst[di+2] = enc.encode[val>>17&0x1F]
173 fallthrough
174 case 1:
175 val |= uint32(src[si+0]) << 24
176 dst[di+1] = enc.encode[val>>22&0x1F]
177 dst[di+0] = enc.encode[val>>27&0x1F]
178 }
179
180
181 if enc.padChar != NoPadding {
182 nPad := (remain * 8 / 5) + 1
183 for i := nPad; i < 8; i++ {
184 dst[di+i] = byte(enc.padChar)
185 }
186 }
187 }
188
189
190
191 func (enc *Encoding) AppendEncode(dst, src []byte) []byte {
192 n := enc.EncodedLen(len(src))
193 dst = slices.Grow(dst, n)
194 enc.Encode(dst[len(dst):][:n], src)
195 return dst[:len(dst)+n]
196 }
197
198
199 func (enc *Encoding) EncodeToString(src []byte) string {
200 buf := make([]byte, enc.EncodedLen(len(src)))
201 enc.Encode(buf, src)
202 return string(buf)
203 }
204
205 type encoder struct {
206 err error
207 enc *Encoding
208 w io.Writer
209 buf [5]byte
210 nbuf int
211 out [1024]byte
212 }
213
214 func (e *encoder) Write(p []byte) (n int, err error) {
215 if e.err != nil {
216 return 0, e.err
217 }
218
219
220 if e.nbuf > 0 {
221 var i int
222 for i = 0; i < len(p) && e.nbuf < 5; i++ {
223 e.buf[e.nbuf] = p[i]
224 e.nbuf++
225 }
226 n += i
227 p = p[i:]
228 if e.nbuf < 5 {
229 return
230 }
231 e.enc.Encode(e.out[0:], e.buf[0:])
232 if _, e.err = e.w.Write(e.out[0:8]); e.err != nil {
233 return n, e.err
234 }
235 e.nbuf = 0
236 }
237
238
239 for len(p) >= 5 {
240 nn := len(e.out) / 8 * 5
241 if nn > len(p) {
242 nn = len(p)
243 nn -= nn % 5
244 }
245 e.enc.Encode(e.out[0:], p[0:nn])
246 if _, e.err = e.w.Write(e.out[0 : nn/5*8]); e.err != nil {
247 return n, e.err
248 }
249 n += nn
250 p = p[nn:]
251 }
252
253
254 copy(e.buf[:], p)
255 e.nbuf = len(p)
256 n += len(p)
257 return
258 }
259
260
261
262 func (e *encoder) Close() error {
263
264 if e.err == nil && e.nbuf > 0 {
265 e.enc.Encode(e.out[0:], e.buf[0:e.nbuf])
266 encodedLen := e.enc.EncodedLen(e.nbuf)
267 e.nbuf = 0
268 _, e.err = e.w.Write(e.out[0:encodedLen])
269 }
270 return e.err
271 }
272
273
274
275
276
277
278 func NewEncoder(enc *Encoding, w io.Writer) io.WriteCloser {
279 return &encoder{enc: enc, w: w}
280 }
281
282
283
284 func (enc *Encoding) EncodedLen(n int) int {
285 if enc.padChar == NoPadding {
286 return n/5*8 + (n%5*8+4)/5
287 }
288 return (n + 4) / 5 * 8
289 }
290
291
294
295 type CorruptInputError int64
296
297 func (e CorruptInputError) Error() string {
298 return "illegal base32 data at input byte " + strconv.FormatInt(int64(e), 10)
299 }
300
301
302
303
304
305 func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
306
307 _ = enc.decodeMap
308
309 dsti := 0
310 olen := len(src)
311
312 for len(src) > 0 && !end {
313
314 var dbuf [8]byte
315 dlen := 8
316
317 for j := 0; j < 8; {
318
319 if len(src) == 0 {
320 if enc.padChar != NoPadding {
321
322 return n, false, CorruptInputError(olen - len(src) - j)
323 }
324
325 dlen, end = j, true
326 break
327 }
328 in := src[0]
329 src = src[1:]
330 if in == byte(enc.padChar) && j >= 2 && len(src) < 8 {
331
332 if len(src)+j < 8-1 {
333
334 return n, false, CorruptInputError(olen)
335 }
336 for k := 0; k < 8-1-j; k++ {
337 if len(src) > k && src[k] != byte(enc.padChar) {
338
339 return n, false, CorruptInputError(olen - len(src) + k - 1)
340 }
341 }
342 dlen, end = j, true
343
344
345
346
347
348 if dlen == 1 || dlen == 3 || dlen == 6 {
349 return n, false, CorruptInputError(olen - len(src) - 1)
350 }
351 break
352 }
353 dbuf[j] = enc.decodeMap[in]
354 if dbuf[j] == 0xFF {
355 return n, false, CorruptInputError(olen - len(src) - 1)
356 }
357 j++
358 }
359
360
361
362 switch dlen {
363 case 8:
364 dst[dsti+4] = dbuf[6]<<5 | dbuf[7]
365 n++
366 fallthrough
367 case 7:
368 dst[dsti+3] = dbuf[4]<<7 | dbuf[5]<<2 | dbuf[6]>>3
369 n++
370 fallthrough
371 case 5:
372 dst[dsti+2] = dbuf[3]<<4 | dbuf[4]>>1
373 n++
374 fallthrough
375 case 4:
376 dst[dsti+1] = dbuf[1]<<6 | dbuf[2]<<1 | dbuf[3]>>4
377 n++
378 fallthrough
379 case 2:
380 dst[dsti+0] = dbuf[0]<<3 | dbuf[1]>>2
381 n++
382 }
383 dsti += 5
384 }
385 return n, end, nil
386 }
387
388
389
390
391
392
393 func (enc *Encoding) Decode(dst, src []byte) (n int, err error) {
394 buf := make([]byte, len(src))
395 l := stripNewlines(buf, src)
396 n, _, err = enc.decode(dst, buf[:l])
397 return
398 }
399
400
401
402
403 func (enc *Encoding) AppendDecode(dst, src []byte) ([]byte, error) {
404
405 n := len(src)
406 for n > 0 && rune(src[n-1]) == enc.padChar {
407 n--
408 }
409 n = decodedLen(n, NoPadding)
410
411 dst = slices.Grow(dst, n)
412 n, err := enc.Decode(dst[len(dst):][:n], src)
413 return dst[:len(dst)+n], err
414 }
415
416
417 func (enc *Encoding) DecodeString(s string) ([]byte, error) {
418 buf := []byte(s)
419 l := stripNewlines(buf, buf)
420 n, _, err := enc.decode(buf, buf[:l])
421 return buf[:n], err
422 }
423
424 type decoder struct {
425 err error
426 enc *Encoding
427 r io.Reader
428 end bool
429 buf [1024]byte
430 nbuf int
431 out []byte
432 outbuf [1024 / 8 * 5]byte
433 }
434
435 func readEncodedData(r io.Reader, buf []byte, min int, expectsPadding bool) (n int, err error) {
436 for n < min && err == nil {
437 var nn int
438 nn, err = r.Read(buf[n:])
439 n += nn
440 }
441
442 if n < min && n > 0 && err == io.EOF {
443 err = io.ErrUnexpectedEOF
444 }
445
446
447
448 if expectsPadding && min < 8 && n == 0 && err == io.EOF {
449 err = io.ErrUnexpectedEOF
450 }
451 return
452 }
453
454 func (d *decoder) Read(p []byte) (n int, err error) {
455
456 if len(d.out) > 0 {
457 n = copy(p, d.out)
458 d.out = d.out[n:]
459 if len(d.out) == 0 {
460 return n, d.err
461 }
462 return n, nil
463 }
464
465 if d.err != nil {
466 return 0, d.err
467 }
468
469
470 nn := (len(p) + 4) / 5 * 8
471 if nn < 8 {
472 nn = 8
473 }
474 if nn > len(d.buf) {
475 nn = len(d.buf)
476 }
477
478
479 var min int
480 var expectsPadding bool
481 if d.enc.padChar == NoPadding {
482 min = 1
483 expectsPadding = false
484 } else {
485 min = 8 - d.nbuf
486 expectsPadding = true
487 }
488
489 nn, d.err = readEncodedData(d.r, d.buf[d.nbuf:nn], min, expectsPadding)
490 d.nbuf += nn
491 if d.nbuf < min {
492 return 0, d.err
493 }
494 if nn > 0 && d.end {
495 return 0, CorruptInputError(0)
496 }
497
498
499 var nr int
500 if d.enc.padChar == NoPadding {
501 nr = d.nbuf
502 } else {
503 nr = d.nbuf / 8 * 8
504 }
505 nw := d.enc.DecodedLen(d.nbuf)
506
507 if nw > len(p) {
508 nw, d.end, err = d.enc.decode(d.outbuf[0:], d.buf[0:nr])
509 d.out = d.outbuf[0:nw]
510 n = copy(p, d.out)
511 d.out = d.out[n:]
512 } else {
513 n, d.end, err = d.enc.decode(p, d.buf[0:nr])
514 }
515 d.nbuf -= nr
516 for i := 0; i < d.nbuf; i++ {
517 d.buf[i] = d.buf[i+nr]
518 }
519
520 if err != nil && (d.err == nil || d.err == io.EOF) {
521 d.err = err
522 }
523
524 if len(d.out) > 0 {
525
526
527
528
529 return n, nil
530 }
531
532 return n, d.err
533 }
534
535 type newlineFilteringReader struct {
536 wrapped io.Reader
537 }
538
539
540
541 func stripNewlines(dst, src []byte) int {
542 offset := 0
543 for _, b := range src {
544 if b == '\r' || b == '\n' {
545 continue
546 }
547 dst[offset] = b
548 offset++
549 }
550 return offset
551 }
552
553 func (r *newlineFilteringReader) Read(p []byte) (int, error) {
554 n, err := r.wrapped.Read(p)
555 for n > 0 {
556 s := p[0:n]
557 offset := stripNewlines(s, s)
558 if err != nil || offset > 0 {
559 return offset, err
560 }
561
562 n, err = r.wrapped.Read(p)
563 }
564 return n, err
565 }
566
567
568 func NewDecoder(enc *Encoding, r io.Reader) io.Reader {
569 return &decoder{enc: enc, r: &newlineFilteringReader{r}}
570 }
571
572
573
574 func (enc *Encoding) DecodedLen(n int) int {
575 return decodedLen(n, enc.padChar)
576 }
577
578 func decodedLen(n int, padChar rune) int {
579 if padChar == NoPadding {
580 return n/8*5 + n%8*5/8
581 }
582 return n / 8 * 5
583 }
584
View as plain text