1

我们有一个包装 BouncyCastle(实际上是 Android 的 SpongyCastle)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*
}
4

1 回答 1

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);
    }
}
于 2012-04-19T03:14:52.537 回答