2016-08-22 17:37:43 -07:00
|
|
|
package multibase
|
|
|
|
|
|
|
|
|
|
import (
|
2016-11-27 23:56:23 +01:00
|
|
|
"encoding/base64"
|
2016-12-21 20:42:49 +01:00
|
|
|
"encoding/hex"
|
2016-08-22 17:37:43 -07:00
|
|
|
"fmt"
|
|
|
|
|
|
|
|
|
|
b58 "github.com/jbenet/go-base58"
|
2016-11-27 23:56:23 +01:00
|
|
|
b32 "github.com/whyrusleeping/base32"
|
2016-08-22 17:37:43 -07:00
|
|
|
)
|
|
|
|
|
|
2016-12-21 20:42:49 +01:00
|
|
|
type Encoding int
|
|
|
|
|
|
2016-08-22 17:37:43 -07:00
|
|
|
const (
|
2016-12-19 14:34:26 +01:00
|
|
|
Identity = 0x00
|
2016-12-12 09:01:18 +01:00
|
|
|
Base1 = '1'
|
|
|
|
|
Base2 = '0'
|
|
|
|
|
Base8 = '7'
|
|
|
|
|
Base10 = '9'
|
|
|
|
|
Base16 = 'f'
|
|
|
|
|
Base16Upper = 'F'
|
|
|
|
|
Base32 = 'b'
|
|
|
|
|
Base32Upper = 'B'
|
|
|
|
|
Base32pad = 'c'
|
|
|
|
|
Base32padUpper = 'C'
|
|
|
|
|
Base32hex = 'v'
|
|
|
|
|
Base32hexUpper = 'V'
|
|
|
|
|
Base32hexPad = 't'
|
|
|
|
|
Base32hexPadUpper = 'T'
|
|
|
|
|
Base58Flickr = 'Z'
|
|
|
|
|
Base58BTC = 'z'
|
|
|
|
|
Base64 = 'm'
|
|
|
|
|
Base64url = 'u'
|
|
|
|
|
Base64pad = 'M'
|
|
|
|
|
Base64urlPad = 'U'
|
2016-08-22 17:37:43 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var ErrUnsupportedEncoding = fmt.Errorf("selected encoding not supported")
|
|
|
|
|
|
2016-12-21 20:42:49 +01:00
|
|
|
func Encode(base Encoding, data []byte) (string, error) {
|
2016-08-22 17:37:43 -07:00
|
|
|
switch base {
|
2016-12-19 14:34:26 +01:00
|
|
|
case Identity:
|
|
|
|
|
// 0x00 inside a string is OK in golang and causes no problems with the length calculation.
|
|
|
|
|
return string(Identity) + string(data), nil
|
2016-12-12 09:01:18 +01:00
|
|
|
case Base16, Base16Upper:
|
2016-11-27 23:56:23 +01:00
|
|
|
return string(Base16) + hex.EncodeToString(data), nil
|
2016-12-12 09:01:18 +01:00
|
|
|
case Base32, Base32Upper:
|
2016-11-27 23:56:23 +01:00
|
|
|
return string(Base32) + b32.RawStdEncoding.EncodeToString(data), nil
|
2016-12-12 09:01:18 +01:00
|
|
|
case Base32hex, Base32hexUpper:
|
2016-11-27 23:56:23 +01:00
|
|
|
return string(Base32hex) + b32.RawHexEncoding.EncodeToString(data), nil
|
2016-12-12 09:01:18 +01:00
|
|
|
case Base32pad, Base32padUpper:
|
|
|
|
|
return string(Base32pad) + b32.StdEncoding.EncodeToString(data), nil
|
|
|
|
|
case Base32hexPad, Base32hexPadUpper:
|
|
|
|
|
return string(Base32hexPad) + b32.HexEncoding.EncodeToString(data), nil
|
2016-08-22 17:37:43 -07:00
|
|
|
case Base58BTC:
|
|
|
|
|
return string(Base58BTC) + b58.EncodeAlphabet(data, b58.BTCAlphabet), nil
|
2016-11-27 23:56:23 +01:00
|
|
|
case Base58Flickr:
|
|
|
|
|
return string(Base58Flickr) + b58.EncodeAlphabet(data, b58.FlickrAlphabet), nil
|
2016-12-12 09:01:18 +01:00
|
|
|
case Base64pad:
|
|
|
|
|
return string(Base64pad) + base64.StdEncoding.EncodeToString(data), nil
|
|
|
|
|
case Base64urlPad:
|
|
|
|
|
return string(Base64urlPad) + base64.URLEncoding.EncodeToString(data), nil
|
2016-08-22 17:37:43 -07:00
|
|
|
default:
|
|
|
|
|
return "", ErrUnsupportedEncoding
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-21 20:42:49 +01:00
|
|
|
func Decode(data string) (Encoding, []byte, error) {
|
2016-10-24 15:31:20 -07:00
|
|
|
if len(data) == 0 {
|
|
|
|
|
return 0, nil, fmt.Errorf("cannot decode multibase for zero length string")
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-22 17:37:43 -07:00
|
|
|
switch data[0] {
|
2016-12-19 14:34:26 +01:00
|
|
|
case Identity:
|
|
|
|
|
return Identity, []byte(data[1:]), nil
|
2016-12-12 09:01:18 +01:00
|
|
|
case Base16, Base16Upper:
|
2016-11-27 23:56:23 +01:00
|
|
|
bytes, err := hex.DecodeString(data[1:])
|
|
|
|
|
return Base16, bytes, err
|
2016-12-12 09:01:18 +01:00
|
|
|
case Base32, Base32Upper:
|
2016-11-27 23:56:23 +01:00
|
|
|
bytes, err := b32.RawStdEncoding.DecodeString(data[1:])
|
|
|
|
|
return Base32, bytes, err
|
2016-12-12 09:01:18 +01:00
|
|
|
case Base32hex, Base32hexUpper:
|
2016-11-27 23:56:23 +01:00
|
|
|
bytes, err := b32.RawHexEncoding.DecodeString(data[1:])
|
|
|
|
|
return Base32hex, bytes, err
|
2016-12-12 09:01:18 +01:00
|
|
|
case Base32pad, Base32padUpper:
|
|
|
|
|
bytes, err := b32.StdEncoding.DecodeString(data[1:])
|
|
|
|
|
return Base32pad, bytes, err
|
|
|
|
|
case Base32hexPad, Base32hexPadUpper:
|
|
|
|
|
bytes, err := b32.HexEncoding.DecodeString(data[1:])
|
|
|
|
|
return Base32hexPad, bytes, err
|
2016-08-22 17:37:43 -07:00
|
|
|
case Base58BTC:
|
|
|
|
|
return Base58BTC, b58.DecodeAlphabet(data[1:], b58.BTCAlphabet), nil
|
2016-11-27 23:56:23 +01:00
|
|
|
case Base58Flickr:
|
|
|
|
|
return Base58Flickr, b58.DecodeAlphabet(data[1:], b58.FlickrAlphabet), nil
|
2016-12-12 09:01:18 +01:00
|
|
|
case Base64pad:
|
2016-11-27 23:56:23 +01:00
|
|
|
bytes, err := base64.StdEncoding.DecodeString(data[1:])
|
2016-12-12 09:01:18 +01:00
|
|
|
return Base64pad, bytes, err
|
|
|
|
|
case Base64urlPad:
|
2016-11-27 23:56:23 +01:00
|
|
|
bytes, err := base64.URLEncoding.DecodeString(data[1:])
|
2016-12-12 09:01:18 +01:00
|
|
|
return Base64urlPad, bytes, err
|
2016-08-22 17:37:43 -07:00
|
|
|
default:
|
|
|
|
|
return -1, nil, ErrUnsupportedEncoding
|
|
|
|
|
}
|
|
|
|
|
}
|