【发布时间】:2021-07-21 10:39:04
【问题描述】:
我试图了解一些我没有创建但我可能必须修复的代码的行为。 根据 JVM 系统属性 file.encoding 的值(在 JVM 启动时 - 以后以编程方式更改该值似乎没有效果),代码的重音字符的行为会有所不同。
代码创建并初始化一个 RSACipher 实例:
final Cipher cipher = Cipher.getInstance(DecryptInformation.RSA_ECB_PKCS1_PADDING);
cipher.init(Cipher.DECRYPT_MODE, decryptingKey);
然后在循环中它使用该实例来解密加密的字节。
byte[] plain = cipher.doFinal(scrambled, 0, i);
我验证了不管 file.encoding 的值如何,scrambled 的值都保持不变,但问题是 plain 中的字节在有重音字符的地方发生了变化。在我的单元测试中(为响应运行时在 wildfly 应用程序中看到的问题而编写),有一个小写的 e-accute 字符(UTF-8 中的 c3a9)。如果使用 VM 参数 -Dfile.encoding=ISO-8859-1 启动测试,我会在字符的变量 plain 中得到 c3a9。另一方面,如果我用 -Dfile.encoding=UTF-8 开始测试,我会得到 c383c2a9 来代替相同的输入字节,我不知道如何系统地解决这个问题所有字符。
谁能解释一下 file.encoding 对解密的影响以及如何防止字符被破坏?例如,应用程序在 linux 上的 wildfly 上运行,其中默认 file.encoding 为 UTF-8,更改整个应用程序的此值可能会产生其他副作用,因此不能选择更改 file.encoding .
【问题讨论】:
-
加密适用于字节而不是字符串或字符。关键点始终是从字符串到字节的转换以及(稍后)转换回字符串。使用一致的编码(如“abcd”.getBytes(StandardCharset.UTF8) 并使用新字符串(decryptedBytes,StandardCharset.UTF8))完成此转换非常重要。这样可以避免使用默认字符集编码的转换在不同的系统上可能会有所不同。
-
回应 Michael Fehr,加密以 new ByteArrayInputStream(toCrypt.getBytes(StandardCharsets.UTF_8) 开始,解密以 new String(plain, StandardCharsets.UTF_8) 继续。谜团在于为什么“plain " 根据默认编码不同。
-
如果默认编码不同,
plain不会有任何不同,但如果您认为不同,请组合一个完整的可运行示例,以及演示这一点的示例输入和输出。然后我们可以自己运行它并深入了解它。 -
-Dfile.encoding只是设置默认编码。如果在编码(在加密部分)和解码(在解密部分)之间仍然存在(或多个)对默认编码(可能已丢失)的依赖关系,则更改-Dfile.encoding时的影响将是合理的。
标签: java cryptography non-ascii-characters