HBASE-11446 Reduce the frequency of RNG calls in SecureWALCellCodec#EncryptedKvEncoder
This commit is contained in:
parent
360df59c0d
commit
2416d798fa
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue