290 lines
5.8 KiB
Go
290 lines
5.8 KiB
Go
package utils
|
||
|
||
import (
|
||
"encoding/json"
|
||
"strings"
|
||
"log"
|
||
"time"
|
||
"fmt"
|
||
"encoding/pem"
|
||
"crypto/x509"
|
||
"crypto/rsa"
|
||
"encoding/base64"
|
||
"errors"
|
||
"io"
|
||
"net/url"
|
||
"hash/crc32"
|
||
crand "crypto/rand"
|
||
"crypto/hmac"
|
||
"crypto/sha1"
|
||
"crypto/md5"
|
||
)
|
||
|
||
// md5
|
||
func Md5Sum(text string) string {
|
||
h := md5.New()
|
||
io.WriteString(h, text)
|
||
return fmt.Sprintf("%x", h.Sum(nil))
|
||
}
|
||
|
||
// 加解密函数 根据dz的Authcode改写的go版本
|
||
// params[0] 加密or解密 bool true:加密 false:解密 默认false
|
||
// params[1] 秘钥
|
||
// params[2] 加密:过期时间
|
||
// params[3] 动态秘钥长度 默认:4位 不能大于32位
|
||
func Authcode(text string, params ...interface{}) string {
|
||
defer func() {
|
||
if err := recover(); err != nil {
|
||
log.Printf("authcode error:%#v", err)
|
||
}
|
||
}()
|
||
|
||
l := len(params)
|
||
|
||
isEncode := false
|
||
key := "DH-Framework"
|
||
expiry := 0
|
||
cKeyLen := 10
|
||
|
||
if l > 0 {
|
||
isEncode = params[0].(bool)
|
||
}
|
||
|
||
if l > 1 {
|
||
key = params[1].(string)
|
||
}
|
||
|
||
if l > 2 {
|
||
expiry = params[2].(int)
|
||
if expiry < 0 {
|
||
expiry = 0
|
||
}
|
||
}
|
||
|
||
if l > 3 {
|
||
cKeyLen = params[3].(int)
|
||
if cKeyLen < 0 {
|
||
cKeyLen = 0
|
||
}
|
||
}
|
||
if cKeyLen > 32 {
|
||
cKeyLen = 32
|
||
}
|
||
|
||
timestamp := time.Now().Unix()
|
||
|
||
// md5加密key
|
||
mKey := Md5Sum(key)
|
||
|
||
// 参与加密的
|
||
keyA := Md5Sum(mKey[0:16])
|
||
// 用于验证数据有效性的
|
||
keyB := Md5Sum(mKey[16:])
|
||
// 动态部分
|
||
var keyC string
|
||
if cKeyLen > 0 {
|
||
if isEncode {
|
||
// 加密的时候,动态获取一个秘钥
|
||
keyC = Md5Sum(fmt.Sprint(timestamp))[32 - cKeyLen:]
|
||
} else {
|
||
// 解密的时候从头部获取动态秘钥部分
|
||
keyC = text[0:cKeyLen]
|
||
}
|
||
}
|
||
|
||
// 加入了动态的秘钥
|
||
cryptKey := keyA + Md5Sum(keyA + keyC)
|
||
// 秘钥长度
|
||
keyLen := len(cryptKey)
|
||
if isEncode {
|
||
// 加密 前10位是过期验证字符串 10-26位字符串验证
|
||
var d int64
|
||
if expiry > 0 {
|
||
d = timestamp + int64(expiry)
|
||
}
|
||
text = fmt.Sprintf("%010d%s%s", d, Md5Sum(text + keyB)[0:16], text)
|
||
} else {
|
||
// 解密
|
||
text = string(Base64Decode(text[cKeyLen:]))
|
||
}
|
||
|
||
// 字符串长度
|
||
textLen := len(text)
|
||
if textLen <= 0 {
|
||
panic(fmt.Sprintf("auth[%s]textLen<=0", text))
|
||
}
|
||
|
||
// 密匙簿
|
||
box := Range(0, 256)
|
||
// 对称算法
|
||
var rndKey []int
|
||
cryptKeyB := []byte(cryptKey)
|
||
for i := 0; i < 256; i++ {
|
||
pos := i % keyLen
|
||
rndKey = append(rndKey, int(cryptKeyB[pos]))
|
||
}
|
||
|
||
j := 0
|
||
for i := 0; i < 256; i++ {
|
||
j = (j + box[i] + rndKey[i]) % 256
|
||
box[i], box[j] = box[j], box[i]
|
||
}
|
||
|
||
textB := []byte(text)
|
||
a := 0
|
||
j = 0
|
||
var result []byte
|
||
for i := 0; i < textLen; i++ {
|
||
a = (a + 1) % 256
|
||
j = (j + box[a]) % 256
|
||
box[a], box[j] = box[j], box[a]
|
||
result = append(result, byte(int(textB[i]) ^ (box[(box[a] + box[j]) % 256])))
|
||
}
|
||
|
||
if isEncode {
|
||
return keyC + strings.Replace(Base64Encode(result), "=", "", -1)
|
||
}
|
||
|
||
// 获取前10位,判断过期时间
|
||
d := Atoi64(string(result[0:10]), 0)
|
||
if (d == 0 || d - timestamp > 0) && string(result[10:26]) == Md5Sum(string(result[26:]) + keyB)[0:16] {
|
||
return string(result[26:])
|
||
}
|
||
|
||
panic(fmt.Sprintf("auth[%s]", text))
|
||
|
||
return ""
|
||
}
|
||
|
||
// AuthcodeUrl 处理Authcode函数的加密解密结果以便url传输
|
||
func AuthcodeUrl(text string, params ...interface{}) string {
|
||
isEncode := false
|
||
if len(params) > 0 {
|
||
isEncode = params[0].(bool)
|
||
}
|
||
if isEncode { //加密
|
||
return strings.Replace(strings.Replace(Authcode(text, params...), "+", ",", -1), "/", "-", -1)
|
||
} else {
|
||
return Authcode(strings.Replace(strings.Replace(text, ",", "+", -1), "-", "/", -1), params...)
|
||
}
|
||
}
|
||
|
||
// JsonEncode 编码JSON
|
||
func JsonEncode(m interface{}) string {
|
||
b, err := json.Marshal(m)
|
||
if err != nil {
|
||
log.Printf("Json Encode[%#v] Error:%s", m, err.Error())
|
||
return ""
|
||
}
|
||
return string(b)
|
||
}
|
||
|
||
// JsonDecode 解码JSON
|
||
func JsonDecode(str string, v ...interface{}) (interface{}, error) {
|
||
var m interface{}
|
||
if len(v) > 0 {
|
||
m = v[0]
|
||
} else {
|
||
m = make(map[string]interface{})
|
||
}
|
||
|
||
err := json.Unmarshal([]byte(str), &m)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return m, nil
|
||
}
|
||
|
||
func Crc32(text string) string {
|
||
h := crc32.NewIEEE()
|
||
io.WriteString(h, text)
|
||
return fmt.Sprintf("%d", h.Sum32())
|
||
}
|
||
|
||
// RsaEncode rsa加密
|
||
func RsaEncode(b, rsaKey []byte) ([]byte, error) {
|
||
block, _ := pem.Decode(rsaKey)
|
||
if block == nil {
|
||
return b, errors.New("key error")
|
||
}
|
||
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||
if err != nil {
|
||
return b, err
|
||
}
|
||
return rsa.EncryptPKCS1v15(crand.Reader, pub.(*rsa.PublicKey), b)
|
||
}
|
||
|
||
// RsaDecode rsa解密
|
||
func RsaDecode(b, rsaKey []byte) ([]byte, error) {
|
||
block, _ := pem.Decode(rsaKey)
|
||
if block == nil {
|
||
return b, errors.New("key error")
|
||
}
|
||
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
||
if err != nil {
|
||
return b, err
|
||
}
|
||
return rsa.DecryptPKCS1v15(crand.Reader, priv, b)
|
||
}
|
||
|
||
func HashHmac(data, key string) string {
|
||
mac := hmac.New(sha1.New, []byte(key))
|
||
mac.Write([]byte(data))
|
||
return fmt.Sprintf("%x", mac.Sum(nil))
|
||
}
|
||
|
||
func HashHmacRaw(data, key string) string {
|
||
mac := hmac.New(sha1.New, []byte(key))
|
||
mac.Write([]byte(data))
|
||
return fmt.Sprintf("%s", mac.Sum(nil))
|
||
}
|
||
|
||
// Base64Encode Base64编码
|
||
func Base64Encode(b []byte) string {
|
||
return base64.StdEncoding.EncodeToString(b)
|
||
}
|
||
|
||
// Base64Decode Base64解码
|
||
func Base64Decode(str string) []byte {
|
||
var b []byte
|
||
var err error
|
||
x := len(str) * 3 % 4
|
||
switch {
|
||
case x == 2:
|
||
str += "=="
|
||
case x == 1:
|
||
str += "="
|
||
}
|
||
if b, err = base64.StdEncoding.DecodeString(str); err != nil {
|
||
return b
|
||
}
|
||
|
||
return b
|
||
}
|
||
|
||
// UrlEncode 编码
|
||
func UrlEncode(str string) string {
|
||
return url.QueryEscape(str)
|
||
}
|
||
|
||
// UrlDecode 解码
|
||
func UrlDecode(str string) string {
|
||
ret, _ := url.QueryUnescape(str)
|
||
return ret
|
||
}
|
||
|
||
/*func Urlencode(str string) string {
|
||
return base64.URLEncoding.EncodeToString([]byte(str))
|
||
}
|
||
|
||
func Urldecode(str string) string {
|
||
b, e := base64.URLEncoding.DecodeString(str)
|
||
if e != nil {
|
||
log.Printf("urldecode error:%s", e.Error())
|
||
return ""
|
||
}
|
||
|
||
return string(b)
|
||
}*/
|