base64.mx raw
1 package helpers
2
3 const b64encode = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
4
5 // Base64Encode encodes bytes to standard base64.
6 func Base64Encode(data []byte) string {
7 n := len(data)
8 out := []byte{:0:(n+2)/3*4}
9 for i := 0; i < n; i += 3 {
10 var b0, b1, b2 byte
11 b0 = data[i]
12 if i+1 < n {
13 b1 = data[i+1]
14 }
15 if i+2 < n {
16 b2 = data[i+2]
17 }
18 out = append(out, b64encode[(b0>>2)&0x3f])
19 out = append(out, b64encode[((b0<<4)|(b1>>4))&0x3f])
20 if i+1 < n {
21 out = append(out, b64encode[((b1<<2)|(b2>>6))&0x3f])
22 } else {
23 out = append(out, '=')
24 }
25 if i+2 < n {
26 out = append(out, b64encode[b2&0x3f])
27 } else {
28 out = append(out, '=')
29 }
30 }
31 return string(out)
32 }
33
34 // Base64Decode decodes standard base64. Returns nil on invalid input.
35 func Base64Decode(s string) []byte {
36 // Strip padding.
37 n := len(s)
38 pad := 0
39 for n > 0 && s[n-1] == '=' {
40 pad++
41 n--
42 }
43 out := []byte{:0:n*3/4}
44 var acc uint32
45 var bits int
46 for i := 0; i < n; i++ {
47 v := b64val(s[i])
48 if v < 0 {
49 return nil
50 }
51 acc = (acc << 6) | uint32(v)
52 bits += 6
53 if bits >= 8 {
54 bits -= 8
55 out = append(out, byte(acc>>uint(bits)))
56 }
57 }
58 _ = pad
59 return out
60 }
61
62 func b64val(c byte) int {
63 switch {
64 case c >= 'A' && c <= 'Z':
65 return int(c - 'A')
66 case c >= 'a' && c <= 'z':
67 return int(c-'a') + 26
68 case c >= '0' && c <= '9':
69 return int(c-'0') + 52
70 case c == '+':
71 return 62
72 case c == '/':
73 return 63
74 default:
75 return -1
76 }
77 }
78