This repository has been archived by the owner on Jul 7, 2020. It is now read-only.
forked from keybase/client
/
base58.go
102 lines (86 loc) · 2 KB
/
base58.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
// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.
package libkb
import (
"bytes"
"fmt"
"math/big"
)
const base58InvalidIndex = 0xFF
var alphabet = []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")
var alphabetMap = func() [256]byte {
var res [256]byte
// First initialize to 0xFF
for i := range res {
res[i] = base58InvalidIndex
}
// And reset the real contents to their values.
for i, c := range alphabet {
res[c] = uint8(i)
}
return res
}()
func reverseBuf(buf []byte) {
tot := len(buf)
mid := tot / 2
for i := 0; i < mid; i++ {
buf[i], buf[tot-i-1] = buf[tot-i-1], buf[i]
}
}
// Encode58 base58 encodes the input.
func Encode58(inp []byte) string {
num := new(big.Int).SetBytes(inp)
buf := make([]byte, 0, len(inp))
base := big.NewInt(int64(58))
rem := new(big.Int)
quo := new(big.Int)
for num.Sign() != 0 {
num, rem = quo.QuoRem(num, base, rem)
c := alphabet[rem.Uint64()]
buf = append(buf, c)
}
// Pad leading zeros...
for _, c := range inp {
if c == 0x0 {
buf = append(buf, alphabet[0])
} else {
// Stop adding padding after the first nonzero byte.
break
}
}
reverseBuf(buf)
return string(buf)
}
// Decode58 base58 decodes the input or returns an error.
func Decode58(inp string) (outp []byte, err error) {
place := big.NewInt(1)
base := big.NewInt(58)
buf := []byte(inp)
padlen := 0
// Advance to first non-pad byte
for ; padlen < len(buf); padlen++ {
if buf[padlen] != alphabet[0] {
break
}
}
buf = buf[padlen:]
reverseBuf(buf)
tmp := new(big.Int)
res := big.NewInt(0)
for i, c := range buf {
charIndex := alphabetMap[c]
if charIndex == base58InvalidIndex {
err = fmt.Errorf("Bad character '%c' found at pos %d", c, i)
return
}
tmp.Mul(place, big.NewInt(int64(charIndex)))
res.Add(res, tmp)
if i != len(buf)-1 {
place.Mul(place, base)
}
}
buf = res.Bytes()
pad := bytes.Repeat([]byte{0}, padlen)
outp = append(pad, buf...)
return
}