github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/encoding/base58/base58.go (about) 1 // Copyright 2012 chaishushan@gmail.com. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package base58 implements a human-friendly base58 encoding. 6 package base58 7 8 import ( 9 "math/big" 10 "strings" 11 ) 12 13 const base58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" 14 15 func EncodeBase58(ba []byte) []byte { 16 if len(ba) == 0 { 17 return nil 18 } 19 20 // Expected size increase from base58 conversion is approximately 137%, use 138% to be safe 21 ri := len(ba) * 138 / 100 22 ra := make([]byte, ri+1) 23 24 x := new(big.Int).SetBytes(ba) // ba is big-endian 25 x.Abs(x) 26 y := big.NewInt(58) 27 m := new(big.Int) 28 29 for x.Sign() > 0 { 30 x, m = x.DivMod(x, y, m) 31 ra[ri] = base58[int32(m.Int64())] 32 ri-- 33 } 34 35 // Leading zeroes encoded as base58 zeros 36 for i := 0; i < len(ba); i++ { 37 if ba[i] != 0 { 38 break 39 } 40 ra[ri] = '1' 41 ri-- 42 } 43 return ra[ri+1:] 44 } 45 46 func DecodeBase58(ba []byte) []byte { 47 if len(ba) == 0 { 48 return nil 49 } 50 51 x := new(big.Int) 52 y := big.NewInt(58) 53 z := new(big.Int) 54 for _, b := range ba { 55 v := strings.IndexRune(base58, rune(b)) 56 z.SetInt64(int64(v)) 57 x.Mul(x, y) 58 x.Add(x, z) 59 } 60 xa := x.Bytes() 61 62 // Restore leading zeros 63 i := 0 64 for i < len(ba) && ba[i] == '1' { 65 i++ 66 } 67 ra := make([]byte, i+len(xa)) 68 copy(ra[i:], xa) 69 return ra 70 } 71 72 func EncodeBase58Check(ba []byte) []byte { 73 // add 4-byte hash check to the end 74 hash := Hash(ba) 75 ba = append(ba, hash[:4]...) 76 ba = EncodeBase58(ba) 77 return ba 78 } 79 80 func DecodeBase58Check(ba []byte) bool { 81 ba = DecodeBase58(ba) 82 if len(ba) < 4 || ba == nil { 83 return false 84 } 85 86 k := len(ba) - 4 87 hash := Hash(ba[:k]) 88 for i := 0; i < 4; i++ { 89 if hash[i] != ba[k+i] { 90 return false 91 } 92 } 93 return true 94 }