1. Base编码与解码

简介:二进制转可视字符串的算法

1.1 base64编码与解码

包含:【52大小写字母】、【10数字】、【/】、【+】 封装

package utils

import "encoding/base64"

func Base64Encoding(src string) string {

src_byte := []byte(src)

return base64.StdEncoding.EncodeToString(src_byte)

}

func Base64Decoding(src string) (string, error) {

res, err := base64.StdEncoding.DecodeString(src)

return string(res), err

}

func Base64UrlEncoding(url string) string {

url_byte := []byte(url)

return base64.URLEncoding.EncodeToString(url_byte)

}

func Base64UrlDecoding(url string) (string, error) {

res, err := base64.URLEncoding.DecodeString(url)

return string(res), err

}

1.2 base58编码与解码

将字符串的每个字节换算成ASCII,字符串实际上就是256进制的数字组合将256进制的数字转换成10进制数字将10进制数字转换成58进制数字(除以58,每次得到的余数就是对应的58进制,0用编码1来代表)将58进制数字对照58编码表找到对应的字符

包含:【49大小写字母(去掉了 O I L )】、【9数字(去掉了0)】、(去掉了\ +)封装

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

// 编码

func Base58Encoding(str string) string {

//1. 转换成ascii码对应的值(得到256进制)

// he -> [104 101]

strByte := []byte(str)

//2. 转换为十进制(256 -> 10)

//104 101 = 104*156 + 101 = 26725

strTen := big.NewInt(0).SetBytes(strByte)

//3. 取出余数(10 -> 58 -> 10)

//26725 / 58 = [45 54 7] = [n w 8](58进制)

//[n w 8] -> [110 119 56](十进制)

var modSlice []byte

var strTen58 = big.NewInt(58)

for strTen.Cmp(big.NewInt(0)) > 0 {

mod := big.NewInt(0)

strTen.DivMod(strTen, strTen58, mod)

modSlice = append(modSlice, base58[mod.Int64()]) //存储余数,并将对应值放入其中

}

//4. 处理0就是1的情况 0使用字节'1'代替

for _, elem := range strByte {

if elem != 0 {

break

} else if elem == 0 {

modSlice = append(modSlice, byte('1'))

}

}

//5. 反转结果

//[56 119 110]

ReverseModSlice := ReverseByteArr(modSlice)

//5. 转为字符串

return string(ReverseModSlice)

}

// 反转字符串

func ReverseByteArr(bytes []byte) []byte {

for i, j := 0, len(bytes)-1; i < j; i, j = i+1, j-1 {

bytes[i], bytes[j] = bytes[j], bytes[i]

}

return bytes

}

// 解码

func Base58Decoding(str string) string { //Base58解码

//1. 字符串 -> ascii(256)

//[56 119 110]

strByte := []byte(str)

//2. 通过索引得到58

//[56 119 110] -> [7 54 45]

//7*58*58 + 54*58 + 45 = 26725

ret := big.NewInt(0)

for _, b := range strByte {

i := bytes.IndexByte(base58, b)

ret.Mul(ret, big.NewInt(58))

ret.Add(ret, big.NewInt(int64(i)))

}

//3. 转成ascii

//[104 101]

return string(ret.Bytes())

}

解说说明

代码中的Int是big.Int结构体,不是int类型,所以使用的也是DivMod方法来取余而不是%DivMod三个参数:被除数、除数、用于存储余数的变量modSlice = append(modSlice, base58[mod.Int64()])不是向前添加,怎么追加了? 因为下一步是反转

测试编码与解码

package main

import (

"BasicBlock/utils"

"fmt"

)

func main() {

src := "hello"

srcUrl := "http://127.0.0.1:8080/?name=hello"

srcBase64 := utils.Base64Encoding(src)

if res, err := utils.Base64Decoding(srcBase64); err != nil {

fmt.Println(err)

} else {

fmt.Println("Base64:", srcBase64)

fmt.Println("原值:", res)

}

srcBase64Url := utils.Base64UrlEncoding(srcUrl)

if res, err := utils.Base64UrlDecoding(srcBase64Url); err != nil {

fmt.Println(err)

} else {

fmt.Println("Base64URL:", srcBase64Url)

fmt.Println("原值:", res)

}

// 编码完又解码

fmt.Println(utils.Base58Decoding(utils.Base58Encoding("he")))

}

测试结果

Base64: aGVsbG8=

