golang[32] - blockchain-base58

base58

Base58 is a unique encoding method used in Bitcoin, which is mainly used to generate the wallet address of Bitcoin. Compared with Base64, base58 does not use the number "0", the letter capital "O", the letter capital "I", and the letter lowercase "l", as well as the "+" and "/" symbols.

Base58 is designed to:
Avoid confusion. In some fonts, the number 0 is very similar to the letter capital O, and the letter capital I is very similar to the letter lowercase l.
The reason for not using "+" and "/" is that non alphanumeric strings are not acceptable as accounts.
There are no punctuation marks, and they are not usually separated from the middle.
Most software supports double-click to select the entire string.

base58 encoding

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
package main

import (
"math/big"
"fmt"
)

//Slice store base58
var b58Alphabet = []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")


func Base58Encode(input []byte) []byte{
//Define a byte slice, return value
var result []byte

//Convert byte array input to big integer big.Int
x:= big.NewInt(0).SetBytes(input)

//Large integer of length 58
base := big.NewInt(int64(len(b58Alphabet)))
 //Large integer for 0
zero := big.NewInt(0)
//Pointer to large integer
mod := &big.Int{}

 //Loop, constantly taking the remainder of x, size 58
for x.Cmp(zero) != 0 {
x.DivMod(x,base,mod)  // Remainder x

   //Add remainder to array
result =  append(result, b58Alphabet[mod.Int64()])
}


//Invert byte array
ReverseBytes(result)

//If the byte array is preceded by byte 0, it will be replaced with 1
for _,b:=range input{

if b ==0x00{
result =  append([]byte{b58Alphabet[0]},result...)
}else{
break
}
}


return result

}

//Invert byte array
func ReverseBytes(data []byte){
for i,j :=0,len(data) - 1;i<j;i,j = i+1,j - 1{
data[i],data[j] = data[j],data[i]
}
}

//Test reverse operation
func main(){
org := []byte("qwerty")
fmt.Println(string(org))

ReverseBytes(org)

fmt.Println(string(org))
//Test coding
 fmt.Printf("%s",string( Base58Encode([]byte("hello jonson"))))
}

Decode

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
func Base58Decode(input []byte) []byte{
result :=  big.NewInt(0)
zeroBytes :=0
for _,b :=range input{
if b=='1'{
zeroBytes++
}else{
break
}
}

payload:= input[zeroBytes:]

for _,b := range payload{
charIndex := bytes.IndexByte(b58Alphabet,b)  //Anti roll remainder

result.Mul(result,big.NewInt(58))   //Previous results multiplied by 58

result.Add(result,big.NewInt(int64(charIndex)))  //Add this remainder

}

decoded :=result.Bytes()


decoded =  append(bytes.Repeat([]byte{0x00},zeroBytes),decoded...)
return decoded
}

Complete code

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
103
104
105
package main

import (
"math/big"
"fmt"
"bytes"
)

var b58Alphabet = []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")


func Base58Encode(input []byte) []byte{
var result []byte

x:= big.NewInt(0).SetBytes(input)

base := big.NewInt(int64(len(b58Alphabet)))
zero := big.NewInt(0)

mod := &big.Int{}
for x.Cmp(zero) != 0 {
x.DivMod(x,base,mod)  // Remainder x
result =  append(result, b58Alphabet[mod.Int64()])
}



ReverseBytes(result)

for _,b:=range input{

if b ==0x00{
result =  append([]byte{b58Alphabet[0]},result...)
}else{
break
}
}


return result

}







func Base58Decode(input []byte) []byte{
result :=  big.NewInt(0)
zeroBytes :=0
for _,b :=range input{
if b=='1'{
zeroBytes++
}else{
break
}
}

payload:= input[zeroBytes:]

for _,b := range payload{
charIndex := bytes.IndexByte(b58Alphabet,b)  //Anti roll remainder

result.Mul(result,big.NewInt(58))   //Previous results multiplied by 58

result.Add(result,big.NewInt(int64(charIndex)))  //Add this remainder

}

decoded :=result.Bytes()


decoded =  append(bytes.Repeat([]byte{0x00},zeroBytes),decoded...)
return decoded
}





func ReverseBytes(data []byte){
for i,j :=0,len(data) - 1;i<j;i,j = i+1,j - 1{
data[i],data[j] = data[j],data[i]
}
}

func main(){
org := []byte("qwerty")
fmt.Println(string(org))

ReverseBytes(org)

fmt.Println(string(org))



fmt.Printf("%s\n",string( Base58Encode([]byte("hello jonson"))))




fmt.Printf("%s",string(Base58Decode([]byte("2yGEbwRFyav6CimZ7"))))
}

Reference material

(bitcoin wiki-base58 code)[ https://en.bitcoin.it/wiki/Base58Check_encoding#Version_bytes]
(Wikipedia base58)[ https://zh.wikipedia.org/wiki/Base58]

Keywords: Web Development encoding

Added by samshel on Tue, 03 Dec 2019 14:09:55 +0200