You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言字符串加密解密出现字符丢失问题排查

问题分析与解决

一、加密后出现大量0、解密丢失数据的原因

你直接使用AES块密码的Encrypt方法处理数据,但AES的块大小固定为16字节。你的令牌长度远超过16字节,cipher.Encrypt仅会加密第一个16字节的块,剩余字节因make([]byte, len(original))初始化默认值为0,最终输出的十六进制字符串后段全是0。

解密时同理,cipher.Decrypt也只处理第一个16字节的块,后续的0解密后仍为0,转成字符串就丢失了原令牌的剩余内容。

解决方法

不能直接用块密码的原始Encrypt/Decrypt方法处理超过块大小的数据,必须使用分组密码模式(如CBC、GCM)。推荐使用GCM模式,它同时提供加密和认证,安全性更高,示例代码如下:

import (
    "crypto/aes"
    "crypto/cipher"
    CR "crypto/rand"
    "encoding/hex"
    "log"
)

var key = make([]byte, 32)

func init() {
    // 程序启动时初始化密钥,比单独函数更可靠
    _, err := CR.Read(key)
    if err != nil {
        log.Fatalf("生成密钥失败: %v", err)
    }
}

func encryptToken(t token) string {
    plaintext := []byte(t.ID)

    block, err := aes.NewCipher(key)
    if err != nil {
        log.Fatalf("创建密码器失败: %v", err)
    }

    // GCM模式需要随机nonce
    gcm, err := cipher.NewGCM(block)
    if err != nil {
        log.Fatalf("创建GCM模式失败: %v", err)
    }

    nonce := make([]byte, gcm.NonceSize())
    _, err = CR.Read(nonce)
    if err != nil {
        log.Fatalf("生成nonce失败: %v", err)
    }

    // 加密结果格式: nonce + 密文 + 认证标签
    ciphertext := gcm.Seal(nonce, nonce, plaintext, nil)
    return hex.EncodeToString(ciphertext)
}

func decryptToken(s string) string {
    ciphertext, err := hex.DecodeString(s)
    if err != nil {
        log.Fatalf("十六进制解码失败: %v", err)
    }

    block, err := aes.NewCipher(key)
    if err != nil {
        log.Fatalf("创建密码器失败: %v", err)
    }

    gcm, err := cipher.NewGCM(block)
    if err != nil {
        log.Fatalf("创建GCM模式失败: %v", err)
    }

    nonceSize := gcm.NonceSize()
    if len(ciphertext) < nonceSize {
        log.Fatal("密文长度过短")
    }

    nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
    plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
    if err != nil {
        log.Fatalf("解密失败: %v", err)
    }

    return string(plaintext)
}

二、修改密钥长度触发panic的原因

AES算法仅支持三种密钥长度:16字节(AES-128)、24字节(AES-192)、32字节(AES-256)。若你将密钥长度改为这三个值之外的数值,aes.NewCipher会返回非nil错误,此时cipher变量为nil,后续调用cipher.Encrypt或cipher.Decrypt就会触发空指针引用panic。

另外你的createKey函数存在语法问题:函数内的err变量未声明,会导致编译错误。建议将密钥初始化放在init函数中,确保程序启动时完成密钥生成,避免使用未初始化的密钥。

内容的提问来源于stack exchange,提问作者John Harrington

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 09:05:21