原值: hello

Base64URL: aHR0cDovLzEyNy4wLjAuMTo4MDgwLz9uYW1lPWhlbGxv

原值: http://127.0.0.1:8080/?name=hello

he

2. 哈希算法

2.1 简介

不可逆(不可解码) 唯一性 防篡改 性能: md4 > md5 > sha224 > sha256 > sha384 > sha512 内存消耗: md5 > md4 > ha512 > sha384 > sha256 > ha224

2.2 md5(已不安全)

加密

func GetMd5(str string) string {

srcBytes := []byte(str)

md5New := md5.New()

// 输入的字节数组添加到MD5哈希对象中

md5Bytes := md5New.Sum(srcBytes)

md5String := hex.EncodeToString(md5Bytes)

return md5String

}

2.3 sha256

加密

func GetSha256(src string) string {

// 将输入字符串转换为字节数组

srcBytes := []byte(src)

// 创建一个新的 SHA-256 散列对象

sha256New := sha256.New()

// 将输入字节数组写入 SHA-256 散列对象

sha256New.Write(srcBytes)

// 计算 SHA-256 散列值并返回结果,Sum 的参数为 nil 表示获取结果的字节数组

sha256Bytes := sha256New.Sum(nil)

// 将字节数组转换为十六进制表示的字符串

sha256String := hex.EncodeToString(sha256Bytes)

// 返回 SHA-256 散列值的十六进制表示

return sha256String

}

测试md5与sha256

func testMdAndSha() {

src := "hello"

res := utils.GetMd5(src)

fmt.Println(res)

res = utils.GetSha256(src)

fmt.Println(res)

}

func main() {

testMdAndSha()

}

测试结果

68656c6c6fd41d8cd98f00b204e9800998ecf8427e

68656c6c6fe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

3. 对称加密与非对称加密

3.1 简介

对称加密非对称加密特点加密密钥与解密密钥相同加密密钥与解密密钥不相同优点效率高,适合大些数据加密安全相对对称加密高缺点安全相对非对称加密低效率低,适合小些数据加密

3.2 对称加密

3.2.1 简介

对称加密算法key长度AESkey支持3中长度(16,24,32字节)DESkey只支持8字节长度DES3key只支持24(8*3)字节长度

3.2.2 AES

ASE-128:key长度为16字节(以下示例)ASE-192:key长度为24字节ASE-256:key长度为32字节

加密+编码解码+解密

/**

@since: 2024/1/3

@desc: 对称加密

**/

package utils

import (

"bytes"

"crypto/aes"

"encoding/base64"

"errors"

"fmt"

)

var key = []byte("encoding/base128") // 支持14、24、32字节

// 添加填充

func PadPwd(b []byte, size int) []byte {

padNum := size - len(b)%size

res := bytes.Repeat([]byte{byte(padNum)}, padNum)

// 补充的元素添加到末尾,内容是padNum(缺少元素的个数)

b = append(b, res...)

return b

}

// 去除填充

func UpPwd(dist []byte) ([]byte, error) {

if len(dist) <= 0 {

return dist, errors.New("长度不能为0")

}

// 获取需要去掉的元素,也就是最后添加的重复元素

num := dist[len(dist)-1]

dist = dist[:len(dist)-int(num)]

return dist, nil

}

// AesEncoding

// @Description: AES加密

// @param src

// @return string

func AesEncoding(src string) (string, error) {

src_bytes := []byte(src)

fmt.Println("1.填充前明文:", src_bytes)

block, err := aes.NewCipher(key)

// 密码填充

new_src_byte := PadPwd(src_bytes, block.BlockSize())

fmt.Println("2.填充后明文:", new_src_byte)

// 准备密文

dst := make([]byte, len(new_src_byte))

// 加密

block.Encrypt(dst, new_src_byte)

fmt.Println("3.填充后密文:", dst)

// base64编码

pwd := base64.StdEncoding.EncodeToString(dst)

fmt.Println("4.编码后密文:", pwd)

return pwd, err

}

// AesDecoding

// @Description: Aes解密

// @param src

// @return string

// @return error

