HBASE-13048 Use hbase.crypto.wal.algorithm in SecureProtobufLogReader while decrypting the data
Signed-off-by: Andrew Purtell <apurtell@apache.org>
This commit is contained in:
parent
a2123144ff
commit
9e9a98fdb1
|
@ -119,6 +119,11 @@ public class EncryptionUtil {
|
||||||
if (cipher == null) {
|
if (cipher == null) {
|
||||||
throw new RuntimeException("Cipher '" + algorithm + "' not available");
|
throw new RuntimeException("Cipher '" + algorithm + "' not available");
|
||||||
}
|
}
|
||||||
|
return getUnwrapKey(conf, subject, wrappedKey, cipher);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Key getUnwrapKey(Configuration conf, String subject,
|
||||||
|
EncryptionProtos.WrappedKey wrappedKey, Cipher cipher) throws IOException, KeyException {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
byte[] iv = wrappedKey.hasIv() ? wrappedKey.getIv().toByteArray() : null;
|
byte[] iv = wrappedKey.hasIv() ? wrappedKey.getIv().toByteArray() : null;
|
||||||
Encryption.decryptWithSubjectKey(out, wrappedKey.getData().newInput(),
|
Encryption.decryptWithSubjectKey(out, wrappedKey.getData().newInput(),
|
||||||
|
@ -132,4 +137,26 @@ public class EncryptionUtil {
|
||||||
return new SecretKeySpec(keyBytes, wrappedKey.getAlgorithm());
|
return new SecretKeySpec(keyBytes, wrappedKey.getAlgorithm());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unwrap a wal key by decrypting it with the secret key of the given subject. The configuration
|
||||||
|
* must be set up correctly for key alias resolution.
|
||||||
|
* @param conf configuration
|
||||||
|
* @param subject subject key alias
|
||||||
|
* @param value the encrypted key bytes
|
||||||
|
* @return the raw key bytes
|
||||||
|
* @throws IOException if key is not found for the subject, or if some I/O error occurs
|
||||||
|
* @throws KeyException if fail to unwrap the key
|
||||||
|
*/
|
||||||
|
public static Key unwrapWALKey(Configuration conf, String subject, byte[] value)
|
||||||
|
throws IOException, KeyException {
|
||||||
|
EncryptionProtos.WrappedKey wrappedKey =
|
||||||
|
EncryptionProtos.WrappedKey.PARSER.parseDelimitedFrom(new ByteArrayInputStream(value));
|
||||||
|
String algorithm = conf.get(HConstants.CRYPTO_WAL_ALGORITHM_CONF_KEY, HConstants.CIPHER_AES);
|
||||||
|
Cipher cipher = Encryption.getCipher(conf, algorithm);
|
||||||
|
if (cipher == null) {
|
||||||
|
throw new RuntimeException("Cipher '" + algorithm + "' not available");
|
||||||
|
}
|
||||||
|
return getUnwrapKey(conf, subject, wrappedKey, cipher);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,4 +73,49 @@ public class TestEncryptionUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWALKeyWrapping() throws Exception {
|
||||||
|
// set up the key provider for testing to resolve a key for our test subject
|
||||||
|
Configuration conf = new Configuration(); // we don't need HBaseConfiguration for this
|
||||||
|
conf.set(HConstants.CRYPTO_KEYPROVIDER_CONF_KEY, KeyProviderForTesting.class.getName());
|
||||||
|
|
||||||
|
// generate a test key
|
||||||
|
byte[] keyBytes = new byte[AES.KEY_LENGTH];
|
||||||
|
new SecureRandom().nextBytes(keyBytes);
|
||||||
|
String algorithm = conf.get(HConstants.CRYPTO_WAL_ALGORITHM_CONF_KEY, HConstants.CIPHER_AES);
|
||||||
|
Key key = new SecretKeySpec(keyBytes, algorithm);
|
||||||
|
|
||||||
|
// wrap the test key
|
||||||
|
byte[] wrappedKeyBytes = EncryptionUtil.wrapKey(conf, "hbase", key);
|
||||||
|
assertNotNull(wrappedKeyBytes);
|
||||||
|
|
||||||
|
// unwrap
|
||||||
|
Key unwrappedKey = EncryptionUtil.unwrapWALKey(conf, "hbase", wrappedKeyBytes);
|
||||||
|
assertNotNull(unwrappedKey);
|
||||||
|
// only secretkeyspec supported for now
|
||||||
|
assertTrue(unwrappedKey instanceof SecretKeySpec);
|
||||||
|
// did we get back what we wrapped?
|
||||||
|
assertTrue("Unwrapped key bytes do not match original",
|
||||||
|
Bytes.equals(keyBytes, unwrappedKey.getEncoded()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = KeyException.class)
|
||||||
|
public void testWALKeyWrappingWithIncorrectKey() throws Exception {
|
||||||
|
// set up the key provider for testing to resolve a key for our test subject
|
||||||
|
Configuration conf = new Configuration(); // we don't need HBaseConfiguration for this
|
||||||
|
conf.set(HConstants.CRYPTO_KEYPROVIDER_CONF_KEY, KeyProviderForTesting.class.getName());
|
||||||
|
|
||||||
|
// generate a test key
|
||||||
|
byte[] keyBytes = new byte[AES.KEY_LENGTH];
|
||||||
|
new SecureRandom().nextBytes(keyBytes);
|
||||||
|
String algorithm = conf.get(HConstants.CRYPTO_WAL_ALGORITHM_CONF_KEY, HConstants.CIPHER_AES);
|
||||||
|
Key key = new SecretKeySpec(keyBytes, algorithm);
|
||||||
|
|
||||||
|
// wrap the test key
|
||||||
|
byte[] wrappedKeyBytes = EncryptionUtil.wrapKey(conf, "hbase", key);
|
||||||
|
assertNotNull(wrappedKeyBytes);
|
||||||
|
|
||||||
|
// unwrap with an incorrect key
|
||||||
|
EncryptionUtil.unwrapWALKey(conf, "other", wrappedKeyBytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ public class SecureProtobufLogReader extends ProtobufLogReader {
|
||||||
// First try the WAL key, if one is configured
|
// First try the WAL key, if one is configured
|
||||||
if (walKeyName != null) {
|
if (walKeyName != null) {
|
||||||
try {
|
try {
|
||||||
key = EncryptionUtil.unwrapKey(conf, walKeyName, keyBytes);
|
key = EncryptionUtil.unwrapWALKey(conf, walKeyName, keyBytes);
|
||||||
} catch (KeyException e) {
|
} catch (KeyException e) {
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
LOG.debug("Unable to unwrap key with WAL key '" + walKeyName + "'");
|
LOG.debug("Unable to unwrap key with WAL key '" + walKeyName + "'");
|
||||||
|
@ -91,7 +91,7 @@ public class SecureProtobufLogReader extends ProtobufLogReader {
|
||||||
User.getCurrent().getShortName());
|
User.getCurrent().getShortName());
|
||||||
try {
|
try {
|
||||||
// Then, try the cluster master key
|
// Then, try the cluster master key
|
||||||
key = EncryptionUtil.unwrapKey(conf, masterKeyName, keyBytes);
|
key = EncryptionUtil.unwrapWALKey(conf, masterKeyName, keyBytes);
|
||||||
} catch (KeyException e) {
|
} catch (KeyException e) {
|
||||||
// If the current master key fails to unwrap, try the alternate, if
|
// If the current master key fails to unwrap, try the alternate, if
|
||||||
// one is configured
|
// one is configured
|
||||||
|
@ -102,7 +102,7 @@ public class SecureProtobufLogReader extends ProtobufLogReader {
|
||||||
conf.get(HConstants.CRYPTO_MASTERKEY_ALTERNATE_NAME_CONF_KEY);
|
conf.get(HConstants.CRYPTO_MASTERKEY_ALTERNATE_NAME_CONF_KEY);
|
||||||
if (alternateKeyName != null) {
|
if (alternateKeyName != null) {
|
||||||
try {
|
try {
|
||||||
key = EncryptionUtil.unwrapKey(conf, alternateKeyName, keyBytes);
|
key = EncryptionUtil.unwrapWALKey(conf, alternateKeyName, keyBytes);
|
||||||
} catch (KeyException ex) {
|
} catch (KeyException ex) {
|
||||||
throw new IOException(ex);
|
throw new IOException(ex);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue