Base64是一種基于64個可打印字符來表示二進制數(shù)據(jù)的表示方法。由于2^6=64,所以每6個比特為一個單元,對應(yīng)某個可打印字符。3個字節(jié)有24個比特,對應(yīng)于4個Base64單元,即3個字節(jié)可由4個可打印字符來表示。它可用來作為電子郵件的傳輸編碼。在Base64中的可打印字符包括字母A-Z、a-z、數(shù)字0-9,這樣共有62個字符,此外兩個可打印符號在不同的系統(tǒng)中而不同。
讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價值的長期合作伙伴,公司提供的服務(wù)項目有:域名注冊、虛擬主機、營銷軟件、網(wǎng)站建設(shè)、王屋網(wǎng)站維護、網(wǎng)站推廣。
Base64常用于在通常處理文本數(shù)據(jù)的場合,表示、傳輸、存儲一些二進制數(shù)據(jù)
在Golang中提供了代碼庫可以供我們直接調(diào)用,用于實現(xiàn)Base64的編碼與解碼,其提供了對兩種格式的數(shù)據(jù)進行編碼(與解碼)
const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
const encodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
來自golang源碼base64.go
msg := "Mac"
//編碼
base64EncodedString := base64.StdEncoding.EncodeToString([]byte(msg))
fmt.Println("Base64編碼后:", base64EncodedString)
//解碼
base64DecodedByte, err := base64.StdEncoding.DecodeString(base64EncodedString)
if err != nil {
log.Panic(err)
}
fmt.Println("Base64解碼后的字節(jié)數(shù)組:", base64DecodedByte)
fmt.Println("Base64解碼后:", string(base64DecodedByte))
返回打印結(jié)果
Base64編碼后: TWFj
Base64解碼后的字節(jié)數(shù)組: [77 97 99]
Base64解碼后: Mac
msgUrl :="http://www.google.com"
base64UrlEncodedString :=base64.URLEncoding.EncodeToString([]byte(msgUrl))
fmt.Println("Base64編碼后:", base64UrlEncodedString)
base64UrlDecodedByte,err := base64.URLEncoding.DecodeString(base64UrlEncodedString)
if err !=nil {
log.Panic(err)
}
fmt.Println("Base64解碼后的字節(jié)數(shù)組:", base64UrlDecodedByte)
fmt.Println("Base64解碼后:", string(base64UrlDecodedByte))
返回打印結(jié)果
Base64編碼后: aHR0cDovL3d3dy5nb29nbGUuY29t
Base64解碼后的字節(jié)數(shù)組: [104 116 116 112 58 47 47 119 119 119 46 103 111 111 103 108 101 46 99 111 109]
Base64解碼后: http://www.google.com
fmt.Println([]byte(msg)) //[77 97 99]
fmt.Printf("%b",[]byte(msg))
//[1001101 1100001 1100011]
補齊8位為:
[01001101 01100001 01100011]
010011 010110 000101 100011
010011 ==> 1x2^0 + 1x2^1 + 0 + 0 + 1x2^4 = 19
010110 ==> 0 + 1x2^1 + 1x2^2 + 0 + 1x2^4 = 22
000101 ==> 1x2^0 + 0 + 1 x 2^2 + 0 + 0 + 0 = 5
100011 ==> 1x2^0 + 1x2^1 + 0 + 0 + 0 + 1x2^5 = 35
19 對應(yīng) T
22 對應(yīng) W
5 對應(yīng) F
35 對應(yīng) j (注意是小寫)
注意
- 若文本為3個字符,則剛好編碼為4個字符長度(3 8 = 4 6)
- 若文本為2個字符,則編碼為3個字符,尾部用一個"="補齊
- 若文本為1個字符,則編碼為2個字符,尾部用兩個"="補齊
Base58是用于Bitcoin中使用的一種獨特的編碼方式,主要用于產(chǎn)生Bitcoin的錢包地址。
相比Base64,Base58不使用數(shù)字"0",字母大寫"O",字母大寫"I",和字母小寫"l",以及"+"和"/"符號。
設(shè)計Base58主要的目的是:
但是這個base58的計算量比base64的計算量多了很多。因為58不是2的整數(shù)倍,需要不斷用除法去計算。
而且長度也比base64稍微多了一點。
附上golang的代碼實現(xiàn)
package main
import (
"math/big"
"bytes"
"fmt"
)
func main() {
/*
測試Base58
*/
//1.原始數(shù)據(jù)
data1 := []byte{10, 20, 30, 40, 50, 60}
data1 = append([]byte{0},data1...) //前綴+數(shù)據(jù)
fmt.Println("原始數(shù)據(jù):",data1)
//Base58編碼
encode:=Base58Encode(data1)
fmt.Println("Base58編碼后:",encode) //[]byte
fmt.Println(string(encode))
//Base58解碼
decode:=Base58Decode(encode)
fmt.Println("Base58解碼后:",decode)
//測試數(shù)據(jù)
data2:="wangergou"
encode2:=Base58Encode([]byte(data2))
fmt.Println(encode2)
fmt.Println(string(encode2))
decode2:=Base58Decode(encode2)
fmt.Println(decode2)
fmt.Println(string(decode2))
fmt.Println(string(decode2[1:])) //wangergou
}
//base64
/*
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
0(零),O(大寫的o),I(大寫的i),l(小寫的L),+,/
*/
var b58Alphabet = []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")
//字節(jié)數(shù)組轉(zhuǎn)Base58,加密
func Base58Encode(input []byte) []byte {
var result [] byte
x := big.NewInt(0).SetBytes(input)
//fmt.Println("x:",x)
base := big.NewInt(int64(len(b58Alphabet)))//58
//fmt.Println("base:",base)
zero := big.NewInt(0)
mod := &big.Int{}
for x.Cmp(zero) != 0 {
x.DivMod(x, base, mod)
//fmt.Println("x:",x,",mod:",mod) //0-57
result = append(result, b58Alphabet[mod.Int64()])
//fmt.Println("result:",string(result))
}
//將得到result中的數(shù)據(jù)進行反轉(zhuǎn)
ReverseBytes(result)
for b := range input { //遍歷input數(shù)組:index,value
if b == 0x00 {
result = append([]byte{b58Alphabet[0]}, result...)
} else {
break
}
}
//1 result
return result
}
//Base58轉(zhuǎn)字節(jié)數(shù)組,解密
func Base58Decode(input [] byte) []byte {
result := big.NewInt(0)
zeroBytes := 0
for b := range input {
if b == 0x00 {
zeroBytes++
}
}
fmt.Println("zeroBytes:",zeroBytes)
payload := input[zeroBytes:]
for _, b := range payload {
charIndex := bytes.IndexByte(b58Alphabet, b)
result.Mul(result, big.NewInt(58))
result.Add(result, big.NewInt(int64(charIndex)))
}
decoded := result.Bytes()
decoded = append(bytes.Repeat([]byte{byte(0x00)}, zeroBytes), decoded...)
return decoded
}
//字節(jié)數(shù)組反轉(zhuǎn)
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]
}
}