func AesDecoding(src string) (string, error) {

/*解码*/

//src_byte := []byte(src)

pwd_byte, err := base64.StdEncoding.DecodeString(src)

if err != nil {

return "", err

}

fmt.Println("1.解码后密文:", pwd_byte)

/*解密*/

block, err := aes.NewCipher(key)

if err != nil {

return "", err

}

dst := make([]byte, len(pwd_byte))

block.Decrypt(dst, pwd_byte)

fmt.Println("2.填充后密文:", dst)

/*去掉填充*/

old_dist, err := UpPwd(dst)

if err != nil {

return "", err

}

fmt.Println("3.填充前密文:", old_dist)

/*转为字符串*/

res := string(dst)

fmt.Println("4.明文:", res)

return res, nil

}

测试

func testSymmetry() {

src := "hello"

fmt.Println("开始加密,明文为:", src)

pwdEn, err := utils.AesEncoding(src)

if err != nil {

fmt.Println(err)

}

fmt.Println("开始解密")

pwdDn, err := utils.AesDecoding(pwdEn)

if err != nil {

fmt.Println(err)

}

fmt.Println(pwdDn)

}

开始加密,明文为: hello

1.填充前明文: [104 101 108 108 111]

2.填充后明文: [104 101 108 108 111 11 11 11 11 11 11 11 11 11 11 11]

3.填充后密文: [10 79 94 216 19 28 243 51 213 205 87 3 173 122 174 29]

4.编码后密文: Ck9e2BMc8zPVzVcDrXquHQ==

开始解密

1.解码后密文: [10 79 94 216 19 28 243 51 213 205 87 3 173 122 174 29]

2.填充后密文: [104 101 108 108 111 11 11 11 11 11 11 11 11 11 11 11]

3.填充前密文: [104 101 108 108 111]

4.明文: hello

3.2.3 DES

与Aes加密非常相似,只需要修改key长度(只支持8字节)

加密+编码解码+解密

var des_key = []byte("fmterror") //8字节

func DesEncoding(src string) (string, error) {

src_bytes := []byte(src)

fmt.Println("1.填充前明文:", src_bytes)

block, err := des.NewCipher(des_key)

// 密码填充

new_src_byte := PadPwd(src_bytes, block.BlockSize())

fmt.Println("2.填充后明文:", new_src_byte)

// 准备密文

dst := make([]byte, len(new_src_byte))

// 加密

block.Encrypt(dst, new_src_byte)

fmt.Println("3.填充后密文:", dst)

// base64编码

pwd := base64.StdEncoding.EncodeToString(dst)

fmt.Println("4.编码后密文:", pwd)

return pwd, err

}

func DesDecoding(src string) (string, error) {

/*解码*/

//src_byte := []byte(src)

pwd_byte, err := base64.StdEncoding.DecodeString(src)

if err != nil {

return "", err

}

fmt.Println("1.解码后密文:", pwd_byte)

/*解密*/

block, err := des.NewCipher(des_key)

if err != nil {

return "", err

}

dst := make([]byte, len(pwd_byte))

block.Decrypt(dst, pwd_byte)

fmt.Println("2.填充后密文:", dst)

/*去掉填充*/

old_dist, err := UpPwd(dst)

if err != nil {

return "", err

}

fmt.Println("3.填充前密文:", old_dist)

/*转为字符串*/

res := string(dst)

fmt.Println("4.明文:", res)

return res, nil

}

测试

func testSymmetry_Des() {

src := "hello"

fmt.Println("开始加密,明文为:", src)

pwdEn, err := utils.DesEncoding(src)

if err != nil {

fmt.Println(err)

}

fmt.Println("开始解密")

pwdDn, err := utils.DesDecoding(pwdEn)

if err != nil {

fmt.Println(err)

}

fmt.Println(pwdDn)

}

开始加密,明文为: hello

1.填充前明文: [104 101 108 108 111]

2.填充后明文: [104 101 108 108 111 3 3 3]

3.填充后密文: [77 159 223 194 83 14 44 184]

4.编码后密文: TZ/fwlMOLLg=

开始解密

1.解码后密文: [77 159 223 194 83 14 44 184]

2.填充后密文: [104 101 108 108 111 3 3 3]

3.填充前密文: [104 101 108 108 111]

4.明文: hello

hello

3.2.4 3DES

与DES非常相似

只需要修改方法des.NewCipher为des.NewTripleDESCipher修改key长度为24

加密+编码解码+解密

var tripleDes_key = []byte("errorserrorserrorserrors") // 24字节

