RC4算法编码异常求助:加密解密字符乱码与失真
解决RC4加密的编码失真问题
问题根源
RC4加密输出的是任意二进制字节流,直接将其转换为String时,无论使用UTF-8、ISO-8859-1还是ASCII编码,都会因为部分字节无法映射为合法字符导致信息丢失:
- ASCII仅支持0-127范围的字节,非ASCII字符(如法语é、中文)会被截断或替换
- UTF-8对非法字节序列会替换为
�(问号),解密时无法还原原始数据 - ISO-8859-1虽能覆盖0-255字节,但会出现大量不可打印乱码,且在文本传输/存储中可能被篡改
解决方案:用Base64封装加密结果
把加密后的二进制字节转成Base64编码的字符串,Base64仅使用64个可打印ASCII字符,完全保留二进制信息,彻底解决编码失真问题。流程如下:
- 明文String → UTF-8字节数组 → RC4加密 → Base64编码为密文String
- 密文String → Base64解码为字节数组 → RC4解密 → UTF-8解码为明文String
修改后的代码示例
RC4核心类(保持字节数组操作逻辑)
public class RC4 { private final byte[] S = new byte[256]; private final byte[] T = new byte[256]; private final int keylen; public RC4(byte[] key) { keylen = key.length; for (int i = 0; i < 256; i++) { S[i] = (byte) i; T[i] = key[i % keylen]; } int j = 0; byte temp; for (int i = 0; i < 256; i++) { j = (j + S[i] + T[i]) & 0xFF; temp = S[i]; S[i] = S[j]; S[j] = temp; } } // 加密:字节数组转字节数组 public byte[] encrypt(byte[] plaintext) { byte[] ciphertext = new byte[plaintext.length]; int i = 0, j = 0, k; byte temp; for (int m = 0; m < plaintext.length; m++) { i = (i + 1) & 0xFF; j = (j + S[i]) & 0xFF; temp = S[i]; S[i] = S[j]; S[j] = temp; k = (S[i] + S[j]) & 0xFF; ciphertext[m] = (byte) (plaintext[m] ^ S[k]); } return ciphertext; } // RC4解密与加密逻辑完全一致 public byte[] decrypt(byte[] ciphertext) { return encrypt(ciphertext); } }
主类(加入Base64编码解码)
import java.util.Base64; import java.nio.charset.StandardCharsets; public class RC4Demo { public static void main(String[] args) { String key = "demoKey123"; String plaintext = "stack 测试 法语文本:éàùç"; // 加密流程 RC4 rc4Encrypt = new RC4(key.getBytes(StandardCharsets.UTF_8)); byte[] plainBytes = plaintext.getBytes(StandardCharsets.UTF_8); byte[] cipherBytes = rc4Encrypt.encrypt(plainBytes); String ciphertext = Base64.getEncoder().encodeToString(cipherBytes); System.out.println("加密密文(Base64):" + ciphertext); // 解密流程 RC4 rc4Decrypt = new RC4(key.getBytes(StandardCharsets.UTF_8)); byte[] decodedCipher = Base64.getDecoder().decode(ciphertext); byte[] decryptedBytes = rc4Decrypt.decrypt(decodedCipher); String decryptedText = new String(decryptedBytes, StandardCharsets.UTF_8); System.out.println("解密明文:" + decryptedText); } }
关键注意事项
- 统一使用
UTF-8进行字符串与字节数组的转换,确保支持所有Unicode字符(包括多语言文本) - Base64编码后的密文长度会比原始字节流增加约1/3,但完全避免了编码失真问题
- 解密时必须使用与加密相同的密钥和编码方式,否则无法正确还原明文
内容的提问来源于stack exchange,提问作者Sakura
相关产品推荐
相关产品推荐

