diff --git a/utils/encryption_decryption/aes_cbc.go b/utils/encryption_decryption/aes_cbc.go
new file mode 100644
index 00000000..9135cfb0
--- /dev/null
+++ b/utils/encryption_decryption/aes_cbc.go
@@ -0,0 +1,64 @@
+package encryption_decryption
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/cipher"
+	"encoding/base64"
+	"fmt"
+	"math/rand"
+)
+
+// 必须16字节
+var key = "fusen20230405145"
+
+// 加密(key必须16字节),前端加解密需要先把base64转字符串再取前16字节作为iv
+func CBCEncrypt(data string) (string, error) {
+	defer func() {
+		if err := recover(); err != nil {
+			fmt.Println("cbc decrypt err:", err)
+		}
+	}()
+	block, err := aes.NewCipher([]byte(key))
+	if err != nil {
+		return "", err
+	}
+	blockSize := len(key)
+	padding := blockSize - len(data)%blockSize // 填充字节
+	if padding == 0 {
+		padding = blockSize
+	}
+	// 填充 padding 个 byte(padding) 到 data
+	data += string(bytes.Repeat([]byte{byte(padding)}, padding))
+	ciphertext := make([]byte, aes.BlockSize+len(data))
+	iv := ciphertext[:aes.BlockSize]
+	if _, err = rand.Read(iv); err != nil { // 将同时写到 ciphertext 的开头
+		return "", err
+	}
+	mode := cipher.NewCBCEncrypter(block, iv)
+	mode.CryptBlocks(ciphertext[aes.BlockSize:], []byte(data))
+	return base64.StdEncoding.EncodeToString(ciphertext), nil
+}
+
+// 解密(key必须16字节)
+func CBCDecrypt(src string) (string, error) {
+	defer func() {
+		if err := recover(); err != nil {
+			fmt.Println("cbc decrypt err:", err)
+		}
+	}()
+	block, err := aes.NewCipher([]byte(key))
+	if err != nil {
+		return "", err
+	}
+	ciphercode, err := base64.StdEncoding.DecodeString(src)
+	if err != nil {
+		return "", err
+	}
+	iv := ciphercode[:aes.BlockSize]        // 密文的前 16 个字节为 iv
+	ciphercode = ciphercode[aes.BlockSize:] // 正式密文
+	mode := cipher.NewCBCDecrypter(block, iv)
+	mode.CryptBlocks(ciphercode, ciphercode)
+	plaintext := string(ciphercode) // ↓ 减去 padding
+	return plaintext[:len(plaintext)-int(plaintext[len(plaintext)-1])], nil
+}