func TripleDesEncoding(src string) (string, error) {

src_bytes := []byte(src)

fmt.Println("1.填充前明文:", src_bytes)

block, err := des.NewTripleDESCipher(tripleDes_key)

// 密码填充

new_src_byte := PadPwd(src_bytes, block.BlockSize())

fmt.Println("2.填充后明文:", new_src_byte)

// 准备密文

dst := make([]byte, len(new_src_byte))

// 加密

block.Encrypt(dst, new_src_byte)

fmt.Println("3.填充后密文:", dst)

// base64编码

pwd := base64.StdEncoding.EncodeToString(dst)

fmt.Println("4.编码后密文:", pwd)

return pwd, err

}

func TripleDesDecoding(src string) (string, error) {

/*解码*/

//src_byte := []byte(src)

pwd_byte, err := base64.StdEncoding.DecodeString(src)

if err != nil {

return "", err

}

fmt.Println("1.解码后密文:", pwd_byte)

/*解密*/

block, err := des.NewTripleDESCipher(tripleDes_key)

if err != nil {

return "", err

}

dst := make([]byte, len(pwd_byte))

block.Decrypt(dst, pwd_byte)

fmt.Println("2.填充后密文:", dst)

/*去掉填充*/

old_dist, err := UpPwd(dst)

if err != nil {

return "", err

}

fmt.Println("3.填充前密文:", old_dist)

/*转为字符串*/

res := string(dst)

fmt.Println("4.明文:", res)

return res, nil

}

测试

func testSymmetry_TripleDes() {

src := "hello"

fmt.Println("开始加密,明文为:", src)

pwdEn, err := utils.TripleDesEncoding(src)

if err != nil {

fmt.Println(err)

}

fmt.Println("开始解密")

pwdDn, err := utils.TripleDesDecoding(pwdEn)

if err != nil {

fmt.Println(err)

}

fmt.Println(pwdDn)

}

开始加密,明文为: hello

1.填充前明文: [104 101 108 108 111]

2.填充后明文: [104 101 108 108 111 3 3 3]

3.填充后密文: [185 118 18 103 102 177 239 107]

4.编码后密文: uXYSZ2ax72s=

开始解密

1.解码后密文: [185 118 18 103 102 177 239 107]

2.填充后密文: [104 101 108 108 111 3 3 3]

3.填充前密文: [104 101 108 108 111]

4.明文: hello

hello

3.3 非对称加密 RSA

简介:RSA来源于三位大佬名字的首字母

3.3.1 生成公钥和密钥

生成公钥和私钥 数据规范化(编码+封装) 公钥和私钥的保存(文件)

/**

@since: 2024/1/4

@desc:

**/

package utils

import (

"crypto/rand"

"crypto/rsa"

"crypto/x509"

"encoding/pem"

"os"

)

func SaveRsaKey(bits int) error {

// 生成公钥和私钥

privateKey, err := rsa.GenerateKey(rand.Reader, bits)

publicKey := privateKey.PublicKey

if err != nil {

return err

}

// x509编码

x509_private := x509.MarshalPKCS1PrivateKey(privateKey)

x509_public := x509.MarshalPKCS1PublicKey(&publicKey)

// 封装block结构

block_private := pem.Block{Type: "private key", Bytes: x509_private}

block_public := pem.Block{Type: "public key", Bytes: x509_public}

// 创建文件

privateFile, err_priFile := os.Create("privateKey.pem")

if err_priFile != nil {

return nil

}

defer privateFile.Close()

pem.Encode(privateFile, &block_private) // 写入私钥

publicFile, err_pubFile := os.Create("publicKey.pem")

if err_pubFile != nil {

return nil

}

defer publicFile.Close()

pem.Encode(publicFile, &block_public) // 写入公钥

return nil

}

测试

func testRsa() {

err := utils.SaveRsaKey(2048)

if err != nil {

fmt.Println(err)

}

}

3.3.2 使用公钥密钥加密与解密

读取文件解码加密 / 解密

//

// RsaEncoding

// @Description: 加密

// @param src

// @param file_path

// @return []byte

// @return error

//

func RsaEncoding(src, file_path string) ([]byte, error) {

fail := []byte("Fail")

/*读取文件*/

file, err := os.Open(file_path)

if err != nil {

return fail, err

}

defer file.Close()

fileInfo, errFileInfo := file.Stat()

if errFileInfo != nil {

return fail, errFileInfo

}

public_data := make([]byte, fileInfo.Size())

file.Read(public_data)

/*解码*/

block, _ := pem.Decode(public_data)

publicKey, errPubKey := x509.ParsePKCS1PublicKey(block.Bytes)

if errPubKey != nil {

return fail, errPubKey

}

/*加密*/

result_byte, errResult := rsa.EncryptPKCS1v15(rand.Reader, publicKey, []byte(src))

if errResult != nil {

return fail, errResult

}

return result_byte, nil

}

