java - IDE 和可运行 JAR 之间的 Java 字符串解码不同
问题描述
在我的程序中,我加密一个字符串并再次解密它。当我在 IntelliJ 中运行它时,它工作正常,但是当我构建一个 jar 时,某些字符无法正确解密。例如“ä”变成“ä”。我了解到当文本编码为 UTF-8 并解码为 ISO 8859-1 时会发生这种情况。(但我的文件已经编码为 UTF-8)
谁能解释为什么在 IntelliJ 中运行程序和将其作为 jar 运行之间存在加密/解码差异?
package main;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Base64;
public class Main {
public static void main(String[] args) throws Exception {
SecretKeySpec password = createKey("safePassword");
String message = "hello ä ö ü ß";
String encryptedMessage = encrypt(message, password);
//this output is the same in IntelliJ and as a jar
System.out.println(encryptedMessage);
byte[] decryptedBytes = decrypt(encryptedMessage, password);
//this output gets messed up when I run it as a jar but not in Intellij
System.out.println(new String(decryptedBytes));
//this output works both ways
System.out.println(new String(decryptedBytes, StandardCharsets.UTF_8));
}
public static String encrypt(String message, SecretKeySpec key) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encrypted = cipher.doFinal(message.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(encrypted);
}
public static byte[] decrypt(String encryptedMessage, SecretKeySpec key) throws Exception {
byte[] message = Base64.getDecoder().decode(encryptedMessage);
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(message);
}
public static SecretKeySpec createKey(String key) throws Exception {
byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
MessageDigest sha = MessageDigest.getInstance("SHA-256");
keyBytes = sha.digest(keyBytes);
keyBytes = Arrays.copyOf(keyBytes, 16);
return new SecretKeySpec(keyBytes, "AES");
}
}
IntelliJ 中的输出:
8nno4HGKG4/Ni/Sxun+s3roOAaav+eXT4kd0ivgZFBA=
hello ä ö ü ß
hello ä ö ü ß
罐子的输出:
8nno4HGKG4/Ni/Sxun+s3roOAaav+eXT4kd0ivgZFBA=
hello ä ö ü �
hello ä ö ü ß
解决方案
System.out.println(new String(decryptedBytes));
您的“字节”是 UTF-8 表示。
上面的行使用平台标准字符集构造了一个解释字节的字符串,它不一定是 UTF-8。
因此生成的字符串是垃圾。
推荐阅读
- kubernetes - 如何为 K8S 上的应用程序准备好输入数据
- netlogo - 从列表中挑选元素
- c++ - 在 Visual Studio 中构建 wxWidgets-3.1.2 项目时如何修复“找不到 setup.h”错误?
- c - C:按顺序计算 2 个表达式,然后返回第一个
- javascript - 将对象更新为新对象的实例
- c# - 当前上下文中不存在名称“进程”
- javascript - 在不停止应用程序的情况下拦截 400 错误请求
- c++ - 递归导致程序崩溃,但 while 循环中的相同概念并非来自 C++ 析构函数
- javascript - 如何修复“TypeError:无法设置属性‘已批准’为空”?
- c++ - 使用 QTableView 和 QgsCanvas 在应用程序上崩溃