Java:使用DES的Decrypt对象时发生StreamCorruptedException

我有两种方法可以在Android内部存储中从文件加密保存和解密加载对象。

加密和保存过程没有任何问题,但是当我想加载对象时StreamCorruptedException发生在inputStream = new ObjectInputStream(cipherInputStream);

我搜索越来越多,但我找不到解决问题的方法。 所有其他解决方案都适用于sockets寿命或类似情况。

我的代码如下:

 private static byte[] iv = { (byte) 0xB1, (byte) 0x15, (byte) 0xB5, (byte) 0xB7, (byte) 0x66, (byte) 0x43, (byte) 0x2F, (byte) 0xA4, (byte) 0xB1, (byte) 0x15, (byte) 0x35, (byte) 0xC7, (byte) 0x66, (byte) 0x58, (byte) 0x2F, (byte) 0x5F }; 

保存方法:(运作良好)

 private static String saveToFile(Serializable object, String fileName, Context ctx) { try { Cipher cipher = null; cipher = Cipher.getInstance("DES"); SecretKey key = KeyGenerator.getInstance("DES").generateKey(); AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv); cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec); SealedObject sealedObject = null; sealedObject = new SealedObject(object, cipher); CipherOutputStream cipherOutputStream = null; FileOutputStream fos = ctx.openFileOutput(fileName, Context.MODE_PRIVATE); cipherOutputStream = new CipherOutputStream( new BufferedOutputStream(fos), cipher); ObjectOutputStream outputStream = null; outputStream = new ObjectOutputStream(cipherOutputStream); outputStream.writeObject(sealedObject); outputStream.close(); return "Save Complete!"; } catch (IOException e) { e.printStackTrace(); return e.getMessage(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return e.getMessage(); } catch (NoSuchPaddingException e) { e.printStackTrace(); return e.getMessage(); } catch (InvalidKeyException e) { e.printStackTrace(); return e.getMessage(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); return e.getMessage(); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); return e.getMessage(); } } 

加载方法:(无法从cipherInputStream加载对象)

 private static Serializable loadFromFile(String fileName, Context ctx) { Cipher cipher = null; Serializable userList = null; try { cipher = Cipher.getInstance("DES"); // Code to write your object to file SecretKey key = KeyGenerator.getInstance("DES").generateKey(); AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv); cipher.init(Cipher.DECRYPT_MODE, key, paramSpec); CipherInputStream cipherInputStream = null; FileInputStream fos = ctx.openFileInput(fileName); cipherInputStream = new CipherInputStream(new BufferedInputStream( fos), cipher); ObjectInputStream inputStream = null; inputStream = new ObjectInputStream(cipherInputStream); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SealedObject sealedObject = null; sealedObject = (SealedObject) inputStream.readObject(); userList = (Serializable) sealedObject.getObject(cipher); inputStream.close(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return e.getMessage(); } catch (NoSuchPaddingException e) { e.printStackTrace(); return e.getMessage(); } catch (InvalidKeyException e) { e.printStackTrace(); return e.getMessage(); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); return e.getMessage(); } catch (FileNotFoundException e) { e.printStackTrace(); return e.getMessage(); } catch (StreamCorruptedException e) { e.printStackTrace(); return e.getMessage(); } catch (IOException e) { e.printStackTrace(); return e.getMessage(); } catch (ClassNotFoundException e) { e.printStackTrace(); return e.getMessage(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); return e.getMessage(); } catch (BadPaddingException e) { e.printStackTrace(); return e.getMessage(); } return userList; } 

保存和加载的公共方法:

 public Serializable loadPlayer(Context ctx) { return loadFromFile("player.dat", ctx); } public String savePlayer(Player player, Context ctx) { return saveToFile(player, "player.dat", ctx); } 

你至少犯了两个重大错误。

  1. 您必须使用相同的密钥来解密,就像您以前加密一样。 你不能只生成一个随机密钥,除了它可以解密任何东西。 密码学不是魔术。 您必须安排以某种方式保存解密密钥,必要时安全地传输并在解密步骤中使用。

  2. 您使用SealedObject加密一次,再使用CipherOutputStream ; 然后在相反的方向上,你用CipherInputStream解密一次,再通过SealedObject解密。 这实际上不起作用,因为Cipher对象在发送方和接收方处不具有可比较的状态,并且无论如何它都是没有意义的。 失去SealedObject或Cipher流。