Blowfish代码应该是等价的,但不是

时间:2012-04-19 01:50:06

标签: java encryption blowfish

我们有一个包装BouncyCastle(实际上是SpongyCastle for Android)Blowfish加密数据流的类:

public class BlowfishOutputStream extends OutputStream
{
    private final OutputStream os;
    private final PaddedBufferedBlockCipher bufferedCipher;

我们的原始代码在单个操作中写入输出流之前加密了整个字节数组

public void write(byte[] raw, int offset, int length) throws IOException
{
    byte[] out = new byte[bufferedCipher.getOutputSize(length)];
    int result = this.bufferedCipher.processBytes(raw, 0, length, out, 0);
    if (result > 0)
    {
        this.os.write(out, 0, result);
    }
}

发送图像(即一次显示大量数据)时,会立即将两个副本保留在内存中。

以下代码是等同的,但不是,我不知道为什么。我可以验证数据是否正在发送(c2的总和等于length)但是在我们的服务器上接收到的中间过程会在我们看到到达之前丢弃图像。我在这个阶段所知道的是,当使用初始代码时,接收响应并且可以提取包含的图像,当使用替换代码时,接收(并接受)响应但是看起来没有提取图像。

public void write(byte[] raw, int offset, int length) throws IOException
{
    // write to the output stream as we encrypt, not all at once.
    final byte[] inBuffer = new byte[Constants.ByteBufferSize];
    final byte[] outBuffer = new byte[Constants.ByteBufferSize];
    ByteArrayInputStream bis = new ByteArrayInputStream(raw);
    // read into inBuffer, encrypt into outBuffer and write to output stream
    for (int len; (len = bis.read(inBuffer)) != -1;)
    {
        int c2 = this.bufferedCipher.processBytes(inBuffer, 0, len, outBuffer, 0);
        this.os.write(outBuffer, 0, c2);
    }
}

注意由于缺少对doFinal的调用而导致问题,因为在关闭流时会调用此问题。

public void close() throws IOException
{
    byte[] out = new byte[bufferedCipher.getOutputSize(0)];
    int result = this.bufferedCipher.doFinal(out, 0);
    if (result > 0)
    {
        this.os.write(out, 0, result);
    }
    *nb try/catch omitted*
}

1 个答案:

答案 0 :(得分:2)

确认,虽然具有讽刺意味的是问题不在于图像,而在于以前的数据,但是数据写的是完整的raw字节数组,而不仅仅是指定的范围。用于加速字节数组的等效代码是:

@Override
public void write(byte[] raw, int offset, int length) throws IOException
{
    // write to the stream as we encrypt, not all at once.
    final byte[] inBuffer = new byte[Constants.ByteBufferSize];
    final byte[] outBuffer = new byte[Constants.ByteBufferSize];
    int readStart = offset;
    // read into inBuffer, encrypt into outBuffer and write to output stream
    while(readStart<length)
    {
        int readAmount = Math.min(length-readStart, inBuffer.length);
        System.arraycopy(raw, readStart, inBuffer, 0, readAmount);
        readStart+=readAmount;
        int c2 = this.bufferedCipher.processBytes(inBuffer, 0, readAmount, outBuffer, 0);
        this.os.write(outBuffer, 0, c2);
    }
}