//

// RsaDecoding

// @Description: 解密

// @param src_byte

// @param file_path

// @return []byte

// @return error

//

func RsaDecoding(src_byte []byte, file_path string) ([]byte, error) {

fail := []byte("Fail")

/*读取文件*/

file, err := os.Open(file_path)

if err != nil {

return fail, err

}

defer file.Close()

fileInfo, errFileInfo := file.Stat()

if errFileInfo != nil {

return fail, errFileInfo

}

private_data := make([]byte, fileInfo.Size())

file.Read(private_data)

/*解码*/

block, _ := pem.Decode(private_data)

privateKey, errPriKey := x509.ParsePKCS1PrivateKey(block.Bytes)

if errPriKey != nil {

return fail, errPriKey

}

/*解密*/

result, err_result := rsa.DecryptPKCS1v15(rand.Reader, privateKey, src_byte)

if err_result != nil {

return fail, err_result

}

return result, nil

}

测试

func testRsa() {

//err := utils.SaveRsaKey(2048)

//if err != nil {

// fmt.Println(err)

//}

src := "hello"

fmt.Println("明文:", src)

res, err_res := utils.RsaEncoding(src, "publicKey.pem")

if err_res != nil {

fmt.Println(err_res)

}

fmt.Println("密文:", res)

old, err_old := utils.RsaDecoding(res, "privateKey.pem")

if err_old != nil {

fmt.Println(err_old)

}

fmt.Println("解密后明文:", string(old))

}

明文: hello

密文: [95 141 29 75 131 44 86 10 34 207 137 183 185 177 72 249 119 145 253 213

19 204 158 194 152 153 50 83 186 251 93 148 165 101 59 240 250 10 172 238 64 97

126 149 212 217 158 50 110 70 206 168 175 10 200 2 146 126 132 98 52 252 126 211

71 179 141 32 114 222 172 143 112 16 34 3 236 158 205 160 41 60 2 2 73 177 92 3

1 83 211 72 79 10 123 223 145 40 26 240 28 183 103 112 123 129 135 54 130 198 25

3 25 201 189 226 115 75 80 185 69 69 148 63 64 97 213 22 163 98 171 84 80 219 13

2 120 16 198 71 81 101 116 16 98 122 244 1 237 239 106 214 226 92 14 196 1 140 1

5 236 195 230 118 6 54 164 77 42 112 52 105 200 62 20 181 25 118 38 18 182 29 54

142 165 206 104 179 94 38 62 135 7 17 190 138 17 220 152 126 192 75 40 81 76 24

2 230 188 155 143 34 64 108 20 102 178 169 129 176 89 225 254 196 168 18 1 149 1

18 180 237 122 71 69 161 247 55 82 8 15 116 127 123 16 246 234 115 90 91 157 162

202 74 185 177 72 56 200 38 247 219]

解密后明文: hello

4. 数字签名

4.1 简介

数字签名(Digital Signature):

数字签名是一种使用私钥生成的加密哈希值,用于验证消息的真实性和完整性。发送者使用私钥对消息进行哈希运算,然后将哈希值与消息一起发送。接收者使用发送者的公钥来解密哈希值,并与自己重新计算的消息哈希值进行比较。如果两者匹配,那么消息未被篡改,且是由私钥的持有者发送的。

非对称加密(Asymmetric Encryption):

公钥用于加密数据,而私钥用于解密数据。任何拥有公钥的人都可以加密信息,但只有私钥的持有者才能解密它。

区别:

数字签名非对称加密公钥与私钥的使用私钥签名(加密),公钥验证签名(解密)公钥加密,私钥解密用途确保通信的完整性和认证发送者身份确保通信的机密性

4.2 签名

获取私钥签名

// GetPrivateKey

// @Description: 获取私钥

// @param file_path

// @return *rsa.PrivateKey

// @return error

