缓冲从CipherInputStream读取

时间:2013-12-16 23:29:15

标签: java oracle encryption buffer

我遇到了需要缓冲CipherInputStream的场景。确切地说,我需要确保缓冲区填充到32K或达到EOF,然后将结果返回到InputStream.read(byte [],int,int)的调用者。在这里,我遇到了一些障碍,我希望你们都可以提供帮助。

  • Oracle JRE - CipherInputStream有一个512字节的内部缓冲区,用于 没有特别的原因。
  • IBM JRE - CipherInputStream有一个内部缓冲区 8KB

使用BufferedInputStream简单地包装CipherInputStream不会给我带来任何好处,因为CipherInputStream.available()将返回0,这使得缓冲毫无意义。 CipherInputStream的javadoc声明这应该被子类http://docs.oracle.com/javase/7/docs/api/javax/crypto/CipherInputStream.html#available()重写

由于我正在使用FileInputStream(在大多数情况下)作为我的最低级别流,并且我的密码算法是没有填充的CTR,我在加密前后都有相同的字节数,但这是事情开始的地方让我模糊我重写了CipherInputStream.available()以返回super.available(),这似乎对使用Oracle的CipherInputStream的本地文件很有用。

我可以确保我的32K缓冲区充满了对read(byte [],int,int)的调用,或者到达了文件末尾。

使用Oracle JRE输出

**CipherInputStream.available: 51121
**CipherInputStream.available: 50609
**CipherInputStream.available: 50097
...
**CipherInputStream.available: 19889
**CipherInputStream.available: 19377
**BufferedInputStream.read: 32768
**CipherInputStream.available: 18353
**CipherInputStream.available: 17841
**CipherInputStream.available: 17329
...
**CipherInputStream.available: 433
**CipherInputStream.available: 0
**BufferedInputStream.read: 18865
**EOF

但是,在IBM JVM上,就好像跳过对底层FileInputStream的in.available调用一样,这会导致api出现问题,而api应该返回一个完整的缓冲区或文件结尾。这与在Windows和iSeries上使用IBM JRE的行为相同。

使用IBM JRE输出

**CipherInputStream.available: 43441
**CipherInputStream.available: 35249
**CipherInputStream.available: 27057
**BufferedInputStream.read: 32768
(where's the 18865)?
**CipherInputStream.available: 10673
**CipherInputStream.available: 2481
**CipherInputStream.available: 0
**BufferedInputStream.read: 18864
**CipherInputStream.available: 0
**BufferedInputStream.read: 1
EOF

代码

int BUFFER_SIZE = 32768;
BufferedInputStream bis = null;
CipherInputStream cis = null;
try {
    // returns an AES256 CTR cipher with no padding
    Cipher cipher = getCipher();

    cis = new CipherInputStream(fis, cipher) {

        @Override
        public int available() throws IOException {
            // The cipher input stream always returns 0 because
            // in certain implementations (padded ciphers), a
            // standard implementation may not be able to
            // accurately determine the number of available
            // bytes. In our case, however, we are not using a
            // padded cipher and the number of available bytes
            // 'should' be the same as the number available from
            // the underlying stream.

            int available = in.available();
            System.out.println("**CipherInputStream.available: "
                + available);
            return available;
        }
    };
    bis = new BufferedInputStream(cis, BUFFER_SIZE);

    byte[] buf = new byte[BUFFER_SIZE];
    int read = 0;
    while (read >= 0) {
        read = bis.read(buf, 0, BUFFER_SIZE);
        if (read >= 0) {
            System.out.println("**BufferedInputStream.read: " + read);
        }
    }
    System.out.println("EOF");
}
finally {
    if (cis != null) {
        try {
            cis.close();
        }
        catch (IOException exp) {
            // ignore
        }
    }
    if (bis != null) {
        try {
            bis.close();
        }
        catch (IOException exp) {
            // ignore
        }
    }
}

我尝试创建自己的BufferedInputStream并更改read(byte [],int,int)方法,以便不检查包装流的available()。这样,它将继续读取,直到a)缓冲区已满,或b)文件结束,但我不确定这是否是最好的方法。

有没有人对如何解决这个问题有任何更好的建议或想法?

1 个答案:

答案 0 :(得分:2)

忘掉available()和所有代码。只需将CipherInputStream包装在DataInputStream中,声明一个32k缓冲区,然后调用readFully()。两行代码。