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  }