Groovy AES加密后无法在C#端解密的原因排查
以下是导致Groovy加密后C#无法解密的核心原因及对应解决办法:
IV处理逻辑错误
你的Groovy代码直接把iv传入IvParameterSpec,如果iv是Base64编码的字符串而非解码后的字节数组,这里就会出问题。IvParameterSpec需要的是原始IV字节,而不是Base64字符串本身的字节(比如UTF-8编码后的Base64字符串字节)。
正确做法是先将Base64格式的IV解码为字节数组:def ivBytes = iv.decodeBase64() cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(ivBytes))同时要确保存入
vars的IV是原始字节数组编码的Base64,而非对Base64字符串重复编码的结果。Base64编码格式不一致
Groovy的encodeBase64()默认生成带换行符的MIME格式Base64,虽然C#的Convert.FromBase64String()会忽略空白字符,但如果Groovy使用了URL安全的Base64(用-、_替换+、/),就会导致C#解码失败。
建议在Groovy中生成标准无换行的Base64:cipher.doFinal(message.getBytes("UTF-8")).encodeBase64(false) as String(
encodeBase64(false)参数表示不添加换行符)密钥截断逻辑不匹配
Groovy代码通过0, 32截取了密钥的前32字节,若原始Base64密钥解码后长度超过32字节,必须确保C#端也做完全相同的截断处理,否则两端密钥不一致。AES-256要求密钥必须是32字节,若C#端使用更长的密钥会直接抛出异常,需严格保证密钥长度一致。字符串编码未对齐
Groovy用message.getBytes("UTF-8")将明文转为字节,C#的StreamReader默认使用UTF-8编码,但如果显式指定了其他编码(比如系统默认编码),会导致解密后文本乱码或读取失败。建议C#端显式指定UTF-8:using (StreamReader streamReader = new StreamReader(cryptoStream, Encoding.UTF8))
最后,建议在两端分别打印密钥、IV的十六进制字节内容,以及加密后的Base64字符串,对比确认每一步的数据完全一致,这是快速定位问题的有效方法。
内容的提问来源于stack exchange,提问作者chris