func GetPrivateKey(file_path string) (*rsa.PrivateKey, error) {

failPri := &rsa.PrivateKey{}

/*读取文件*/

file, err := os.Open(file_path)

if err != nil {

return failPri, err

}

defer file.Close()

fileInfo, errFileInfo := file.Stat()

if errFileInfo != nil {

return failPri, errFileInfo

}

private_data := make([]byte, fileInfo.Size())

file.Read(private_data)

/*解码*/

block, _ := pem.Decode(private_data)

privateKey, errPriKey := x509.ParsePKCS1PrivateKey(block.Bytes)

if errPriKey != nil {

return failPri, errPriKey

}

return privateKey, nil

}

// RsaGetSign

// @Description: 使用私钥签名

// @param file_path

// @param src

// @return error

func RsaGetSign(file_path string, src string) ([]byte, error) {

fail := []byte("")

// 获取私钥

privateKey, err := GetPrivateKey(file_path)

if err != nil {

return fail, err

}

src_bytes := []byte(src)

sha256_new := sha256.New()

sha256_new.Write(src_bytes)

sha256_bytes := sha256_new.Sum(nil) // 计算哈希值

//签名

sign, err_sign := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, sha256_bytes)

if err_sign != nil {

return fail, err_sign

}

return sign, nil

}

4.3 验证签名

获取公钥验证签名

// GetPublicKey

// @Description: 获取公钥

// @param file_path

// @return *rsa.PublicKey

// @return error

func GetPublicKey(file_path string) (*rsa.PublicKey, error) {

failPub := &rsa.PublicKey{}

/*读取文件*/

file, err := os.Open(file_path)

if err != nil {

return failPub, err

}

defer file.Close()

fileInfo, errFileInfo := file.Stat()

if errFileInfo != nil {

return failPub, errFileInfo

}

public_data := make([]byte, fileInfo.Size())

file.Read(public_data)

/*解码*/

block, _ := pem.Decode(public_data)

publicKey, errPubKey := x509.ParsePKCS1PublicKey(block.Bytes)

if errPubKey != nil {

return failPub, errPubKey

}

return publicKey, nil

}

//

// RsaVarifySign

// @Description: 使用公钥验证

// @param file_path

// @param src

// @param sign

// @return bool

// @return error

//

func RsaVarifySign(file_path string, src string, sign []byte) (bool, error) {

// 获取公钥

publicKey, err := GetPublicKey(file_path)

if err != nil {

return false, err

}

src_bytes := []byte(src)

sha256_new := sha256.New()

sha256_new.Write(src_bytes)

sha256_bytes := sha256_new.Sum(nil) // 计算哈希值

// 验证签名

err_varify := rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, sha256_bytes, sign)

if err_varify != nil {

return false, err_varify

}

return true, nil

}

4.4 测试签名与验证

func testRsa() {

src := "hello"

sign, err := utils.RsaGetSign("privateKey.pem", src)

if err != nil {

fmt.Println(err)

}

fmt.Println("签名:", sign)

right, err_varify := utils.RsaVarifySign("publicKey.pem", src, sign)

if err_varify != nil {

fmt.Println(err_varify)

}

fmt.Println("签名验证:", right)

}

签名: [140 102 255 209 120 164 93 98 184 14 148 135 84 121 140 144 202 96 7 0 1

53 57 151 181 116 17 41 220 53 60 191 129 178 98 238 143 25 210 26 45 133 159 84

36 5 227 45 105 250 193 152 138 184 107 59 250 223 73 95 122 208 88 154 117 41

178 150 109 141 139 118 35 38 4 81 196 198 73 106 119 145 178 229 57 28 184 43 2

01 176 137 161 75 202 156 172 138 171 230 141 226 75 171 230 170 18 251 201 136

71 65 100 68 3 162 197 250 51 244 192 193 179 131 238 113 198 212 169 238 7 135

129 55 135 124 66 81 138 237 36 49 74 198 39 51 119 243 191 40 46 197 5 17 71 10

9 46 102 84 39 228 220 82 197 172 106 235 30 233 157 140 178 100 224 82 210 52 1

51 254 52 187 143 252 112 190 207 105 59 58 250 124 14 173 91 90 197 157 11 115

186 137 74 132 166 68 59 70 28 34 102 79 40 45 65 20 190 184 6 231 151 158 194 6

2 178 95 83 148 156 192 133 119 218 36 172 125 130 43 158 216 144 218 92 147 243

11 90 13 198 4 30 40 5 15 22 239 180 245 183]

签名验证: true

参考阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: