区块链算法之base58
一、base58编码原理
Base58是用于Bitcoin中使用的一种独特的编码方式,主要用于产生Bitcoin的钱包地址。base58和base64一样是一种二进制转可视字符串的算法,主要用来转换大整数值。区别是,转换出来的字符串,去除了几个看起来会产生歧义的字符,如 0 (零), O (大写字母O), I (大写的字母i) and l (小写的字母L) ,和几个影响双击选择的字符,如/, +。结果字符集正好58个字符(包括9个数字,24个大写字母,25个小写字母)。看下base58的编码表:
也就是字符1代表0,字符2代表1,字符3代表2…字符z代表57。然后回一下辗转相除法。
如要将1234转换为58进制;
第一步:1234除于58,商21,余数为16,查表得H
第二步:21除于58,商0,余数为21,查表得N
所以得到base58编码为:NH
如果待转换的数前面有0怎么办?直接附加编码1来代表,有多少个就附加多少个(编码表中1代表0)。
二、代码实现
golang实现
以下是一个studygolang上看到的一个实现的golang版本,具体代码如下:
1package main
2import (
3 "math/big"
4 "fmt"
5 "bytes"
6)
7var b58Alphabet = []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")
8func Base58Encode(input []byte) []byte{
9 var result []byte
10 x:= big.NewInt(0).SetBytes(input)
11 //把字节数组input转化为了大整数big.Int
12 base := big.NewInt(int64(len(b58Alphabet)))
13 zero := big.NewInt(0)
14 //大整数的指针
15 mod := &big.Int{}
16 for x.Cmp(zero) != 0 {
17 x.DivMod(x,base,mod) // 对x取余数
18 result = append(result, b58Alphabet[mod.Int64()])
19 }
20 for _,b:=range input{
21 if b ==0x00{
22 result = append([]byte{b58Alphabet[0]},result...)
23 }else{
24 break
25 }
26 }
27 return result
28}
29func Base58Decode(input []byte) []byte{
30 result := big.NewInt(0)
31 zeroBytes :=0
32 for _,b :=range input{
33 if b=='1'{
34 zeroBytes++
35 }else{
36 break
37 }
38 }
39 payload:= input[zeroBytes:]
40 for _,b := range payload{
41 charIndex := bytes.IndexByte(b58Alphabet,b) //反推出余数
42 result.Mul(result,big.NewInt(58)) //之前的结果乘以58
43 result.Add(result,big.NewInt(int64(charIndex))) //加上这个余数
44 }
45 decoded :=result.Bytes()
46 decoded = append(bytes.Repeat([]byte{0x00},zeroBytes),decoded...)
47 return decoded
48}
49func ReverseBytes(data []byte){
50 for i,j :=0,len(data) - 1;i<j;i,j = i+1,j - 1{
51 data[i],data[j] = data[j],data[i]
52 }
53}
54func main(){
55 org := []byte("qwerty")
56 fmt.Println(string(org))
57 ReverseBytes(org)
58 fmt.Println(string(org))
59 fmt.Printf("%s\n",string( Base58Encode([]byte("hello jonson"))))
60 fmt.Printf("%s",string(Base58Decode([]byte("2yGEbwRFyav6CimZ7"))))
61}
这里使用了反转,不是很方便,可以看后面使用一个高仿bitcoin版本的,也可以使用github上别我已经实现的版本:https://github.com/shengdoushi/base58/ (支持Bitcoin、Ripple、IPFS,缺点也是没有base58check)
比特币中的关于该算法的源码地址为:https://github.com/bitcoin/bitcoin/blob/master/src/base58.cpp (c++语言),一个高仿bitcoin源码的golang版实现的base58算法如下(不包含base58check算法):
1[root@361way base58]# go run 01base58.go
2kvMuJRLnworeVVrPSiY
3www.361way.com
我已把代码放在github上:https://github.com/361way/golang/blob/master/base58/01base58.go
python版本的实现
不得不说python版本写的还是不错的,base58.cpp上带的,这里都已经实现。地址为:https://pypi.org/project/base58/ (https://github.com/keis/base58)。
三、其他
base58编码不是所有的都使用的上面所列的基础码,不同的类型的里使用的编码不同,如下:
1BitcoinAlphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
2IPFSAlphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
3FlickrAlphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"
4RippleAlphabet = "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"
捐赠本站(Donate)
如您感觉文章有用,可扫码捐赠本站!(If the article useful, you can scan the QR code to donate))
- Author: shisekong
- Link: https://blog.361way.com/base58/6266.html
- License: This work is under a 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. Kindly fulfill the requirements of the aforementioned License when adapting or creating a derivative of this work.