@@ -0,0 +1,755 @@
|
||||
package crypt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/hmac"
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"io"
|
||||
"net/url"
|
||||
"os"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"91porn-server/common/crypt/ecb"
|
||||
sli "91porn-server/common/slice"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
)
|
||||
|
||||
// CreateToken 生成Token算法
|
||||
func CreateToken(secret string, tokenClaims map[string]interface{}) (tokeness string, err error) {
|
||||
if secret == "" {
|
||||
return "", errors.New("secret is empty")
|
||||
}
|
||||
claims := jwt.MapClaims(tokenClaims)
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
return token.SignedString([]byte(secret))
|
||||
}
|
||||
|
||||
func keyFunc(secret string) jwt.Keyfunc {
|
||||
return func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(secret), nil
|
||||
}
|
||||
}
|
||||
|
||||
// ParseToken 解析Token
|
||||
func ParseToken(secret string, tokeness string) (map[string]interface{}, error) {
|
||||
if secret == "" || tokeness == "" {
|
||||
return nil, errors.New("secret or tokeness is empty")
|
||||
}
|
||||
token, err := jwt.Parse(tokeness, keyFunc(secret))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//验证token,如果token被修改过则为false
|
||||
if !token.Valid {
|
||||
return nil, errors.New("token is invalid")
|
||||
}
|
||||
claimsToken, ok := token.Claims.(jwt.MapClaims)
|
||||
if !ok {
|
||||
return nil, errors.New("cannot convert claim to MapClaim")
|
||||
}
|
||||
return claimsToken, nil
|
||||
}
|
||||
|
||||
// StructToStr 结构体转json 先对结构体按照字典顺序排序 并返回字符串
|
||||
func StructToStr(obj interface{}) (string, error) {
|
||||
if obj == nil {
|
||||
return "", errors.New("obj is not nil")
|
||||
}
|
||||
data := make(map[string]interface{})
|
||||
bytes, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err = json.Unmarshal(bytes, &data); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return MapToStr(data)
|
||||
}
|
||||
|
||||
func JsonStr2Str(str string, key ...string) string {
|
||||
if str == "" {
|
||||
return ""
|
||||
}
|
||||
mapstr, err := JSON2Map(str)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
sortStr, err := MapToStrSkipObject(mapstr, key...)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return sortStr
|
||||
}
|
||||
|
||||
func Obj2Obj(src, dest interface{}) error {
|
||||
data, err := json.Marshal(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(data, dest)
|
||||
}
|
||||
|
||||
// MapToStr 对map按照字典顺序排序 并返回字符串
|
||||
func MapToStr(data map[string]interface{}) (string, error) {
|
||||
if len(data) == 0 {
|
||||
return "", errors.New("data is nil or empty")
|
||||
}
|
||||
newData := make(map[string]interface{})
|
||||
keys := make([]string, 0, len(data))
|
||||
for k := range data {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
newData[k] = data[k]
|
||||
}
|
||||
b, err := json.Marshal(newData)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
// MapToStr 对map按照字典顺序排序 并返回字符串 对value是对象 map list 类型的key 过滤掉
|
||||
func MapToStrSkipObject(data map[string]interface{}, key ...string) (string, error) {
|
||||
if len(data) == 0 {
|
||||
return "", errors.New("data is nil or empty")
|
||||
}
|
||||
newData := make(map[string]interface{})
|
||||
keys := make([]string, 0, len(data))
|
||||
for k := range data {
|
||||
if sli.Contains(key, k) {
|
||||
continue
|
||||
}
|
||||
t := reflect.TypeOf(data[k])
|
||||
if t != nil {
|
||||
tkind := t.Kind()
|
||||
if tkind == reflect.Map || tkind == reflect.Slice || tkind == reflect.Array || tkind == reflect.Struct {
|
||||
continue
|
||||
}
|
||||
keys = append(keys, k)
|
||||
}
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
newData[k] = data[k]
|
||||
}
|
||||
b, err := json.Marshal(newData)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
// JSON2Struct json转struct
|
||||
func JSON2Struct(str string, obj interface{}) error {
|
||||
return json.Unmarshal([]byte(str), &obj)
|
||||
}
|
||||
|
||||
// JSONArray2Struct json转struct
|
||||
func JSONArray2Struct(str []string, obj interface{}) []interface{} {
|
||||
data := make([]interface{}, len(str))
|
||||
for i, v := range str {
|
||||
_ = JSON2Struct(v, &obj)
|
||||
data[i] = obj
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// JSON2Map json转map
|
||||
func JSON2Map(str string) (map[string]interface{}, error) {
|
||||
var mapResult map[string]interface{}
|
||||
return mapResult, json.Unmarshal([]byte(str), &mapResult)
|
||||
}
|
||||
|
||||
// StructToStrNormal 结构体转str
|
||||
func StructToStrNormal(obj interface{}) (string, error) {
|
||||
str, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(str), nil
|
||||
}
|
||||
|
||||
func UrlValueToStr(values url.Values, exclude string) (string, string) {
|
||||
if values == nil {
|
||||
return "", ""
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
var sign string
|
||||
keys := make([]string, 0, len(values))
|
||||
for k := range values {
|
||||
if k == exclude {
|
||||
sign = strings.Join(values[k], "")
|
||||
continue
|
||||
}
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for i, k := range keys {
|
||||
if i != 0 {
|
||||
buf.WriteString("&")
|
||||
}
|
||||
buf.WriteString(k)
|
||||
buf.WriteString("=")
|
||||
buf.WriteString(strings.Join(values[k], ""))
|
||||
}
|
||||
return buf.String(), sign
|
||||
}
|
||||
|
||||
// 对参数进行排序后 拼接成url字符串 只对一级字符串类型的参数做处理
|
||||
func MapToUrlOnlyStr(data map[string]interface{}) string {
|
||||
if len(data) == 0 {
|
||||
return ""
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
keys := make([]string, len(data))
|
||||
i := 0
|
||||
for k := range data {
|
||||
keys[i] = k
|
||||
i++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for i, k := range keys {
|
||||
if i != 0 {
|
||||
buf.WriteString("&")
|
||||
}
|
||||
buf.WriteString(k)
|
||||
buf.WriteString("=")
|
||||
if v, ok := data[k].(string); ok {
|
||||
buf.WriteString(v)
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// MapToStr 对map按照字典顺序排序 并返回字符串url 拼接的字段
|
||||
func MapToUrlStr(data map[string]interface{}) string {
|
||||
if len(data) == 0 {
|
||||
return ""
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
keys := make([]string, len(data))
|
||||
i := 0
|
||||
for k := range data {
|
||||
keys[i] = k
|
||||
i++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for i, k := range keys {
|
||||
if i != 0 {
|
||||
buf.WriteString("&")
|
||||
}
|
||||
buf.WriteString(k)
|
||||
buf.WriteString("=")
|
||||
if v, ok := data[k].(string); ok {
|
||||
buf.WriteString(v)
|
||||
continue
|
||||
}
|
||||
t := reflect.TypeOf(data[k])
|
||||
if t != nil && t.Kind() == reflect.Map {
|
||||
if v, ok := data[k].(map[string]interface{}); ok {
|
||||
buf.WriteString("{")
|
||||
str := MapToUrlStr(v)
|
||||
buf.WriteString(str)
|
||||
buf.WriteString("}")
|
||||
}
|
||||
}
|
||||
if t != nil && (t.Kind() == reflect.Slice || t.Kind() == reflect.Array) {
|
||||
arraybyte, _ := json.Marshal(data[k])
|
||||
buf.WriteString(string(arraybyte))
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// MapToURL 集合转URL
|
||||
func MapToURL(m map[string]string) string {
|
||||
if len(m) == 0 {
|
||||
return ""
|
||||
}
|
||||
v := url.Values{}
|
||||
for k := range m {
|
||||
v.Set(k, string(m[k]))
|
||||
}
|
||||
return v.Encode()
|
||||
}
|
||||
|
||||
func Strcut2UrlValue(obj interface{}) (string, error) {
|
||||
t := reflect.TypeOf(obj)
|
||||
v := reflect.ValueOf(obj)
|
||||
if t.Kind() != reflect.Struct {
|
||||
return "", errors.New("obj must be struct type")
|
||||
}
|
||||
u := url.Values{}
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
var value string
|
||||
tag := t.Field(i).Tag.Get("json")
|
||||
switch t.Field(i).Type.Kind() {
|
||||
case reflect.String:
|
||||
value = v.Field(i).String()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
value = strconv.Itoa(int(v.Field(i).Int()))
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
value = strconv.FormatUint(v.Field(i).Uint(), 10)
|
||||
case reflect.Slice, reflect.Array:
|
||||
buf := bytes.Buffer{}
|
||||
b, _ := json.Marshal(v.Field(i).Interface())
|
||||
t := strings.TrimRight(strings.TrimLeft(string(b), "["), "]")
|
||||
array := strings.Split(t, ",")
|
||||
if len(array) == 0 {
|
||||
value = ""
|
||||
}
|
||||
if len(array) == 1 {
|
||||
value = array[0]
|
||||
} else {
|
||||
for i, v := range array {
|
||||
if i == 0 {
|
||||
buf.WriteString(v)
|
||||
continue
|
||||
}
|
||||
buf.WriteString("&")
|
||||
buf.WriteString(tag)
|
||||
buf.WriteString("=")
|
||||
buf.WriteString(v)
|
||||
value = buf.String()
|
||||
}
|
||||
}
|
||||
}
|
||||
u.Add(tag, value)
|
||||
}
|
||||
dcodeurl, err := url.QueryUnescape(u.Encode())
|
||||
return dcodeurl, err
|
||||
}
|
||||
|
||||
// StrToMd5 字符串转md5
|
||||
func StrToMd5(str string) string {
|
||||
data := []byte(str)
|
||||
return ByteToMd5(data)
|
||||
}
|
||||
|
||||
// ByteToMd5 数组转md5
|
||||
func ByteToMd5(data []byte) string {
|
||||
md5Ctx := md5.New()
|
||||
md5Ctx.Write(data)
|
||||
cipherStr := md5Ctx.Sum(nil)
|
||||
return hex.EncodeToString(cipherStr)
|
||||
}
|
||||
|
||||
// FileToMd5 文件转MD5
|
||||
func FileToMd5(fileName string) string {
|
||||
file, err := os.Open(fileName)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
//defer file.Close()
|
||||
md5Ctx := md5.New()
|
||||
if _, err := io.Copy(md5Ctx, file); err != nil {
|
||||
return ""
|
||||
}
|
||||
cipherStr := md5Ctx.Sum(nil)
|
||||
return hex.EncodeToString(cipherStr)
|
||||
}
|
||||
|
||||
// HashCode 对一个字符串生成唯一的hasHcode 码
|
||||
func HashCode(src string) int {
|
||||
v := int(crc32.ChecksumIEEE([]byte(src)))
|
||||
if v < 0 {
|
||||
return -v
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// HexToString converts
|
||||
func HexToString(data []byte) string {
|
||||
return hex.EncodeToString(data)
|
||||
}
|
||||
|
||||
// StrToSha256 字符串转sha256
|
||||
func StrToSha256(str string) string {
|
||||
shaCtx := sha256.New()
|
||||
shaCtx.Write([]byte(str))
|
||||
shaBytes := shaCtx.Sum(nil)
|
||||
cipherStr := hex.EncodeToString(shaBytes[:])
|
||||
return cipherStr
|
||||
}
|
||||
|
||||
// StrToSha1 字符串转sha1
|
||||
func StrToSha1(str string, secret string) []byte {
|
||||
h := hmac.New(sha1.New, []byte(secret))
|
||||
h.Write([]byte(str))
|
||||
return h.Sum(nil)
|
||||
}
|
||||
|
||||
// StrToSha1 字符串转sha1 转16进制后
|
||||
func StrToHmacSha1(str, secret string) string {
|
||||
return hex.EncodeToString(StrToSha1(str, secret))
|
||||
}
|
||||
|
||||
// StrToHmacSha256 加密 字符串转sha256加密字符串
|
||||
func StrToHmacSha256(str string, secret string) string {
|
||||
h := hmac.New(sha256.New, []byte(secret))
|
||||
h.Write([]byte(str))
|
||||
cipherStr := hex.EncodeToString(h.Sum(nil))
|
||||
return cipherStr
|
||||
}
|
||||
|
||||
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
|
||||
padding := blockSize - len(ciphertext)%blockSize
|
||||
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||
return append(ciphertext, padtext...)
|
||||
}
|
||||
|
||||
func PKCS7UnPadding(origData []byte) []byte {
|
||||
length := len(origData)
|
||||
unpadding := int(origData[length-1])
|
||||
return origData[:(length - unpadding)]
|
||||
}
|
||||
|
||||
// AesEncrypt AES加密
|
||||
func AesEncrypt(origData, key string) ([]byte, error) {
|
||||
origDataByte := []byte(origData)
|
||||
return CoreAesEncrypt(origDataByte, key)
|
||||
}
|
||||
|
||||
// AesDecrypt AES解密
|
||||
func AesDecrypt(crypted, key string) (string, error) {
|
||||
cryptedByte := []byte(crypted)
|
||||
return CoreAesDecrypt(cryptedByte, key)
|
||||
}
|
||||
|
||||
// CoreAesEncrypt AES加密
|
||||
func CoreAesEncrypt(origData []byte, key string) ([]byte, error) {
|
||||
keybyte := []byte(key)
|
||||
block, err := aes.NewCipher(keybyte)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blockSize := block.BlockSize()
|
||||
origData = PKCS7Padding(origData, blockSize)
|
||||
blockMode := cipher.NewCBCEncrypter(block, keybyte[:blockSize])
|
||||
crypted := make([]byte, len(origData))
|
||||
blockMode.CryptBlocks(crypted, origData)
|
||||
return crypted, nil
|
||||
}
|
||||
|
||||
// https://core.telegram.org/api/end-to-end#sending-and-receiving-messages-in-a-secret-chat
|
||||
func CoreAesEncryptEx(plain []byte, nonceLen int, key string) ([]byte, error) {
|
||||
nonce := make([]byte, nonceLen)
|
||||
_, err := io.ReadFull(rand.Reader, nonce)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var largeShaRaw []byte
|
||||
largeShaRaw = append(largeShaRaw, []byte(key)...)
|
||||
largeShaRaw = append(largeShaRaw, nonce...)
|
||||
largeShaRawMid := len(largeShaRaw) / 2
|
||||
msgKeyLarge := sha256.Sum256(largeShaRaw)
|
||||
msgKey := msgKeyLarge[8:24] //16 bytes
|
||||
|
||||
var shaRawA []byte
|
||||
shaRawA = append(shaRawA, msgKey...)
|
||||
shaRawA = append(shaRawA, largeShaRaw[:largeShaRawMid]...)
|
||||
sha256a := sha256.Sum256(shaRawA) //32 bytes
|
||||
|
||||
var shaRawB []byte
|
||||
shaRawB = append(shaRawB, largeShaRaw[largeShaRawMid:]...)
|
||||
shaRawB = append(shaRawB, msgKey...)
|
||||
sha256b := sha256.Sum256(shaRawB) //32 bytes
|
||||
|
||||
var aesKey []byte //32 bytes AES-256
|
||||
aesKey = append(aesKey, sha256a[:8]...) //a: 8 bytes
|
||||
aesKey = append(aesKey, sha256b[8:24]...) //b: 16 bytes
|
||||
aesKey = append(aesKey, sha256a[24:32]...) //a: 8 bytes
|
||||
|
||||
var aesIV []byte // 16 bytes
|
||||
aesIV = append(aesIV, sha256b[:4]...) //b: 4 bytes
|
||||
aesIV = append(aesIV, sha256a[12:20]...) //a: 8 bytes
|
||||
aesIV = append(aesIV, sha256b[28:]...) //b: 4 bytes
|
||||
|
||||
block, err := aes.NewCipher(aesKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blockSize := block.BlockSize()
|
||||
ciphertext := PKCS7Padding(plain, blockSize)
|
||||
mode := cipher.NewCBCEncrypter(block, aesIV)
|
||||
cipher := make([]byte, nonceLen+len(ciphertext))
|
||||
copy(cipher, nonce)
|
||||
mode.CryptBlocks(cipher[nonceLen:], ciphertext)
|
||||
return cipher, nil
|
||||
}
|
||||
|
||||
// CoreAesDecryptEx 是 CoreAesEncryptEx 的逆运算。
|
||||
// 入参 crypt 前 nonceLen 字节为随机 nonce,其余为 CBC 密文;密钥派生与加密端完全一致。
|
||||
// 由于 crypt 可能来自不可信输入(如客户端伪造的票据),这里对长度和分组边界做了保护,避免切片或 CBC 解密 panic。
|
||||
func CoreAesDecryptEx(crypt []byte, nonceLen int, key string) ([]byte, error) {
|
||||
if nonceLen < 0 || len(crypt) < nonceLen {
|
||||
return nil, errors.New("CoreAesDecryptEx: ciphertext shorter than nonce")
|
||||
}
|
||||
nonce := make([]byte, nonceLen)
|
||||
copy(nonce, crypt)
|
||||
var largeShaRaw []byte
|
||||
largeShaRaw = append(largeShaRaw, []byte(key)...)
|
||||
largeShaRaw = append(largeShaRaw, nonce...)
|
||||
largeShaRawMid := len(largeShaRaw) / 2
|
||||
msgKeyLarge := sha256.Sum256(largeShaRaw)
|
||||
msgKey := msgKeyLarge[8:24] //16 bytes
|
||||
|
||||
var shaRawA []byte
|
||||
shaRawA = append(shaRawA, msgKey...)
|
||||
shaRawA = append(shaRawA, largeShaRaw[:largeShaRawMid]...)
|
||||
sha256a := sha256.Sum256(shaRawA) //32 bytes
|
||||
|
||||
var shaRawB []byte
|
||||
shaRawB = append(shaRawB, largeShaRaw[largeShaRawMid:]...)
|
||||
shaRawB = append(shaRawB, msgKey...)
|
||||
sha256b := sha256.Sum256(shaRawB) //32 bytes
|
||||
|
||||
var aesKey []byte //32 bytes AES-256
|
||||
aesKey = append(aesKey, sha256a[:8]...) //a: 8 bytes
|
||||
aesKey = append(aesKey, sha256b[8:24]...) //b: 16 bytes
|
||||
aesKey = append(aesKey, sha256a[24:32]...) //a: 8 bytes
|
||||
|
||||
var aesIV []byte // 16 bytes
|
||||
aesIV = append(aesIV, sha256b[:4]...) //b: 4 bytes
|
||||
aesIV = append(aesIV, sha256a[12:20]...) //a: 8 bytes
|
||||
aesIV = append(aesIV, sha256b[28:]...) //b: 4 bytes
|
||||
|
||||
block, err := aes.NewCipher(aesKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
realData := crypt[nonceLen:]
|
||||
blockSize := block.BlockSize()
|
||||
if len(realData) == 0 || len(realData)%blockSize != 0 {
|
||||
return nil, errors.New("CoreAesDecryptEx: ciphertext is not a multiple of block size")
|
||||
}
|
||||
blockMode := cipher.NewCBCDecrypter(block, aesIV)
|
||||
origData := make([]byte, len(realData))
|
||||
blockMode.CryptBlocks(origData, realData)
|
||||
// 用带校验的 PKCS7 去填充:错误密钥/损坏数据几乎必然产生非法填充,这里返回错误而非 panic,
|
||||
// 也顺带充当一次完整性校验(共享的 PKCS7UnPadding 在非法填充时会越界 panic,故不复用)。
|
||||
return pkcs7UnpadSafe(origData, blockSize)
|
||||
}
|
||||
|
||||
// pkcs7UnpadSafe 校验并剥离 PKCS7 填充,非法填充返回错误而不 panic。
|
||||
func pkcs7UnpadSafe(data []byte, blockSize int) ([]byte, error) {
|
||||
length := len(data)
|
||||
if length == 0 || length%blockSize != 0 {
|
||||
return nil, errors.New("invalid PKCS7 padding: bad length")
|
||||
}
|
||||
pad := int(data[length-1])
|
||||
if pad <= 0 || pad > blockSize || pad > length {
|
||||
return nil, errors.New("invalid PKCS7 padding: bad size")
|
||||
}
|
||||
for _, b := range data[length-pad:] {
|
||||
if int(b) != pad {
|
||||
return nil, errors.New("invalid PKCS7 padding: inconsistent bytes")
|
||||
}
|
||||
}
|
||||
return data[:length-pad], nil
|
||||
}
|
||||
|
||||
// CoreAesDecrypt AES解密
|
||||
func CoreAesDecrypt(crypted []byte, key string) (s string, err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = fmt.Errorf("CoreAesDecrypt is panic. crypted:%s,key:%s", string(crypted), key)
|
||||
return
|
||||
}
|
||||
}()
|
||||
keybyte := []byte(key)
|
||||
block, err := aes.NewCipher(keybyte)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
blockSize := block.BlockSize()
|
||||
if blockSize < 0 {
|
||||
return "", errors.New("blockSize less than zero")
|
||||
}
|
||||
blockMode := cipher.NewCBCDecrypter(block, keybyte[:blockSize])
|
||||
origData := make([]byte, len(crypted))
|
||||
blockMode.CryptBlocks(origData, crypted)
|
||||
origData = PKCS7UnPadding(origData)
|
||||
return string(origData), nil
|
||||
}
|
||||
|
||||
// XorEnc
|
||||
func XorEnc(src string, xorKey string) string {
|
||||
var result string
|
||||
j := 0
|
||||
bt := []rune(src)
|
||||
xor := []rune(xorKey)
|
||||
for i := 0; i < len(bt); i++ {
|
||||
s := strconv.FormatInt(int64(bt[i]^xor[j]), 10)
|
||||
result = result + s
|
||||
j = 1 % len(xor)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// XorDec
|
||||
func XorDec(src string, xorKey string) string {
|
||||
var result string
|
||||
j := 0
|
||||
bt := []rune(src)
|
||||
xor := []rune(xorKey)
|
||||
for i := 0; i < len(bt); i++ {
|
||||
s := strconv.FormatInt(int64(bt[i]^xor[j]), 10)
|
||||
result = result + s
|
||||
j = i % len(xor)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func XorDecode(src, key string) string {
|
||||
srcByte, _ := base64.StdEncoding.DecodeString(src)
|
||||
keyByte, _ := base64.StdEncoding.DecodeString(key)
|
||||
srcByte = xor(srcByte, keyByte)
|
||||
return base64.StdEncoding.EncodeToString(srcByte)
|
||||
}
|
||||
|
||||
func XorEncode(src, key string) string {
|
||||
return XorDecode(src, key)
|
||||
}
|
||||
|
||||
func xor(src []byte, key []byte) []byte {
|
||||
for i := 0; i < len(src); i++ {
|
||||
src[i] ^= key[i%len(key)]
|
||||
}
|
||||
return src
|
||||
}
|
||||
|
||||
func XORLength(src []byte, key []byte, length int) []byte {
|
||||
for i := 0; i < length; i++ {
|
||||
src[i] ^= key[i%len(key)]
|
||||
}
|
||||
return src[:length]
|
||||
}
|
||||
|
||||
// ECB PKCS5 加密
|
||||
func AESECBEncrypt(src, key []byte) []byte {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
fmt.Printf("txn put fail: %v", err)
|
||||
return nil
|
||||
}
|
||||
ecbMod := ecb.NewECBEncrypter(block)
|
||||
content := PKCS5Padding(src, block.BlockSize())
|
||||
des := make([]byte, len(content))
|
||||
ecbMod.CryptBlocks(des, content)
|
||||
return des
|
||||
}
|
||||
|
||||
// ECB PKCS5 解密
|
||||
func AESECBDecrypt(encrypted, key []byte) []byte {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
fmt.Printf("decrypt fail: %v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
ecbMod := ecb.NewECBDecrypter(block)
|
||||
des := make([]byte, len(encrypted))
|
||||
ecbMod.CryptBlocks(des, encrypted)
|
||||
|
||||
// 去除 PKCS5 填充
|
||||
result := PKCS5UnPadding(des)
|
||||
return result
|
||||
}
|
||||
|
||||
// PKCS5UnPadding
|
||||
func PKCS5UnPadding(origData []byte) []byte {
|
||||
length := len(origData)
|
||||
// 去掉最后一个字节 unpadding 次
|
||||
unpadding := int(origData[length-1])
|
||||
if unpadding > length {
|
||||
return origData
|
||||
}
|
||||
return origData[:(length - unpadding)]
|
||||
}
|
||||
|
||||
// PKCS5Padding
|
||||
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
|
||||
padding := blockSize - len(ciphertext)%blockSize
|
||||
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||
return append(ciphertext, padtext...)
|
||||
}
|
||||
|
||||
// 加密
|
||||
func AESCBCPck5Encrypt(origData, key []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blockSize := block.BlockSize()
|
||||
origData = PKCS5Padding(origData, blockSize)
|
||||
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
|
||||
crypted := make([]byte, len(origData))
|
||||
blockMode.CryptBlocks(crypted, origData)
|
||||
return crypted, nil
|
||||
}
|
||||
|
||||
// base64补全
|
||||
func padding(origin string) string {
|
||||
missing := len(origin) % 4
|
||||
if missing != 0 {
|
||||
origin += strings.Repeat("=", 4-missing)
|
||||
}
|
||||
|
||||
return origin
|
||||
}
|
||||
|
||||
// AdDecrypt 集团广告中心-广告数据解密专用
|
||||
func AdDecrypt(encryptedData, keyBase64 string) (res string, err error) {
|
||||
// 1. Base64 解码获取密钥
|
||||
keyBytes, err := base64.StdEncoding.DecodeString(padding(keyBase64))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("密钥 Base64 解码失败: %v", err)
|
||||
}
|
||||
// 2. Base64 解码获取加密数据
|
||||
data, err := base64.StdEncoding.DecodeString(padding(encryptedData))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("数据 Base64 解码失败: %v", err)
|
||||
}
|
||||
|
||||
// 3. 拆分 IV 与密文(前 12 字节为 IV)
|
||||
if len(data) < 12 {
|
||||
return "", errors.New("数据长度不足,无法提取 IV")
|
||||
}
|
||||
iv := data[:12]
|
||||
ciphertext := data[12:]
|
||||
// 4. 初始化 AES 密码块
|
||||
block, err := aes.NewCipher(keyBytes)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("创建 AES 密码块失败: %v", err)
|
||||
}
|
||||
// 5. 采用 GCM 模式
|
||||
aesGCM, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("创建 GCM 失败: %v", err)
|
||||
}
|
||||
// 6. 解密数据
|
||||
plainText, err := aesGCM.Open(nil, iv, ciphertext, nil)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("解密失败: %v", err)
|
||||
}
|
||||
|
||||
return string(plainText), nil
|
||||
}
|
||||
Reference in New Issue
Block a user