base58和base64一樣是一種二進(jìn)制轉(zhuǎn)可視字符串的算法泽谨,主要用來(lái)轉(zhuǎn)換大整數(shù)值兔毒。區(qū)別是咖楣,轉(zhuǎn)換出來(lái)的字符串等龙,去除了幾個(gè)看起來(lái)會(huì)產(chǎn)生歧義的字符富俄,如 0 (零), O (大寫(xiě)字母O), I (大寫(xiě)的字母i) and l (小寫(xiě)的字母L) ,和幾個(gè)影響雙擊選擇的字符而咆,如/, +。結(jié)果字符集正好58個(gè)字符(包括9個(gè)數(shù)字幕袱,24個(gè)大寫(xiě)字母暴备,25個(gè)小寫(xiě)字母)。不同的應(yīng)用實(shí)現(xiàn)中们豌,base58 最后查詢的字母表可能不同涯捻,所以沒(méi)有具體的標(biāo)準(zhǔn)。下面是幾個(gè)應(yīng)用中的字母表:
比特幣地址:
123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
Monero 地址
123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
Ripple 地址
rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz
Flickr 的短URL
123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ
Base58 編碼與解碼
Base58 的輸入是一個(gè)[0,256)的值的流望迎,輸出結(jié)果是一個(gè)[0,58) 的值的流障癌。然后將每個(gè)值去查字母表,得出一個(gè)可視字符串辩尊。轉(zhuǎn)換過(guò)程實(shí)際上就是一個(gè)256進(jìn)制的值轉(zhuǎn)換為一個(gè)58進(jìn)制的值涛浙。
進(jìn)制轉(zhuǎn)換過(guò)程如下(下面?zhèn)未a描述256進(jìn)制轉(zhuǎn)換為58進(jìn)制過(guò)程, base58編碼需要將58進(jìn)制流查表得到對(duì)應(yīng)的字符流):
# 將 input 256進(jìn)制流轉(zhuǎn)換為 output 58進(jìn)制流
for carry in input:
for (outputPos, outputNum) in output.reverse():
carry += outputNum * 256
output[outputPos] = carry % 58
carry /= 58
# output 流處理完畢, carry依然有值轿亮, 則繼續(xù)向 output 前部插入
while carry != 0 :
output.insertFront(carry%58)
carry /= 58
在實(shí)現(xiàn)的時(shí)候疮薇,開(kāi)頭的0需要特殊處理下,因?yàn)?轉(zhuǎn)換后依然是0我注, 所以可以將輸入流開(kāi)頭的0直接填充到結(jié)果前邊按咒。
逆轉(zhuǎn)換過(guò)程(先將輸入字符串轉(zhuǎn)換為58進(jìn)制的流, 然后將58進(jìn)制的流轉(zhuǎn)換為256進(jìn)制的流但骨, 下面?zhèn)未a描述58進(jìn)制轉(zhuǎn)換為256進(jìn)制過(guò)程):
# 將 input 58進(jìn)制流轉(zhuǎn)換為 output 256進(jìn)制流
for carry in input:
for (outputPos, outputNum) in output.reverse():
carry += outputNum * 58
output[outputPos] = carry % 256
carry /= 256
# output 流處理完畢励七, carry依然有值, 則繼續(xù)向 output 前部插入
while carry != 0 :
output.insertFront(carry%256)
carry /= 256
同樣奔缠,在實(shí)現(xiàn)的時(shí)候掠抬,開(kāi)頭的0需要特殊處理下,因?yàn)?轉(zhuǎn)換后依然是0添坊, 所以可以將輸入流開(kāi)頭的0直接填充到結(jié)果前邊剿另。
Base58Check
比特幣之所以加入改進(jìn)版的 Base58 算法,主要為了解決 Base58 導(dǎo)出的字符串沒(méi)有校驗(yàn)機(jī)制贬蛙,這樣雨女,在傳播過(guò)程中,如果漏寫(xiě)了幾個(gè)字符阳准,會(huì)檢測(cè)不出來(lái)氛堕。所以使用了改進(jìn)版的算法 Base58Check。
實(shí)現(xiàn)是:在encode前野蝇,在輸入流尾部加入輸入內(nèi)容的hash值(4個(gè)字節(jié))讼稚。然后再對(duì)輸入流進(jìn)行 Base58Encode。
在 decode 時(shí)候:先 Base58Decode, 然后拆成兩部分(內(nèi)容和校驗(yàn)值)绕沈,判斷對(duì)內(nèi)容計(jì)算的校驗(yàn)值和校驗(yàn)值字段是否一致锐想。
Go 的base58庫(kù):
https://github.com/shengdoushi/base58
比特幣Base58相關(guān)源碼地址: https://github.com/bitcoin/bitcoin/blob/master/src/base58.cpp