1

BouncyCastle (実際には Android の SpongyCastle) Blowfish をラップしてデータを暗号化してストリーミングするクラスがあります。

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

元のコードは、1 回の操作で出力ストリームに書き込む前に、バイト配列全体を暗号化しました。

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);
    }
}

画像を送信する場合 (一度に大量のデータを送信する場合)、一度に 2 つのコピーがメモリに保持されます。

次のコードは同等であることを意図していますが、そうではありません。その理由はわかりません。データが送信されていることを確認できます (の合計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 に答える