BufferedReader.readLine() 会破坏二进制数据

3

出于学术目的,我正在使用java和java加密编写一个小型基于加密的应用程序。但是,通常我使用C或C++(在这方面非常容易),所以如果这是一个显而易见的问题,我表示歉意。我的问题在于我想要解密信息时遇到了困难。问题实际上并不是与使用加密相关(或其他什么东西),而是正确检索我的初始化向量。目前,我有一个明文文件,格式为新行/冒号分隔(是的,这很不安全,但这是一种学术练习——显然,在现实世界中,密钥文件不会以明文形式存在)。

password:salt:<IV>

其中<IV>为初始化向量。我决定直接以二进制格式写出初始化向量,但是这时我的问题开始了。我能够正确地写出数据(通过hexdump验证),但似乎并没有被正确地读回程序中。例如,考虑一个计数器值

00 18 C0 98 (decimal: 1622168)

这个值正确地被写出。但是,当我尝试读取它时,这个值完全错误。我怀疑这是由于BufferedReader.readLine()引起的。我只是读取这一行并将其写入另一个文件,然后这个值就会改变为

BD EF BF BD (decimal: who cares, very wrong...)

但是ASCII值(密码和盐)保持不变,冒号分隔符也保留。初始化向量二进制则完全被混淆。

我试图做的事情是:

BufferedReader reader = new BufferedReader(new FileReader(f));
String last  = null;
String parse = null;
while((last = reader.readLine()) != null) {
    parse = last;
}
reader.close();
int offset = // A few indexOf() statements to find the positon;
byte[] iv  = parse.substring(offset).getBytes();

目前,iv.length > 16(使用128位AES)已经是错误的。因此,我不确定如何实现ASCII二进制混合(也许一开始就是不良设计)。我的一个问题是在Java中char != byte,如果要读取整行(无论如何使用readLine()),我不能简单地将所有内容读取为字节。但是否有任何方法可以解决这个问题?因为我想要整行,但我还想从该行中提取二进制数据。

另外,我也尝试过直接转换。

for(int i = 0 ; i < 16 ; ++i)
  iv[i] = (byte)parse.charAt(offset + i);

但这也不起作用。另一段代码(基于getBytes())在我的个人计算机上使用的是java version "1.6.0_37",但部署环境使用的是java version "1.6.0_33",因此失败了。感谢任何帮助。


3
不要在二进制数据上使用读取器。 - user207421
1个回答

10

什么是二进制数据行?你如何知道哪个 0x0A 是数据,哪个是换行符?

关键在于BufferedReader是用于读取文本,而不是任意数据!它会将所有数据视为文本。它还会尝试使用某种编码将您的二进制数据转换为文本,这当然会破坏您的数据。

更好的方法是要么:

  • 不将您的任何数据写为二进制数据,依赖于换行符或其他定界符。(例如继续使用BufferedReader.readLine()
  • 将您的所有数据都写为二进制数据,并使文件中的每个记录具有固定长度,或者采用一些更复杂的定界符方案。(例如只使用FileInputStream.read(byte[])

我正在阅读关于DataInputStream.readLine()(http://docs.oracle.com/javase/6/docs/api/java/io/DataInputStream.html#readLine())的注释,了解它为什么被弃用,并且认为`BufferedReader.readLine()`不会像这样搞乱字节。 - RageD
1
在这两种情况下的问题是读取器试图将原始字节转换为字符(文本),而您的数据不是文本!或者至少不完全是文本。 - Gordon Bailey
没错,我想这是有道理的。谢谢你的帮助。我不习惯在数据解释方面有这样的规定(虽然你提出了一个很好的观点),但我的数据没有包含任何回车或换行二进制码! - RageD
我敢打赌它包含非ASCII字符(例如字节> 127)。它将尝试根据默认编码将其转换为文本,但很可能会失败(因为数据几乎是随机的)。祝你好运,继续完成你的项目。 - Gordon Bailey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接