High-performance Base58 encoding/decoding library for Go with support for multiple alphabets.
- Fast: Optimized algorithms using chunked processing and lookup tables
- Multiple Alphabets: Built-in support for Bitcoin, Flickr, and Ripple alphabets
- Memory Efficient: Minimal allocations (1-2 allocs for most operations), stack allocation for small inputs
- Zero Dependencies: Pure Go implementation
- Fully Tested: Comprehensive test suite with fuzzing
go get github.com/dozyio/base58package main
import (
"fmt"
"github.com/dozyio/base58"
)
func main() {
// Encode using Bitcoin alphabet (default)
data := []byte("Hello, World!")
encoded := base58.Encode(data)
fmt.Println(encoded) // 72k1xXWG59fYdzSNoA
// Decode
decoded, err := base58.Decode(encoded)
if err != nil {
panic(err)
}
fmt.Println(string(decoded)) // Hello, World!
}// Use Flickr alphabet
encoded := base58.EncodeAlphabet(data, base58.FlickrAlphabet)
decoded, err := base58.DecodeAlphabet(encoded, base58.FlickrAlphabet)
// Use Ripple alphabet
encoded = base58.EncodeAlphabet(data, base58.RippleAlphabet)
decoded, err = base58.DecodeAlphabet(encoded, base58.RippleAlphabet)
// Create custom encoding instance
custom := base58.NewEncoding("your58characteralphabetgoesheremakesureitisunique123")
encoded = custom.Encode(data)
decoded, err = custom.Decode(encoded)Benchmarked on Apple M3 Max against popular Go Base58 libraries:
- mr-tron/base58 v1.2.0
- btcsuite/btcd/btcutil v1.1.6
| Input Size | This Library | mr-tron/base58 | btcd | Speedup vs mr-tron | Speedup vs btcd | Allocs vs mr-tron | Allocs vs btcd |
|---|---|---|---|---|---|---|---|
| 10 bytes | 32.94 ns/op 1 alloc/op |
60.02 ns/op 1 alloc/op |
94.33 ns/op 5 allocs/op |
1.82x faster | 2.86x faster | Equal | 5x fewer |
| 100 bytes | 180.1 ns/op 1 alloc/op |
3,396 ns/op 2 allocs/op |
440.8 ns/op 7 allocs/op |
18.9x faster | 2.45x faster | 2x fewer | 7x fewer |
| 1 KB | 10,037 ns/op 106 allocs/op |
470,766 ns/op 2 allocs/op |
7,426 ns/op 30 allocs/op |
46.9x faster | 1.35x slower | 53x more | 3.5x more |
| 10 KB | 272,245 ns/op 751 allocs/op |
48,694,924 ns/op 2 allocs/op |
409,456 ns/op 260 allocs/op |
179x faster | 1.50x faster | 376x more | 2.9x more |
Memory Allocations (Decode):
| Input Size | This Library | mr-tron/base58 | btcd |
|---|---|---|---|
| 10 bytes | 16 B/op 1 alloc/op |
24 B/op 1 alloc/op |
96 B/op 5 allocs/op |
| 100 bytes | 112 B/op 1 alloc/op |
352 B/op 2 allocs/op |
512 B/op 7 allocs/op |
| 1 KB | 13,660 B/op 106 allocs/op |
3,456 B/op 2 allocs/op |
17,024 B/op 30 allocs/op |
| 10 KB | 195,307 B/op 751 allocs/op |
34,816 B/op 2 allocs/op |
1,417,480 B/op 260 allocs/op |
| Input Size | This Library | mr-tron/base58 | btcd | Speedup vs mr-tron | Speedup vs btcd | Allocs vs mr-tron | Allocs vs btcd |
|---|---|---|---|---|---|---|---|
| 10 bytes | 39.05 ns/op 1 alloc/op |
98.09 ns/op 1 alloc/op |
79.44 ns/op 3 allocs/op |
2.51x faster | 2.03x faster | Equal | 3x fewer |
| 100 bytes | 581.1 ns/op 1 alloc/op |
11,196 ns/op 2 allocs/op |
754.4 ns/op 4 allocs/op |
19.3x faster | 1.30x faster | 2x fewer | 4x fewer |
| 1 KB | 46,754 ns/op 4 allocs/op |
1,245,349 ns/op 2 allocs/op |
46,893 ns/op 4 allocs/op |
26.6x faster | Equal | 2x more | Equal |
| 10 KB | 4,402,854 ns/op 4 allocs/op |
125,558,953 ns/op 2 allocs/op |
4,393,754 ns/op 4 allocs/op |
28.5x faster | Equal | 2x more | Equal |
Memory Allocations (Encode):
| Input Size | This Library | mr-tron/base58 | btcd |
|---|---|---|---|
| 10 bytes | 16 B/op 1 alloc/op |
16 B/op 1 alloc/op |
72 B/op 3 allocs/op |
| 100 bytes | 144 B/op 1 alloc/op |
288 B/op 2 allocs/op |
440 B/op 4 allocs/op |
| 1 KB | 3,976 B/op 4 allocs/op |
2,816 B/op 2 allocs/op |
3,976 B/op 4 allocs/op |
| 10 KB | 39,560 B/op 4 allocs/op |
28,672 B/op 2 allocs/op |
39,560 B/op 4 allocs/op |
Optimized for typical libp2p peer ID sizes (34-byte SHA-256 multihash):
| Operation | This Library | mr-tron/base58 | btcd | Speedup vs mr-tron | Speedup vs btcd | Allocs vs mr-tron | Allocs vs btcd |
|---|---|---|---|---|---|---|---|
| Encode | 102.6 ns/op 48 B/op 1 alloc/op |
1,322 ns/op 96 B/op 2 allocs/op |
210.7 ns/op 184 B/op 4 allocs/op |
12.9x faster | 2.05x faster | 2x fewer | 4x fewer |
| Decode | 68.80 ns/op 48 B/op 1 alloc/op |
346.9 ns/op 128 B/op 2 allocs/op |
179.5 ns/op 160 B/op 5 allocs/op |
5.04x faster | 2.61x faster | 2x fewer | 5x fewer |
| Round-Trip | 173.6 ns/op 96 B/op 2 allocs/op |
1,714 ns/op 224 B/op 4 allocs/op |
397.5 ns/op 344 B/op 9 allocs/op |
9.87x faster | 2.29x faster | 2x fewer | 4.5x fewer |
This library achieves high performance through several optimizations:
- Hybrid Approach: Automatically switches between optimized algorithms based on input size:
- Small inputs (< 512 bytes for encode, < 768 bytes for decode): Uses chunked uint64 math with minimal allocations
- Large inputs (≥ 512/768 bytes): Uses
math/bigwhich leverages assembly-optimized big integer operations - This hybrid strategy provides the best performance across all input sizes
- Chunked Processing: Processes input in Base58^5 (encode) and Base58^10 (decode) chunks instead of single bytes
- Lookup Tables: Pre-computed 2-character lookup table (58^2 = 3,364 entries) for faster output generation
- Stack Allocation: Uses stack allocation for small inputs to avoid heap pressure
- Unsafe Pointers: Direct memory access for critical hot paths
- SIMD-Ready: Byte reversal using
bits.ReverseBytes32for potential hardware acceleration - Zero-Copy Strings: Uses
unsafe.Stringto avoid allocations when converting []byte to string - Alphabet Caching: Caches encoding instances to avoid rebuilding decode maps
// Encode/Decode with Bitcoin alphabet
func Encode(input []byte) string
func Decode(str string) ([]byte, error)
// Encode/Decode with custom alphabet
func EncodeAlphabet(input []byte, alphabet string) string
func DecodeAlphabet(str string, alphabet string) ([]byte, error)
// Create encoding instance
func NewEncoding(alphabet string) *Encodingconst (
BTCAlphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
FlickrAlphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"
RippleAlphabet = "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"
)var (
BTC = NewEncoding(BTCAlphabet)
Flickr = NewEncoding(FlickrAlphabet)
Ripple = NewEncoding(RippleAlphabet)
)# Run tests
go test -v
# Run benchmarks
go test -bench=. -benchmem
# Run with race detection
go test -race
# Run fuzzing
go test -fuzz=FuzzBase58 -fuzztime=30sMIT License - see LICENSE file for details
Contributions are welcome! Please feel free to submit a Pull Request.