/*
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
package com.facebook.crypto.streams;
import javax.crypto.Cipher;
import javax.crypto.ShortBufferException;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* The Cipher stream implementation in android is really slow.
* This provides a better cipher stream for java Ciphers.
* </p>
* If we ran benchmark code with the default cipher input stream in android,
* we would beat it hands down. We use this stream so that we can have a
* more fair comparison.
*/
public class BetterCipherInputStream extends FilterInputStream {
private static final int UPDATE_BUFFER_SIZE = 256;
private final Cipher mCipher;
private final byte[] mUpdateBuffer;
public BetterCipherInputStream(InputStream in, Cipher cipher) {
super(in);
mCipher = cipher;
mUpdateBuffer = new byte[UPDATE_BUFFER_SIZE];
}
@Override
public int read(byte[] buffer, int offset, int count) throws IOException {
int read = in.read(buffer, offset, count);
if (read == -1) {
return -1;
}
int times = read / UPDATE_BUFFER_SIZE;
int remainder = read % UPDATE_BUFFER_SIZE;
int originalOffset = offset;
int currentReadOffset = offset;
try {
for (int i = 0; i < times; ++i) {
int bytesDecrypted = mCipher.update(buffer, offset, UPDATE_BUFFER_SIZE, mUpdateBuffer);
System.arraycopy(mUpdateBuffer, 0, buffer, currentReadOffset, bytesDecrypted);
currentReadOffset += bytesDecrypted;
offset += UPDATE_BUFFER_SIZE;
}
if (remainder > 0) {
int bytesDecrypted = mCipher.update(buffer, offset, remainder, mUpdateBuffer);
System.arraycopy(mUpdateBuffer, 0, buffer, currentReadOffset, bytesDecrypted);
currentReadOffset += bytesDecrypted;
}
} catch (ShortBufferException e) {
// do nothing. This cannot happen, since we supply the correct lengths.
}
return currentReadOffset - originalOffset;
}
}