RC4 加密输出看似乱码(如 "¯[á")是正常现象,因其密文为任意字节序列,不可直接转为字符串;错误地用 new String(byte[]) 解码会导致信息损坏,尤其在处理法语等含非 ASCII 字符的文本时。应统一使用确定编码(如 UTF-8)进行文本→字节转换,并以十六进制或 Base64 表示密文。
rc4 加密输出看似乱码(如 "¯\[á")是正常现象,因其密文为任意字节序列,不可直接转为字符串;错误地用 `new string(byte[])` 解码会导致信息损坏,尤其在处理法语等含非 ascii 字符的文本时。应统一使用确定编码(如 utf-8)进行文本→字节转换,并以十六进制或 base64 表示密文。
RC4 是一种流密码算法,其核心操作基于字节异或(XOR),输入明文和密钥均需先转换为字节数组,加密后生成的密文也是纯二进制字节流——它不保证可读性,也不符合任何字符编码规范(如 UTF-8、ISO-8859-1)。因此,将密文字节数组直接构造为 new String(cipher) 是根本性错误:Java 会按平台默认编码(常为 UTF-8)尝试解析这些随机字节,遇到非法字节序列时或替换为 ,或截断,或静默损坏,最终导致解密失败(如 "saisir" 变成 "saiÎir")。
✅ 正确做法:严格分离「文本」与「二进制」处理流程
-
文本 → 字节:始终指定明确编码
使用 String.getBytes(StandardCharsets.UTF_8) 将明文/密钥转为字节,避免依赖系统默认编码(尤其在法语环境易出错):String keyText = scanner.nextLine(); byte[] key = keyText.getBytes(StandardCharsets.UTF_8); // 显式指定 UTF-8 String plainText = scanner.nextLine(); byte[] plain = plainText.getBytes(StandardCharsets.UTF_8);
-
密文展示:禁用 new String(),改用可打印编码
密文字节数组绝不可直接转为字符串。推荐两种安全方案:-
十六进制(Hex):简洁、无歧义、便于调试
public static String toHex(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(String.format("%02x", b & 0xFF)); } return sb.toString(); } // 使用示例: String cipherText = toHex(rc.chiffrer(plain)); // 输出如 "a1b2c3..." System.out.println("Le cryptogramme (hex) : " + cipherText); -
Base64:更紧凑,适合传输
import java.util.Base64; String cipherText = Base64.getEncoder().encodeToString(rc.chiffrer(plain));
-
-
解密时:反向还原字节,再解码为文本
若用户输入的是 Hex 密文,需先解析回字节数组:// 解析 hex 字符串(假设输入为小写 hex,如 "a1b2c3") public static byte[] fromHex(String hex) { if (hex.length() % 2 != 0) throw new IllegalArgumentException("Hex string must have even length"); byte[] bytes = new byte[hex.length() / 2]; for (int i = 0; i
⚠️ 注意事项与常见陷阱
- 密钥编码必须一致:若密钥含法语字符(如 "café"),keyText.getBytes() 默认可能用 ISO-8859-1(Windows)或 UTF-8(Linux/macOS),导致不同平台密钥字节不同 → 加密结果不一致。务必显式使用 StandardCharsets.UTF_8。
- RC4 状态不可重用:你的 chiffrer() 方法修改了内部 S 数组(破坏了密钥调度状态),同一 RC4 实例不能多次加密不同消息。演示中若需多次加解密,应在每次调用前重建 RC4 对象,或实现密钥流重置逻辑(如重新初始化 S/T)。
- 不要混淆“加密”与“编码”:String 是文本抽象,byte[] 是二进制载体。RC4 操作在字节层,所有字符串 ↔ 字节转换必须有明确、可逆、跨平台一致的编码约定。
✅ 总结
RC4 的“乱码”不是 bug,而是流密码的本质特征。解决之道在于:永远用 StandardCharsets.UTF_8 进行文本/字节互转,永远用 Hex 或 Base64 展示和传输密文,永远避免 new String(byte[]) 直接解析密文字节。如此,无论是 "stack" 还是 "saisir",都能在法语环境下稳定加解密,且演示清晰专业。











