HBASE-11446 Reduce the frequency of RNG calls in SecureWALCellCodec#EncryptedKvEncoder

This commit is contained in:
Andrew Purtell 2014-07-04 10:45:19 -07:00
parent 360df59c0d
commit 2416d798fa
7 changed files with 61 additions and 13 deletions

View File

@ -42,6 +42,12 @@ public interface Decryptor {
*/
public int getIvLength();
/**
* Get the cipher's internal block size
* @return the cipher's internal block size
*/
public int getBlockSize();
/**
* Set the initialization vector
* @param iv

View File

@ -537,16 +537,24 @@ public final class Encryption {
}
public static void incrementIv(byte[] iv) {
incrementIv(iv, 1);
}
public static void incrementIv(byte[] iv, int v) {
int length = iv.length;
boolean carry = true;
for (int i = 0; i < length; i++) {
if (carry) {
iv[i] = (byte) ((iv[i] + 1) & 0xFF);
carry = 0 == iv[i];
} else {
break;
// TODO: Optimize for v > 1, e.g. 16, 32
do {
for (int i = 0; i < length; i++) {
if (carry) {
iv[i] = (byte) ((iv[i] + 1) & 0xFF);
carry = 0 == iv[i];
} else {
break;
}
}
}
v--;
} while (v > 0);
}
}

View File

@ -42,6 +42,12 @@ public interface Encryptor {
*/
public int getIvLength();
/**
* Get the cipher's internal block size
* @return the cipher's internal block size
*/
public int getBlockSize();
/**
* Get the initialization vector
*/
@ -63,5 +69,4 @@ public interface Encryptor {
* Reset state, reinitialize with the key and iv
*/
void reset();
}

View File

@ -53,6 +53,7 @@ public class AES extends Cipher {
public static final int KEY_LENGTH = 16;
public static final int KEY_LENGTH_BITS = KEY_LENGTH * 8;
public static final int BLOCK_SIZE = 16;
public static final int IV_LENGTH = 16;
public static final String CIPHER_MODE_KEY = "hbase.crypto.algorithm.aes.mode";

View File

@ -58,6 +58,11 @@ public class AESDecryptor implements Decryptor {
return AES.IV_LENGTH;
}
@Override
public int getBlockSize() {
return AES.BLOCK_SIZE;
}
@Override
public void setIv(byte[] iv) {
Preconditions.checkNotNull(iv, "IV cannot be null");

View File

@ -60,6 +60,11 @@ public class AESEncryptor implements Encryptor {
return AES.IV_LENGTH;
}
@Override
public int getBlockSize() {
return AES.BLOCK_SIZE;
}
@Override
public byte[] getIv() {
return iv;

View File

@ -31,6 +31,7 @@ import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.codec.KeyValueCodec;
import org.apache.hadoop.hbase.io.crypto.Decryptor;
import org.apache.hadoop.hbase.io.crypto.Encryption;
import org.apache.hadoop.hbase.io.crypto.Encryptor;
import org.apache.hadoop.hbase.io.util.StreamUtils;
import org.apache.hadoop.hbase.util.Bytes;
@ -40,8 +41,6 @@ import org.apache.hadoop.hbase.util.Bytes;
*/
public class SecureWALCellCodec extends WALCellCodec {
private static final SecureRandom RNG = new SecureRandom();
private Encryptor encryptor;
private Decryptor decryptor;
@ -139,7 +138,24 @@ public class SecureWALCellCodec extends WALCellCodec {
static class EncryptedKvEncoder extends KeyValueCodec.KeyValueEncoder {
private Encryptor encryptor;
private byte[] iv;
private final ThreadLocal<byte[]> iv = new ThreadLocal<byte[]>() {
@Override
protected byte[] initialValue() {
byte[] iv = new byte[encryptor.getIvLength()];
new SecureRandom().nextBytes(iv);
return iv;
}
};
protected byte[] nextIv() {
byte[] b = iv.get(), ret = new byte[b.length];
System.arraycopy(b, 0, ret, 0, b.length);
return ret;
}
protected void incrementIv(int v) {
Encryption.incrementIv(iv.get(), 1 + (v / encryptor.getBlockSize()));
}
public EncryptedKvEncoder(OutputStream os) {
super(os);
@ -148,7 +164,6 @@ public class SecureWALCellCodec extends WALCellCodec {
public EncryptedKvEncoder(OutputStream os, Encryptor encryptor) {
super(os);
this.encryptor = encryptor;
iv = new byte[encryptor.getIvLength()];
}
@Override
@ -159,7 +174,7 @@ public class SecureWALCellCodec extends WALCellCodec {
byte[] kvBuffer = kv.getBuffer();
int offset = kv.getOffset();
RNG.nextBytes(iv);
byte[] iv = nextIv();
encryptor.setIv(iv);
encryptor.reset();
@ -196,6 +211,9 @@ public class SecureWALCellCodec extends WALCellCodec {
StreamUtils.writeRawVInt32(out, baos.size());
baos.writeTo(out);
// Increment IV given the final payload length
incrementIv(baos.size());
}
}