qnc-server-tob/pkg/lzkit/crypto
2025-06-24 15:46:41 +08:00
..
bcrypt.go 后台面板 2025-06-09 12:34:52 +08:00
crypto_test.go 新增代理实名认证和授权 2025-05-24 14:26:20 +08:00
crypto_url.go 新版本,代理功能上线 2025-03-07 03:48:59 +08:00
crypto.go first commit 2025-01-10 00:09:25 +08:00
ecb_test.go add tax 2025-06-24 15:46:41 +08:00
ecb.go 1 2025-04-08 12:49:19 +08:00
generate.go first commit 2025-01-10 00:09:25 +08:00
README.md 后台面板 2025-06-09 12:34:52 +08:00
west_crypto.go first commit 2025-01-10 00:09:25 +08:00

AES 加密工具包

本包提供了多种加密方式,特别是用于处理敏感个人信息(如手机号、身份证号等)的加密和解密功能。

主要功能

  • AES-CBC 模式加密/解密 - 标准加密模式,适用于一般数据加密
  • AES-ECB 模式加密/解密 - 确定性加密模式,适用于数据库字段加密和查询
  • 专门针对个人敏感信息的加密/解密方法
  • 密钥生成和管理工具

安全性说明

  • AES-CBC 模式:使用随机 IV相同明文每次加密结果不同安全性较高
  • AES-ECB 模式:确定性加密,相同明文每次加密结果相同,便于数据库查询,但安全性较低

⚠️ 警告ECB 模式仅适用于短文本(如手机号、身份证号)的确定性加密,不建议用于加密大段文本或高安全需求场景。

使用示例

1. 加密手机号

使用 AES-ECB 模式加密手机号,保证确定性(相同手机号总是产生相同密文)

import (
    "fmt"
    "qnc-server/pkg/lzkit/crypto"
)

func encryptMobileExample() {
    // 您的密钥(需安全保存,建议存储在配置中)
    key := []byte("1234567890abcdef") // 16字节AES-128密钥

    // 加密手机号
    mobile := "13800138000"
    encryptedMobile, err := crypto.EncryptMobile(mobile, key)
    if err != nil {
        panic(err)
    }

    fmt.Println("加密后的手机号:", encryptedMobile)

    // 解密手机号
    decryptedMobile, err := crypto.DecryptMobile(encryptedMobile, key)
    if err != nil {
        panic(err)
    }

    fmt.Println("解密后的手机号:", decryptedMobile)
}

2. 在数据库中存储和查询加密手机号

// 加密并存储手机号
func saveUser(db *sqlx.DB, mobile string, key []byte) (int64, error) {
    encryptedMobile, err := crypto.EncryptMobile(mobile, key)
    if err != nil {
        return 0, err
    }

    var id int64
    err = db.QueryRow(
        "INSERT INTO users (mobile, create_time) VALUES (?, NOW()) RETURNING id",
        encryptedMobile,
    ).Scan(&id)

    return id, err
}

// 根据手机号查询用户
func findUserByMobile(db *sqlx.DB, mobile string, key []byte) (*User, error) {
    encryptedMobile, err := crypto.EncryptMobile(mobile, key)
    if err != nil {
        return nil, err
    }

    var user User
    err = db.QueryRow(
        "SELECT id, mobile, create_time FROM users WHERE mobile = ?",
        encryptedMobile,
    ).Scan(&user.ID, &user.EncryptedMobile, &user.CreateTime)

    if err != nil {
        return nil, err
    }

    // 解密手机号用于显示
    user.Mobile, _ = crypto.DecryptMobile(user.EncryptedMobile, key)

    return &user, nil
}

3. 加密身份证号

func encryptIDCardExample() {
    key := []byte("1234567890abcdef")

    idCard := "440101199001011234"
    encryptedIDCard, err := crypto.EncryptIDCard(idCard, key)
    if err != nil {
        panic(err)
    }

    fmt.Println("加密后的身份证号:", encryptedIDCard)

    // 解密身份证号
    decryptedIDCard, err := crypto.DecryptIDCard(encryptedIDCard, key)
    if err != nil {
        panic(err)
    }

    fmt.Println("解密后的身份证号:", decryptedIDCard)
}

4. 密钥管理

func keyManagementExample() {
    // 生成随机密钥
    key, err := crypto.GenerateAESKey(16) // AES-128
    if err != nil {
        panic(err)
    }
    fmt.Printf("生成的密钥(十六进制): %x\n", key)

    // 从密码派生密钥(便于记忆)
    password := "my-secure-password"
    derivedKey, err := crypto.DeriveKeyFromPassword(password, 16)
    if err != nil {
        panic(err)
    }
    fmt.Printf("从密码派生的密钥: %x\n", derivedKey)
}

5. 使用十六进制输出(适用于 URL 参数)

func hexEncodingExample() {
    key := []byte("1234567890abcdef")
    mobile := "13800138000"

    // 使用十六进制编码(适合URL参数)
    encryptedHex, err := crypto.EncryptMobileHex(mobile, key)
    if err != nil {
        panic(err)
    }

    fmt.Println("十六进制编码的加密手机号:", encryptedHex)

    // 解密十六进制编码的手机号
    decryptedMobile, err := crypto.DecryptMobileHex(encryptedHex, key)
    if err != nil {
        panic(err)
    }

    fmt.Println("解密后的手机号:", decryptedMobile)
}

在 Go-Zero 项目中使用

在 Go-Zero 项目中,建议将加密密钥放在配置文件中:

  1. 在配置文件中添加密钥配置:
# etc/main.yaml
Name: main-api
Host: 0.0.0.0
Port: 8888

Encrypt:
    MobileKey: "1234567890abcdef" # 16字节AES-128密钥
    IDCardKey: "1234567890abcdef1234567890abcdef" # 32字节AES-256密钥
  1. 在配置结构中定义:
type Config struct {
    rest.RestConf
    Encrypt struct {
        MobileKey string
        IDCardKey string
    }
}
  1. 在服务上下文中使用:
type ServiceContext struct {
    Config      config.Config
    UserModel   model.UserModel
    MobileKey   []byte
    IDCardKey   []byte
}

func NewServiceContext(c config.Config) *ServiceContext {
    return &ServiceContext{
        Config:      c,
        UserModel:   model.NewUserModel(sqlx.NewMysql(c.DB.DataSource), c.Cache),
        MobileKey:   []byte(c.Encrypt.MobileKey),
        IDCardKey:   []byte(c.Encrypt.IDCardKey),
    }
}
  1. 在 Logic 中使用:
func (l *RegisterLogic) Register(req *types.RegisterReq) (*types.RegisterResp, error) {
    // 加密手机号用于存储
    encryptedMobile, err := crypto.EncryptMobile(req.Mobile, l.svcCtx.MobileKey)
    if err != nil {
        return nil, errors.New("手机号加密失败")
    }

    // 保存到数据库
    user := &model.User{
        Mobile: encryptedMobile,
        // 其他字段...
    }

    result, err := l.svcCtx.UserModel.Insert(l.ctx, nil, user)
    // 其余逻辑...
}