package encipher import ( "bytes" "crypto/aes" "crypto/cipher" "encoding/base64" "encoding/json" "errors" "strings" "time" "git.apinb.com/bsm-sdk/engine/env" "git.apinb.com/bsm-sdk/engine/exception" "git.apinb.com/bsm-sdk/engine/types" "git.apinb.com/bsm-sdk/engine/vars" ) var ( certBytes *types.CertFileBytes = nil JwtSecret []byte JwtSecretLen int ) func New() { JwtSecret = []byte(env.MeshEnv.JwtSecretKey) JwtSecretLen = len(env.MeshEnv.JwtSecretKey) } func GenerateTokenAes(id uint, identity, client, role string, extend map[string]string) (string, error) { if (JwtSecretLen == 16 || JwtSecretLen == 24 || JwtSecretLen == 32) == false { return "", errors.New("JwtSecret lenght must 16/24/32.") } expireTime := time.Now().Add(vars.JwtExpireDay) claims := types.JwtClaims{ ID: id, Identity: identity, Extend: extend, Client: client, Role: role, ExpiresAt: expireTime.Unix(), } byte, err := json.Marshal(claims) if err != nil { return "", err } token, err := AesEncryptCBC(byte) if err != nil { return "", err } return token, nil } func AesEncryptCBC(plan []byte) (string, error) { // 分组秘钥 // NewCipher该函数限制了输入k的长度必须为16, 24或者32 block, _ := aes.NewCipher(JwtSecret) // 获取秘钥块的长度 blockSize := block.BlockSize() // 补全码 plan = PKCS7Padding(plan, blockSize) // 加密模式 blockMode := cipher.NewCBCEncrypter(block, JwtSecret[:blockSize]) // 创建数组 cryted := make([]byte, len(plan)) // 加密 blockMode.CryptBlocks(cryted, plan) return base64.StdEncoding.EncodeToString(cryted), nil } func AesDecryptCBC(cryted string) (b []byte, err error) { if (JwtSecretLen == 16 || JwtSecretLen == 24 || JwtSecretLen == 32) == false { return b, errors.New("JwtSecret lenght must 16/24/32.") } // 转成字节数组 crytedByte, err := base64.StdEncoding.DecodeString(cryted) if err != nil { return } // 分组秘钥 block, err := aes.NewCipher(JwtSecret) if err != nil { return } // 获取秘钥块的长度 blockSize := block.BlockSize() // 加密模式 blockMode := cipher.NewCBCDecrypter(block, JwtSecret[:blockSize]) // 创建数组 orig := make([]byte, len(crytedByte)) // 解密 blockMode.CryptBlocks(orig, crytedByte) // 去补全码 orig = PKCS7UnPadding(orig, blockSize) if orig == nil { return nil, exception.ErrAuthParseFail } return orig, nil } func PKCS7Padding(ciphertext []byte, blocksize int) []byte { padding := blocksize - len(ciphertext)%blocksize padtext := bytes.Repeat([]byte{byte(padding)}, padding) return append(ciphertext, padtext...) } // 去码 // bug:runtime error: slice bounds out of range [:-22] func PKCS7UnPadding(origData []byte, blocksize int) []byte { if blocksize <= 0 { return nil } if origData == nil || len(origData) == 0 { return nil } if len(origData)%blocksize != 0 { return nil } length := len(origData) unpadding := int(origData[length-1]) if length-unpadding <= 0 { return nil } return origData[:(length - unpadding)] } func ParseTokenAes(token string) (*types.JwtClaims, error) { token = strings.TrimSpace(token) data, err := AesDecryptCBC(token) if err != nil { return nil, err } var ac *types.JwtClaims err = json.Unmarshal(data, &ac) if err != nil { return nil, exception.ErrAuthParseFail } expireTime := time.Now().Unix() if expireTime > ac.ExpiresAt { return nil, exception.ErrAuthExpire } return ac, nil }