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();
|
public int getIvLength();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the cipher's internal block size
|
||||||
|
* @return the cipher's internal block size
|
||||||
|
*/
|
||||||
|
public int getBlockSize();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the initialization vector
|
* Set the initialization vector
|
||||||
* @param iv
|
* @param iv
|
||||||
|
|
|
@ -537,8 +537,14 @@ public final class Encryption {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void incrementIv(byte[] iv) {
|
public static void incrementIv(byte[] iv) {
|
||||||
|
incrementIv(iv, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void incrementIv(byte[] iv, int v) {
|
||||||
int length = iv.length;
|
int length = iv.length;
|
||||||
boolean carry = true;
|
boolean carry = true;
|
||||||
|
// TODO: Optimize for v > 1, e.g. 16, 32
|
||||||
|
do {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
if (carry) {
|
if (carry) {
|
||||||
iv[i] = (byte) ((iv[i] + 1) & 0xFF);
|
iv[i] = (byte) ((iv[i] + 1) & 0xFF);
|
||||||
|
@ -547,6 +553,8 @@ public final class Encryption {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
v--;
|
||||||
|
} while (v > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,12 @@ public interface Encryptor {
|
||||||
*/
|
*/
|
||||||
public int getIvLength();
|
public int getIvLength();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the cipher's internal block size
|
||||||
|
* @return the cipher's internal block size
|
||||||
|
*/
|
||||||
|
public int getBlockSize();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the initialization vector
|
* Get the initialization vector
|
||||||
*/
|
*/
|
||||||
|
@ -63,5 +69,4 @@ public interface Encryptor {
|
||||||
* Reset state, reinitialize with the key and iv
|
* Reset state, reinitialize with the key and iv
|
||||||
*/
|
*/
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ public class AES extends Cipher {
|
||||||
|
|
||||||
public static final int KEY_LENGTH = 16;
|
public static final int KEY_LENGTH = 16;
|
||||||
public static final int KEY_LENGTH_BITS = KEY_LENGTH * 8;
|
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 int IV_LENGTH = 16;
|
||||||
|
|
||||||
public static final String CIPHER_MODE_KEY = "hbase.crypto.algorithm.aes.mode";
|
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;
|
return AES.IV_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBlockSize() {
|
||||||
|
return AES.BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setIv(byte[] iv) {
|
public void setIv(byte[] iv) {
|
||||||
Preconditions.checkNotNull(iv, "IV cannot be null");
|
Preconditions.checkNotNull(iv, "IV cannot be null");
|
||||||
|
|
|
@ -60,6 +60,11 @@ public class AESEncryptor implements Encryptor {
|
||||||
return AES.IV_LENGTH;
|
return AES.IV_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBlockSize() {
|
||||||
|
return AES.BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] getIv() {
|
public byte[] getIv() {
|
||||||
return iv;
|
return iv;
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.apache.hadoop.hbase.Cell;
|
||||||
import org.apache.hadoop.hbase.KeyValue;
|
import org.apache.hadoop.hbase.KeyValue;
|
||||||
import org.apache.hadoop.hbase.codec.KeyValueCodec;
|
import org.apache.hadoop.hbase.codec.KeyValueCodec;
|
||||||
import org.apache.hadoop.hbase.io.crypto.Decryptor;
|
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.crypto.Encryptor;
|
||||||
import org.apache.hadoop.hbase.io.util.StreamUtils;
|
import org.apache.hadoop.hbase.io.util.StreamUtils;
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
|
@ -40,8 +41,6 @@ import org.apache.hadoop.hbase.util.Bytes;
|
||||||
*/
|
*/
|
||||||
public class SecureWALCellCodec extends WALCellCodec {
|
public class SecureWALCellCodec extends WALCellCodec {
|
||||||
|
|
||||||
private static final SecureRandom RNG = new SecureRandom();
|
|
||||||
|
|
||||||
private Encryptor encryptor;
|
private Encryptor encryptor;
|
||||||
private Decryptor decryptor;
|
private Decryptor decryptor;
|
||||||
|
|
||||||
|
@ -139,7 +138,24 @@ public class SecureWALCellCodec extends WALCellCodec {
|
||||||
static class EncryptedKvEncoder extends KeyValueCodec.KeyValueEncoder {
|
static class EncryptedKvEncoder extends KeyValueCodec.KeyValueEncoder {
|
||||||
|
|
||||||
private Encryptor encryptor;
|
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) {
|
public EncryptedKvEncoder(OutputStream os) {
|
||||||
super(os);
|
super(os);
|
||||||
|
@ -148,7 +164,6 @@ public class SecureWALCellCodec extends WALCellCodec {
|
||||||
public EncryptedKvEncoder(OutputStream os, Encryptor encryptor) {
|
public EncryptedKvEncoder(OutputStream os, Encryptor encryptor) {
|
||||||
super(os);
|
super(os);
|
||||||
this.encryptor = encryptor;
|
this.encryptor = encryptor;
|
||||||
iv = new byte[encryptor.getIvLength()];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -159,7 +174,7 @@ public class SecureWALCellCodec extends WALCellCodec {
|
||||||
byte[] kvBuffer = kv.getBuffer();
|
byte[] kvBuffer = kv.getBuffer();
|
||||||
int offset = kv.getOffset();
|
int offset = kv.getOffset();
|
||||||
|
|
||||||
RNG.nextBytes(iv);
|
byte[] iv = nextIv();
|
||||||
encryptor.setIv(iv);
|
encryptor.setIv(iv);
|
||||||
encryptor.reset();
|
encryptor.reset();
|
||||||
|
|
||||||
|
@ -196,6 +211,9 @@ public class SecureWALCellCodec extends WALCellCodec {
|
||||||
|
|
||||||
StreamUtils.writeRawVInt32(out, baos.size());
|
StreamUtils.writeRawVInt32(out, baos.size());
|
||||||
baos.writeTo(out);
|
baos.writeTo(out);
|
||||||
|
|
||||||
|
// Increment IV given the final payload length
|
||||||
|
incrementIv(baos.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue