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) {
|
||||
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();
|
||||
byte[] iv = wrappedKey.hasIv() ? wrappedKey.getIv().toByteArray() : null;
|
||||
Encryption.decryptWithSubjectKey(out, wrappedKey.getData().newInput(),
|
||||
|
@ -132,4 +137,26 @@ public class EncryptionUtil {
|
|||
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
|
||||
if (walKeyName != null) {
|
||||
try {
|
||||
key = EncryptionUtil.unwrapKey(conf, walKeyName, keyBytes);
|
||||
key = EncryptionUtil.unwrapWALKey(conf, walKeyName, keyBytes);
|
||||
} catch (KeyException e) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Unable to unwrap key with WAL key '" + walKeyName + "'");
|
||||
|
@ -91,7 +91,7 @@ public class SecureProtobufLogReader extends ProtobufLogReader {
|
|||
User.getCurrent().getShortName());
|
||||
try {
|
||||
// Then, try the cluster master key
|
||||
key = EncryptionUtil.unwrapKey(conf, masterKeyName, keyBytes);
|
||||
key = EncryptionUtil.unwrapWALKey(conf, masterKeyName, keyBytes);
|
||||
} catch (KeyException e) {
|
||||
// If the current master key fails to unwrap, try the alternate, if
|
||||
// one is configured
|
||||
|
@ -102,7 +102,7 @@ public class SecureProtobufLogReader extends ProtobufLogReader {
|
|||
conf.get(HConstants.CRYPTO_MASTERKEY_ALTERNATE_NAME_CONF_KEY);
|
||||
if (alternateKeyName != null) {
|
||||
try {
|
||||
key = EncryptionUtil.unwrapKey(conf, alternateKeyName, keyBytes);
|
||||
key = EncryptionUtil.unwrapWALKey(conf, alternateKeyName, keyBytes);
|
||||
} catch (KeyException ex) {
|
||||
throw new IOException(ex);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue