1. 前言
参考Php中加密自增ID:
https://www.misiai.com/articles/12.html
注意:上面这篇文章是转自知乎的一篇文章
然后这里用Go实现了:
package main
import (
"bytes"
"errors"
"fmt"
"math/rand"
"strconv"
"strings"
"time"
)
//下面为测试
func main() {
s, err := encode(98959656)
fmt.Println(s, err)
i, err := decode(s)
fmt.Println(i, err)
}
const key = "YourSecretForThis"
/*
这个算法第一个字符是随机的从密钥中获取一个字符串,
最后一个字符是验证字符,是利用(密钥长度-随机数+给定ID长度)%密钥长度
中间部分就是:每位转换成16进制的ID数字+随机数,然后取余key的长度,得到的数字就是该位在key的字符,加入到总加密后的字符串中
*/
func encode(id int64) (string, error) {
// 16进制数组
hexArr := strings.Split(strconv.FormatInt(id, 16), "")
keyArr := strings.Split(key, "")
keyLen := len(key)
rand.Seed(time.Now().UnixNano())
rnd := rand.Intn(keyLen - 1)
str := keyArr[rnd]
verify := keyArr[(keyLen-rnd+len(strconv.FormatInt(id, 10)))%keyLen]
var buf bytes.Buffer
buf.WriteString(str)
for _, h := range hexArr {
hi, err := strconv.ParseInt(h, 16, 64)
if err != nil {
return "", err
}
offset := int(hi) + rnd
buf.WriteString(keyArr[offset%keyLen])
}
buf.WriteString(verify) // 写入验证码
return buf.String(), nil
}
func decode(str string) (int64, error) {
strArr := strings.Split(str, "")
keyArr := strings.Split(key, "")
keyLen := len(key)
rnd := strings.Index(key, strArr[0])
verify := strArr[len(strArr)-1]
strArr = strArr[1 : len(strArr)-1]
var buf bytes.Buffer
for _, s := range strArr {
pos := strings.Index(key, s)
if pos >= rnd {
buf.WriteString(strconv.FormatInt(int64(pos-rnd), 16))
} else {
buf.WriteString(strconv.FormatInt(int64(keyLen-rnd+pos), 16))
}
}
dec, err := strconv.ParseInt(buf.String(), 16, 64)
if err != nil {
return 0, err
}
if verify != keyArr[(keyLen-rnd+len(strconv.FormatInt(dec, 10)))%keyLen] {
return 0, errors.New("校验错误,给定字符串不合法")
}
return dec, nil
}
用Go实现这种简单算法还是蛮有意思的
之前喜欢PHP的一个重要原因就是,PHP中有很多开箱自用的函数,且都很易于使用
Go也是这样,自带的标准库给了很多开箱即用的函数,点个赞!?