Go语言字符串加密解密异常:加密后解密结果不符问题排查
问题分析与解决方案
你遇到的核心问题是加密和解密的处理逻辑完全不匹配,导致解密时处理的根本不是加密后的原始字节数据。
为什么会出错?
- 你的
Encrypt函数把每个异或后的字节,转换成了十六进制转义字符串格式(比如一个字节0xcd会被格式化为字符串\xcd,这是4个独立的ASCII字符:\、x、c、d)。 - 但
Decrypt函数却直接拿这个转义字符串的每个字符(也就是上述4个字符的ASCII值)去和密钥异或,相当于你在解密一堆和原始加密字节完全无关的字符数据,结果自然和原字符串不符。
修正方案(两种可选)
方案一:直接处理原始字节(推荐,更高效简洁)
放弃转义字符串的输出,让加密后的结果直接是异或后的字节组成的字符串(Go中string本质就是字节序列),这样加密和解密逻辑对称:
package main import ( "fmt" ) const key = "\xbd\xb2\x3d\xbc\x20\xe2\x8c\x98" // 你的密钥 func Encrypt(input string) (output string) { keyLen := len(key) for i := 0; i < len(input); i++ { output += string(input[i] ^ key[i%keyLen]) } return } func Decrypt(input string) (output string) { keyLen := len(key) for i := 0; i < len(input); i++ { output += string(input[i] ^ key[i%keyLen]) } return } func main() { stringa := "password" encrypted := Encrypt(stringa) fmt.Printf("加密后(原始字节,带转义显示):%q\n", encrypted) decrypted := Decrypt(encrypted) fmt.Println("解密后:", decrypted) fmt.Println("原字符串:", stringa) }
运行后会输出匹配的结果,%q格式化符会帮你把不可打印的字符转义显示,方便查看。
方案二:保留转义字符串输出,先解析再解密
如果你必须输出\xXX格式的转义字符串,那解密时需要先把这个字符串解析回原始的加密字节数组,再进行异或操作:
package main import ( "fmt" "strconv" ) const key = "\xbd\xb2\x3d\xbc\x20\xe2\x8c\x98" // 你的密钥 func Encrypt(input string) (output string) { keyLen := len(key) for i := 0; i < len(input); i++ { output += fmt.Sprintf("\\x%02x", input[i]^key[i%keyLen]) } return } func Decrypt(input string) (output string, err error) { // 给转义字符串加上双引号,让strconv.Unquote能正确解析转义序列 quotedInput := `"` + input + `"` rawEncryptedBytes, err := strconv.Unquote(quotedInput) if err != nil { return "", fmt.Errorf("解析转义字符串失败:%w", err) } // 用解析后的原始字节进行解密 keyLen := len(key) for i := 0; i < len(rawEncryptedBytes); i++ { output += string(rawEncryptedBytes[i] ^ key[i%keyLen]) } return output, nil } func main() { stringa := "password" encrypted := Encrypt(stringa) fmt.Println("加密后:", encrypted) decrypted, err := Decrypt(encrypted) if err != nil { fmt.Println("解密错误:", err) return } fmt.Println("解密后:", decrypted) fmt.Println("原字符串:", stringa) }
这个方案中,strconv.Unquote会把\xcd这样的转义序列转换成对应的单个字节0xcd,之后再用密钥异或就能得到原字符串了。
内容的提问来源于stack exchange,提问作者Lucian Blaga
相关产品推荐
相关产品推荐

