AES-CBC解密异常:自定义Go函数解密结果乱码问题排查
AES-CBC解密开头乱码+末尾填充问题的原因及解决方法
核心问题排查
1. 密钥/IV的编码转换错误
你提供的密钥(62448f7b7128e8b55224dd667b7c1a7e)和IV(db64fa140a888b41)是十六进制字符串,如果直接将其作为字节数组传入Go的AES函数,会把每个字符的ASCII码当作有效字节,完全偏离实际密钥/IV的字节值,这是开头乱码的核心原因。
2. 填充方式不匹配
在线工具默认使用PKCS7填充,但Go标准库的crypto/cipher.BlockMode仅负责块级加密解密操作,不会自动处理填充逻辑。如果你的代码未实现PKCS7去填充步骤,解密结果末尾必然会残留填充字符。
3. 密文处理逻辑偏差
若在线工具是将IV拼接在密文头部后再做Base64编码,你直接使用给定IV解密会导致块偏移错误,同样会引发开头乱码。但你提到提取IV也未解决问题,大概率还是编码转换环节出错。
解决代码示例
以下是符合要求的完整Go解密实现,包含十六进制转字节、PKCS7去填充的正确逻辑:
package main import ( "crypto/aes" "crypto/cipher" "encoding/base64" "encoding/hex" "fmt" ) // PKCS7Unpadding 去除PKCS7格式的填充字符 func PKCS7Unpadding(data []byte) []byte { length := len(data) if length == 0 { return data } padding := int(data[length-1]) return data[:length-padding] } func AESDecrypt(cipherTextBase64 string, keyHex string, ivHex string) ([]byte, error) { // 1. 解码Base64格式的密文 cipherText, err := base64.StdEncoding.DecodeString(cipherTextBase64) if err != nil { return nil, err } // 2. 将十六进制密钥转换为字节数组 key, err := hex.DecodeString(keyHex) if err != nil { return nil, err } // 3. 将十六进制IV转换为字节数组 iv, err := hex.DecodeString(ivHex) if err != nil { return nil, err } // 4. 创建AES加密块 block, err := aes.NewCipher(key) if err != nil { return nil, err } // 5. 初始化CBC解密模式 mode := cipher.NewCBCDecrypter(block, iv) // 6. 执行解密操作 plainText := make([]byte, len(cipherText)) mode.CryptBlocks(plainText, cipherText) // 7. 去除填充字符 plainText = PKCS7Unpadding(plainText) return plainText, nil } func main() { // 替换为你的Base64加密文本 cipherText := "你的Base64密文内容" key := "62448f7b7128e8b55224dd667b7c1a7e" iv := "db64fa140a888b41" result, err := AESDecrypt(cipherText, key, iv) if err != nil { fmt.Println("解密失败:", err) return } fmt.Println("解密结果:", string(result)) }
验证步骤
- 确保密钥和IV都通过
hex.DecodeString转换为字节数组,而非直接使用[]byte(key)这种错误方式。 - 解密后必须调用
PKCS7Unpadding去除末尾填充字符。 - 若之前尝试从密文提取IV,需确认提取的是前16字节(AES块大小),且同样做十六进制转字节的处理(针对原始字节密文)。
内容的提问来源于stack exchange,提问作者Support JunidiFresh
相关产品推荐
相关产品推荐

