From 8691ecadc311ef27af5035fcb5ad29820783a3b5 Mon Sep 17 00:00:00 2001 From: zhaoxiaorong Date: Fri, 7 Feb 2025 14:05:18 +0800 Subject: [PATCH] encipher --- cmd/service.go | 36 +++++++++++ crypto/encipher.go | 154 +++++++++++++++++++++++++++++++++++++++++++++ errcode/errcode.go | 16 +++++ 3 files changed, 206 insertions(+) create mode 100644 cmd/service.go create mode 100644 crypto/encipher.go diff --git a/cmd/service.go b/cmd/service.go new file mode 100644 index 0000000..a927776 --- /dev/null +++ b/cmd/service.go @@ -0,0 +1,36 @@ +package cmd + +import ( + "fmt" + "os" + "strings" + + "git.apinb.com/bsm-sdk/core/vars" +) + +func NewCmd() { + if len(os.Args) > 1 { + parseArgs(os.Args[1]) + } +} + +func parseArgs(cmd string) { + cmd = strings.ToLower(cmd) + switch cmd { + case "-v", "--v", "-version", "--version": + versionCmd() + case "--json": + versionCmdJson() + } + + os.Exit(0) +} + +func versionCmd() { + fmt.Printf("[Blocks Service: %s] Version: %s \n", vars.ServiceKey, vars.VERSION) + fmt.Printf("[Blocks Service: %s] Compile: %s by %s build.\n", vars.ServiceKey, vars.GO_VERSION, vars.BUILD_TIME) +} + +func versionCmdJson() { + fmt.Printf("{\"version\":\"%s\",\"build_time\":\"%s\"}\n", vars.VERSION, vars.BUILD_TIME) +} diff --git a/crypto/encipher.go b/crypto/encipher.go new file mode 100644 index 0000000..9c6880a --- /dev/null +++ b/crypto/encipher.go @@ -0,0 +1,154 @@ +package encipher + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "encoding/base64" + "encoding/json" + "strings" + "time" + + "git.apinb.com/bsm-sdk/core/env" + "git.apinb.com/bsm-sdk/core/errcode" + "git.apinb.com/bsm-sdk/core/types" + "git.apinb.com/bsm-sdk/core/vars" +) + +var ( + certBytes *types.CertFileBytes = nil + JwtSecret []byte + JwtSecretLen int +) + +func New(token string) { + JwtSecret = []byte(token) + JwtSecretLen = len(env.MeshEnv.JwtSecretKey) +} + +func GenerateTokenAes(id uint, identity, client, role string, owner any, extend map[string]string) (string, error) { + if (JwtSecretLen == 16 || JwtSecretLen == 24 || JwtSecretLen == 32) == false { + return "", errcode.ErrAuthSecret + } + expireTime := time.Now().Add(vars.JwtExpireDay) + claims := types.JwtClaims{ + ID: id, + Identity: identity, + Client: client, + Extend: extend, + Owner: owner, + Role: role, + ExpiresAt: expireTime.Unix(), + } + + byte, err := json.Marshal(claims) + if err != nil { + return "", errcode.ErrJsonEncode + } + + token, err := AesEncryptCBC(byte) + if err != nil { + return "", err + } + return token, nil +} + +func AesEncryptCBC(plan []byte) (string, error) { + + // 分组秘钥 + // NewCipher该函数限制了输入k的长度必须为16, 24或者32 + block, err := aes.NewCipher(JwtSecret) + if err != nil { + return "", errcode.ErrAuthSecret + } + // 获取秘钥块的长度 + 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 nil, errcode.ErrAuthSecret + } + // 转成字节数组 + crytedByte, err := base64.StdEncoding.DecodeString(cryted) + if err != nil { + return nil, errcode.ErrBase64Decode + } + // 分组秘钥 + block, err := aes.NewCipher(JwtSecret) + if err != nil { + return nil, errcode.ErrAuthSecret + } + // 获取秘钥块的长度 + 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, errcode.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, errcode.ErrAuthParseFail + } + + expireTime := time.Now().Unix() + if expireTime > ac.ExpiresAt { + return nil, errcode.ErrAuthExpire + } + + return ac, nil +} diff --git a/errcode/errcode.go b/errcode/errcode.go index 052f9d0..6500259 100644 --- a/errcode/errcode.go +++ b/errcode/errcode.go @@ -71,6 +71,22 @@ var ( ErrIdentityArgument = NewError(193, "Identity Invalid Argument") ) +var ( + ErrBase64Decode = NewError(201, "Auth Token Base64 Decode Error") + ErrAuthNotFound = NewError(202, "Auth Token Not Found") + ErrAuthParseFail = NewError(203, "Auth Parse Fail") + ErrAuthId = NewError(204, "Auth Id Not Passed") + ErrAuthIdentity = NewError(205, "Auth Identity Not Passed") + ErrAuthTokenChanged = NewError(206, "Auth Token Changed") + ErrAuthIdType = NewError(207, "Auth Id Type Error") + ErrAuthExpire = NewError(208, "Auth Token Expire") + ErrAuthClient = NewError(209, "Auth Token Client Not Passed") + ErrJsonDecode = NewError(210, "Auth JSON Decode Error") + ErrJsonEncode = NewError(211, "Auth JSON Encode Error") + ErrAuthSecret = NewError(212, "Auth JwtSecret Error") + ErrAccountNotFound = NewError(213, "Account Not Found") +) + func NewError(code int, msg string) error { return fiber.NewError(code, msg) }