2017-02-13 71 views
2

你好,我有以下问题:java读取加密对象

我有一个类/对象访问至极序列化。

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(); 

阅读:

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 

感谢您的时间&帮助! :*

+0

如果您注释掉您的方法中的(de)加密内容,会发生什么情况?你能写和读回一个未加密的对象吗? – 9000

+0

我刚刚尝试过,现在在阅读时遇到EOF异常。我可能会搞砸了吗? **编辑**是循环的一些问题。它工作正常,没有加密。 –

+0

@Emmanuel:不是我会尝试另一种方式:通过密码流写入和读回字符串,以确保这部分工作正常。 – 9000

回答

2

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

当您读取文件时,ObjectInputStream要求底层流(密码流)读取非常特定的头文件。但密码流对此知之甚少 - 根据自己的协议,他读取正常的字节数,以便理解加密数据。结果是ObjectInputStream获取了截断/更改的标题,无法正确处理该流。

好消息是,你并不需要它! SealedObject会照顾你的加密/解密。只需删除密码流,它应该工作。

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

和阅读:

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

现在,如果你真的要使用的密码流(从而有效的加密/使用相同的密钥对数据进行解密两次),你需要先对该文件进行“第一遍”解密,然后在新的解密文件上打开一个对象流。

+0

Merci!非常感谢你。这解决了问题! –

+0

德里恩! bon hacking! –

1

您忘记了电话out.flush()out.close()

如果你这样做了,有些数据可能实际上不会写入磁盘,并且不可能再次读取它。

+0

我确实叫过“close()”,但没有刷新它。不幸的是,这并没有解决问题。 :(我要编辑/更新我的帖子 –

+0

好吧,这是一个盲目的猜测:)我要去尝试你的代码。 –