BufferedReader.readLine()破坏了二进制文件

Rag*_*geD 3 java binary

出于学术目的,我正在使用java和java加密技术开发基于加密的小型应用程序.也就是说,我通常使用C或C++(这很容易),所以我很抱歉这是一个明显的问题.所以,当我想要解密信息时,问题出现了.问题与使用加密或任何东西没有多大关系,但事实上,正确地检索我的初始化向量.现在我有一个明文文件,其格式为new-line /冒号(是的,这是不安全的,但这是一个学术练习 - 显然关键文件不会在现实世界的明文中)

password:salt:<IV>
Run Code Online (Sandbox Code Playgroud)

<IV>初始化向量在哪里.我决定直接以二进制格式写出初始化向量.现在我在这里是我的问题开始的地方.我可以正确地写出数据(使用hexdump验证),但它似乎没有被正确地读回到程序中.例如,考虑一个计数器值

00 18 C0 98 (decimal: 1622168)
Run Code Online (Sandbox Code Playgroud)

正确写出该值.但是,当我尝试读取它时,这个值都是错误的.我怀疑这是结果BufferedReader.readLine().我只是读取这一行并将其写入另一个文件,然后将该值更改为

BD EF BF BD (decimal: who cares, very wrong...)
Run Code Online (Sandbox Code Playgroud)

但是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();
Run Code Online (Sandbox Code Playgroud)

此时,iv.length > 16(使用128位AES)已经错了.所以我不完全确定如何完成这种ASCII二进制混合(也许这是一个糟糕的设计开始).我的一部分问题是char != byte在Java中,如果我想读取一个完整的行(readLine()无论如何都使用),我不能简单地以字节的形式读取所有内容.但是,无论如何要解决这个问题?因为我想要整行,但我也想从这一行中提取二进制文件.

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

for(int i = 0 ; i < 16 ; ++i)
  iv[i] = (byte)parse.charAt(offset + i);
Run Code Online (Sandbox Code Playgroud)

但这也不起作用.其他代码(getBytes()基于)在我的个人计算机上工作java version "1.6.0_37",但部署环境正在使用java version "1.6.0_33"失败的地方.任何帮助表示赞赏.

Gor*_*ley 10

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

重点是BufferedReader阅读文本,而不是任意数据!它会将您的所有数据视为文本.它还会尝试使用某种编码将二进制文件转换为文本,这当然会破坏您的数据.

一种更好的方法是:

  • 不要将您的任何数据写为二进制文件,并依赖换行符或其他分隔符.(例如继续使用BufferedReader.readLine())
  • 将所有数据写为二进制文件,并将文件中的每条记录设置为固定长度,或者提出一些更复杂的分隔符方案.(例如只是使用FileInputStream.read(byte[]))