java读取加密对象

时间:2017-02-13 18:44:33

标签: java encryption file-io

您好我有以下问题:

我有一个可序列化的类/对象访问。

public class Access implements Serializable {

private static final long serialVersionUID = 1L;

private URL website;
private String username;
private String password;

// + some methods

}

现在将它们写入文件时,我使用密码对它们进行加密。看起来像这样:
写作:

ObservableList<Access> userData;
userData = FXCollections.observableArrayList();
...
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key128);
File file = new File("./resources/saves" + username);
file.createNewFile();
CipherOutputStream cipherOut = new CipherOutputStream(
        new BufferedOutputStream(new FileOutputStream(file, true)), cipher);
ObjectOutputStream out = new ObjectOutputStream(cipherOut);

userData.forEach((item) -> {
    try {
        out.writeObject(new SealedObject(item, cipher));
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
});
out.flush();
out.close();

READING:

ObservableList<Access> access = FXCollections.observableArrayList();

Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key128);

CipherInputStream cipherIn = new CipherInputStream(
        new BufferedInputStream(new FileInputStream("./resources/saves" + username)), cipher);
ObjectInputStream in = new ObjectInputStream(cipherIn);
SealedObject sealed;
while ((sealed = (SealedObject) in.readObject()) != null) {
    access.add((Access) sealed.getObject(cipher));
}

如果我现在加载文件,它似乎已损坏。我发现很难找到错误。我认为问题在于加载功能。我错过了一些明显的东西吗?

错误:

java.io.StreamCorruptedException: invalid stream header: 3D23898C

感谢您的时间和救命! :*

2 个答案:

答案 0 :(得分:2)

好的,问题是密码流和对象流之间的交互。

当您读取文件时,ObjectInputStream会要求基础流(密码流)读取非常特定的标头。但是密码流对此没有任何了解 - 他根据自己的协议读取了他应该使用的正常字节量,以便了解加密数据。结果是ObjectInputStream获得了截断/更改的标头,无法正确处理流。

好消息是,你实际上并不需要它! SealedObject将为您处理加密/解密。只需删除密码流即可。

ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file, true));

并阅读:

    FileInputStream inputStream = new FileInputStream(fileName);
    ObjectInputStream ois = new ObjectInputStream(inputStream);

现在,如果确实想要使用密码流(因此使用相同的密钥有效地加密/解密数据两次),您需要先进行&#34;第一次传递&# 34;在文件上解密它,然后在新的解密文件上打开一个对象流。

答案 1 :(得分:1)

您是否忘记致电if out.flush()

如果你这样做了,某些数据可能实际上没有被写入磁盘,而且再也无法读取它。