使用CipherOutputStream加密JSON后,JsonReader读取解密内容失败求助
解决CipherInputStream解密后JsonReader无法读取JsonObject的问题
我之前处理加解密JSON的时候也踩过类似的坑,JsonReader读不了内容大概率是解密后的数据不完整或者是乱码,咱们一步步排查解决:
1. 先确认加密环节的流处理是否正确
CipherOutputStream有个很容易忽略的点:它内部会缓存数据,必须调用close()或者至少flush()才能确保所有加密数据都写入文件。如果加密时只写了数据但没关流,解密出来的内容会缺失,Json自然解析失败。
加密时的正确写法应该是这样(用try-with-resources自动管理流):
try (FileOutputStream fos = new FileOutputStream(encryptedPath); CipherOutputStream cos = new CipherOutputStream(fos, Encryption.get_encrypt_cipher()); OutputStreamWriter osw = new OutputStreamWriter(cos, StandardCharsets.UTF_8); JsonWriter writer = new JsonWriter(osw)) { // 用Gson写入JSON内容 gson.toJson(yourJsonObject, writer); } // 自动关闭所有流,确保加密数据全部写入文件
2. 验证解密用的Cipher实例和加密时完全一致
解密的Cipher必须和加密时使用相同的算法、模式、填充方式、密钥和IV(如果是CBC等模式),哪怕有一点不一样,解密出来的就是乱码,JsonReader根本识别不了。
比如加密时你是这么初始化Cipher的:
Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
那解密时必须完全对应:
Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); decryptCipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
特别注意:IV向量必须和加密时的一致,很多人会忽略这点导致解密乱码。
3. 规范解密时的流处理
你的解密代码框架没问题,但建议用try-with-resources来自动管理流,避免资源泄漏同时确保流被正确关闭:
try (FileInputStream fis = new FileInputStream(path); CipherInputStream cis = new CipherInputStream(fis, Encryption.get_decrypt_cipher()); InputStreamReader isr = new InputStreamReader(cis, StandardCharsets.UTF_8); JsonReader reader = new JsonReader(isr)) { // 解析JSON为实体类 YourModel model = gson.fromJson(reader, YourModel.class); // 或者直接读取JsonObject JsonObject jsonObject = JsonParser.parseReader(reader).getAsJsonObject(); }
另外,你可以先把解密后的内容转成字符串打印出来:如果是乱码,说明加解密参数不匹配;如果内容缺失,说明加密时流没正确关闭。
4. 额外排查点:加密前的JSON是否有效
如果加密前的JSON本身就有格式问题,解密后自然也解析失败。可以先跳过加密步骤,直接用Gson读写JSON,确认原始JSON是有效的格式。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

