forked from keys-pub/keys
-
Notifications
You must be signed in to change notification settings - Fork 0
/
encode.go
202 lines (181 loc) · 4.42 KB
/
encode.go
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
// Package encoding provides encoding and decoding of different formats like Base62, Saltpack, BIP39.
package encoding
import (
stdencoding "encoding"
"encoding/base32"
"encoding/base64"
"encoding/hex"
"strings"
"github.com/keybase/saltpack/encoding/basex"
"github.com/pkg/errors"
)
// TextMarshaler alias for encoding.TextMarshaler.
type TextMarshaler = stdencoding.TextMarshaler
// Encoding is an encoding for bytes to and from a string
type Encoding string
const (
// NoEncoding ...
NoEncoding Encoding = ""
// Hex (Base16) encoding
Hex Encoding = "base16"
// Base32 encoding
Base32 Encoding = "base32"
// Base58 encoding
Base58 Encoding = "base58"
// Base62 encoding
Base62 Encoding = "base62"
// Base64 encoding (with padding)
Base64 Encoding = "base64"
// Saltpack encoding
Saltpack Encoding = "saltpack"
// BIP39 encoding
BIP39 Encoding = "bip39"
)
// NewEncoding returns an Encoding from a string.
func NewEncoding(s string) Encoding {
enc, err := Parse(s)
if err != nil {
panic(err)
}
return enc
}
// Parse returns an Encoding from a string.
func Parse(s string) (Encoding, error) {
switch s {
case string(Hex):
return Hex, nil
case string(Base32):
return Base32, nil
case string(Base58):
return Base58, nil
case string(Base62):
return Base62, nil
case string(Base64):
return Base64, nil
case string(Saltpack):
return Saltpack, nil
case string(BIP39):
return BIP39, nil
case string(NoEncoding):
return NoEncoding, nil
default:
return NoEncoding, errors.Errorf("invalid encoding %s", s)
}
}
// ParseOr returns an Encoding from a string, or if empty, a default.
func ParseOr(s string, d Encoding) (Encoding, error) {
if s == "" {
return d, nil
}
return Parse(s)
}
// Encode encodes bytes to an Encoding.
func Encode(b []byte, encoding Encoding, opt ...EncodeOption) (string, error) {
opts, err := newEncodeOptions(opt, encoding)
if err != nil {
return "", err
}
switch encoding {
case Base64:
encoder := base64.StdEncoding
if opts.NoPadding {
encoder = base64.RawStdEncoding
}
return encoder.EncodeToString(b), nil
case Base62:
return basex.Base62StdEncodingStrict.EncodeToString(b), nil
case Base58:
return basex.Base58StdEncodingStrict.EncodeToString(b), nil
case Base32:
encoder := base32.StdEncoding
if opts.NoPadding {
encoder = encoder.WithPadding(base32.NoPadding)
}
out := encoder.EncodeToString(b)
if opts.Lowercase {
out = strings.ToLower(out)
}
return out, nil
case Hex:
return hex.EncodeToString(b), nil
case Saltpack:
return encodeSaltpack(b), nil
case BIP39:
return BytesToPhrase(b)
default:
return "", errors.Errorf("unrecognized encoding")
}
}
// MustEncode returns encoding or panics on error.
func MustEncode(b []byte, encoding Encoding, opt ...EncodeOption) string {
s, err := Encode(b, encoding, opt...)
if err != nil {
panic(err)
}
return s
}
// Decode decodes string to bytes using encoding
func Decode(s string, encoding Encoding) ([]byte, error) {
switch encoding {
case Base64:
return base64.StdEncoding.DecodeString(s)
case Base62:
return basex.Base62StdEncodingStrict.DecodeString(s)
case Base58:
return basex.Base58StdEncodingStrict.DecodeString(s)
case Base32:
return base32.StdEncoding.DecodeString(s)
case Hex:
return hex.DecodeString(s)
case Saltpack:
return decodeSaltpack(s)
case BIP39:
b, err := PhraseToBytes(s, true)
if err != nil {
return nil, err
}
return b[:], nil
default:
return nil, errors.Errorf("unknown encoding")
}
}
// MustDecode decodes or panics.
func MustDecode(s string, encoding Encoding) []byte {
b, err := Decode(s, encoding)
if err != nil {
panic(err)
}
return b
}
// DecodeHex decode base16 (hex).
func DecodeHex(s string) ([]byte, error) {
return Decode(s, Hex)
}
// EncodeHex encode base16 (hex).
func EncodeHex(b []byte) string {
return MustEncode(b, Hex)
}
// DecodeBase32 decode base32.
func DecodeBase32(s string) ([]byte, error) {
return Decode(s, Base32)
}
// EncodeBase32 encode base32.
func EncodeBase32(b []byte) string {
return MustEncode(b, Base32)
}
// DecodeBase62 decode base62.
func DecodeBase62(s string) ([]byte, error) {
return Decode(s, Base62)
}
// EncodeBase62 encode base62.
func EncodeBase62(b []byte) string {
return MustEncode(b, Base62)
}
// DecodeBase64 decode base64.
func DecodeBase64(s string) ([]byte, error) {
return Decode(s, Base64)
}
// EncodeBase64 encode base64.
func EncodeBase64(b []byte) string {
return MustEncode(b, Base64)
}