Initial commit

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 13:57:10 +08:00
co-authored by Claude Opus 5
commit 8679200f41
1897 changed files with 257900 additions and 0 deletions
+137
View File
@@ -0,0 +1,137 @@
package crypt
import (
"91porn-server/common/log"
"91porn-server/web/webg"
"crypto/aes"
"crypto/cipher"
"encoding/hex"
"fmt"
"net/url"
"reflect"
"strings"
)
//const appSecret = "iPEnB74mfCZhNNnY" //(客服后台->产品列表 对应产品的产品密钥) 测试
func CheckSign(sign string, data interface{}, router string) bool {
//对参数进行加密,和sign 进行对比
dataMap, _ := StructToMap(data, router)
params := url.Values{}
for k, v := range dataMap {
params.Set(k, v)
}
mySign, err := GenerateSign(params.Encode(), webg.Conf.Customer.Secret)
if err != nil {
log.Error("CheckSign Generate signature error:", log.Any("Secret", webg.Conf.Customer.Secret), log.E(err))
return false
}
return mySign == sign
}
// StructToMap 将结构体转换为map[string]string
func StructToMap(data interface{}, router string) (map[string]string, error) {
result := make(map[string]string)
// 使用反射获取结构体信息
v := reflect.ValueOf(data)
t := reflect.TypeOf(data)
// 如果是指针,获取指向的元素
if t.Kind() == reflect.Ptr {
v = v.Elem()
t = t.Elem()
}
// 确保是结构体类型
if t.Kind() != reflect.Struct {
return nil, fmt.Errorf("data must be a struct or pointer to struct")
}
// 遍历结构体字段
for i := 0; i < v.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
// 获取json标签作为key
jsonTag := field.Tag.Get("json")
if jsonTag == "" {
// 如果没有json标签,使用字段名
jsonTag = strings.ToLower(field.Name)
}
if router != "" {
if jsonTag == "appId" || jsonTag == "sign" {
continue
}
}
// 获取字段值并转换为字符串
var valueStr string
switch value.Kind() {
case reflect.String:
valueStr = value.String()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
valueStr = fmt.Sprintf("%d", value.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
valueStr = fmt.Sprintf("%d", value.Uint())
case reflect.Bool:
valueStr = fmt.Sprintf("%t", value.Bool())
case reflect.Float32, reflect.Float64:
valueStr = fmt.Sprintf("%f", value.Float())
default:
valueStr = fmt.Sprintf("%v", value.Interface())
}
// 添加到结果中
result[jsonTag] = valueStr
}
return result, nil
}
// PKCS7Padding PKCS7填充
func PKCS7Padding_1(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize
padtext := make([]byte, padding)
for i := range padtext {
padtext[i] = byte(padding)
}
return append(data, padtext...)
}
// AESEncrypt AES-CBC加密
func AESEncrypt(origData, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
// 使用密钥的前16字节作为IV
iv := key[:16]
// PKCS7填充
blockSize := block.BlockSize()
origData = PKCS7Padding_1(origData, blockSize)
// CBC模式加密
mode := cipher.NewCBCEncrypter(block, iv)
crypted := make([]byte, len(origData))
mode.CryptBlocks(crypted, origData)
return crypted, nil
}
// GenerateSign 生成签名
func GenerateSign(data, appSecret string) (string, error) {
key := []byte(appSecret)
plaintext := []byte(data)
ciphertext, err := AESEncrypt(plaintext, key)
if err != nil {
return "", err
}
// 转换为十六进制字符串
hexStr := hex.EncodeToString(ciphertext)
return hexStr, nil
}
+755
View File
@@ -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
}
+49
View File
@@ -0,0 +1,49 @@
package crypt
import (
"bytes"
"testing"
)
// TestCoreAesEncryptDecryptExRoundTrip 校验新增的 CoreAesDecryptEx 与 CoreAesEncryptEx 互逆。
func TestCoreAesEncryptDecryptExRoundTrip(t *testing.T) {
key := "h5-m3u8-ticket-key-roundtrip-000000000000"
plains := [][]byte{
[]byte(""),
[]byte("a"),
[]byte(`{"u":10086,"p":"v3/av/a.m3u8","e":1737000000}`),
bytes.Repeat([]byte("x"), 512),
}
for _, plain := range plains {
enc, err := CoreAesEncryptEx(plain, 12, key)
if err != nil {
t.Fatalf("encrypt: %v", err)
}
dec, err := CoreAesDecryptEx(enc, 12, key)
if err != nil {
t.Fatalf("decrypt: %v", err)
}
if !bytes.Equal(dec, plain) {
t.Fatalf("round trip mismatch: got %q want %q", dec, plain)
}
}
}
// TestCoreAesDecryptExRejectsShort 确保短于 nonce 的非法输入不 panic 且返回错误。
func TestCoreAesDecryptExRejectsShort(t *testing.T) {
if _, err := CoreAesDecryptEx([]byte{1, 2, 3}, 12, "key"); err == nil {
t.Fatal("expected error for input shorter than nonce")
}
}
// TestCoreAesDecryptExWrongKey 用错误密钥解密不应还原出原文。
func TestCoreAesDecryptExWrongKey(t *testing.T) {
enc, err := CoreAesEncryptEx([]byte("secret-payload"), 12, "key-a-000000000000000000000000000000")
if err != nil {
t.Fatalf("encrypt: %v", err)
}
dec, err := CoreAesDecryptEx(enc, 12, "key-b-111111111111111111111111111111")
if err == nil && string(dec) == "secret-payload" {
t.Fatal("wrong key must not recover plaintext")
}
}
+63
View File
@@ -0,0 +1,63 @@
package ecb
import "crypto/cipher"
type ecb struct {
b cipher.Block
blockSize int
}
func newECB(b cipher.Block) *ecb {
return &ecb{
b: b,
blockSize: b.BlockSize(),
}
}
type ecbEncrypter ecb
// NewECBEncrypter returns a BlockMode which encrypts in electronic code book
// mode, using the given Block.
func NewECBEncrypter(b cipher.Block) cipher.BlockMode {
return (*ecbEncrypter)(newECB(b))
}
func (x *ecbEncrypter) BlockSize() int { return x.blockSize }
func (x *ecbEncrypter) CryptBlocks(dst, src []byte) {
if len(src)%x.blockSize != 0 {
panic("crypto/cipher: input not full blocks")
}
if len(dst) < len(src) {
panic("crypto/cipher: output smaller than input")
}
for len(src) > 0 {
x.b.Encrypt(dst, src[:x.blockSize])
src = src[x.blockSize:]
dst = dst[x.blockSize:]
}
}
type ecbDecrypter ecb
// NewECBDecrypter returns a BlockMode which decrypts in electronic code book
// mode, using the given Block.
func NewECBDecrypter(b cipher.Block) cipher.BlockMode {
return (*ecbDecrypter)(newECB(b))
}
func (x *ecbDecrypter) BlockSize() int { return x.blockSize }
func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
if len(src)%x.blockSize != 0 {
panic("crypto/cipher: input not full blocks")
}
if len(dst) < len(src) {
panic("crypto/cipher: output smaller than input")
}
for len(src) > 0 {
x.b.Decrypt(dst, src[:x.blockSize])
src = src[x.blockSize:]
dst = dst[x.blockSize:]
}
}
+140
View File
@@ -0,0 +1,140 @@
package crypt
import (
"bytes"
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"91porn-server/common/log"
)
func splitBytesSlice(data []byte, n int) [][]byte {
var chunk []byte
chunks := make([][]byte, 0, len(data)/n+1)
for len(data) >= n {
chunk, data = data[:n], data[n:]
chunks = append(chunks, chunk)
}
if len(data) > 0 {
chunks = append(chunks, data[:])
}
return chunks
}
func rsaBytesToPublicKey(pub []byte) (*rsa.PublicKey, error) {
block, _ := pem.Decode(pub)
b := block.Bytes
var err error
pk, err := x509.ParsePKIXPublicKey(b)
if err != nil {
log.Error("RSABytesToPublicKey ParsePKIXPublicKey err", log.E(err))
return nil, err
}
if pk_, ok := pk.(*rsa.PublicKey); ok {
return pk_, nil
}
log.Error("RSABytesToPublicKey error input not PublicKey")
return nil, errors.New("Not RSA PublicKey format")
}
func rsaBytesToPrivateKey(priv []byte) (*rsa.PrivateKey, error) {
block, _ := pem.Decode(priv)
b := block.Bytes
var err error
key, err := x509.ParsePKCS8PrivateKey(b)
if err != nil {
log.Error("RSABytesToPrivateKey ParsePKCS8PrivateKey err", log.E(err))
return nil, err
}
if pk_, ok := key.(*rsa.PrivateKey); ok {
return pk_, nil
}
log.Error("RSABytesToPrivateKey error input not PrivateKey")
return nil, errors.New("Not RSA PrivateKey format")
}
// 公钥加密
func RSAEncryptByPublicKey(pemPubKey string, data []byte) ([]byte, error) {
pubKey, err := rsaBytesToPublicKey([]byte(pemPubKey))
if err != nil {
log.Error("RSAEncryptByPublicKey rsaBytesToPublicKey err", log.E(err))
return nil, err
}
partLen := pubKey.N.BitLen()/8 - 11
chunks := splitBytesSlice(data, partLen)
result := bytes.Buffer{}
for _, chunk := range chunks {
cipherSilce, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, chunk)
if err != nil {
log.Error("RSAEncryptByPublicKey EncryptPKCS1v15 err", log.E(err))
return nil, err
}
result.Write(cipherSilce)
}
return result.Bytes(), nil
}
// 私玥签名
func RSASignByPrivateKey(pemPrivateKey string, data []byte, hash crypto.Hash) ([]byte, error) {
privateKey, err := rsaBytesToPrivateKey([]byte(pemPrivateKey))
if err != nil {
log.Error("RSASignByPrivateKey rsaBytesToPrivateKey err", log.E(err))
return nil, err
}
h := hash.New()
h.Write(data)
hashed := make([]byte, 0)
hashed = h.Sum(hashed)
return rsa.SignPKCS1v15(rand.Reader, privateKey, hash, hashed)
}
func RSAVerifyByPublicKey(publicKey string, data, sign []byte, hash crypto.Hash) (err error) {
pubKey, err := rsaBytesToPublicKey([]byte(publicKey))
if err != nil {
log.Error("RSAEncryptByPublicKey rsaBytesToPublicKey err", log.E(err))
return err
}
h := hash.New()
h.Write(data)
hashed := make([]byte, 0)
hashed = h.Sum(hashed)
return rsa.VerifyPKCS1v15(pubKey, hash, hashed, sign)
}
// 公钥解密
func RSADecryptByPrivateKey(pemPrivateKey []byte, cipherData []byte) ([]byte, error) {
privateKey, err := rsaBytesToPrivateKey(pemPrivateKey)
if err != nil {
log.Error("RSADecryptByPrivateKey rsaBytesToPrivateKey err", log.E(err))
return nil, err
}
blockLen := privateKey.N.BitLen() / 8
chunks := splitBytesSlice(cipherData, blockLen)
result := bytes.Buffer{}
for _, chunk := range chunks {
plain, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, chunk)
if err != nil {
log.Error("RSADecryptByPrivateKey DecryptPKCS1v15 err", log.E(err))
return nil, err
}
result.Write(plain)
}
return result.Bytes(), nil
}
// 公钥解密
func RSADecryptByPrivateKey1(pemPrivateKey []byte, cipherData []byte) ([]byte, error) {
block, _ := pem.Decode(pemPrivateKey) //将密钥解析成私钥实例
if block == nil {
return nil, errors.New("private key error!")
}
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) //解析pem.Decode()返回的Block指针实例
if err != nil {
return nil, err
}
return rsa.DecryptPKCS1v15(rand.Reader, priv, cipherData) //RSA算法解密
}