@BeforeClass public static void setUp() throws Exception { Configuration conf = TEST_UTIL.getConfiguration(); // Disable block cache in this test. conf.setFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, 0.0f); conf.set(HConstants.CRYPTO_KEYPROVIDER_CONF_KEY, KeyProviderForTesting.class.getName()); conf.set(HConstants.CRYPTO_MASTERKEY_NAME_CONF_KEY, "hbase"); conf.setInt("hfile.format.version", 3); fs = FileSystem.get(conf); cryptoContext = Encryption.newContext(conf); String algorithm = conf.get(HConstants.CRYPTO_KEY_ALGORITHM_CONF_KEY, HConstants.CIPHER_AES); Cipher aes = Encryption.getCipher(conf, algorithm); assertNotNull(aes); cryptoContext.setCipher(aes); byte[] key = new byte[aes.getKeyLength()]; RNG.nextBytes(key); cryptoContext.setKey(key); }
@BeforeClass public static void setUp() throws Exception { Configuration conf = TEST_UTIL.getConfiguration(); conf.set(HConstants.CRYPTO_KEYPROVIDER_CONF_KEY, KeyProviderForTesting.class.getName()); conf.set(HConstants.CRYPTO_MASTERKEY_NAME_CONF_KEY, "hbase"); conf.setInt("hfile.format.version", 3); fs = FileSystem.get(conf); cryptoContext = Encryption.newContext(conf); Cipher aes = Encryption.getCipher(conf, "AES"); assertNotNull(aes); cryptoContext.setCipher(aes); byte[] key = new byte[aes.getKeyLength()]; RNG.nextBytes(key); cryptoContext.setKey(key); }
/** * Unwrap a key by decrypting it with the secret key of the given subject. * The configuration must be set up correctly for key alias resolution. Keys * are always unwrapped using AES. * @param conf configuration * @param subject subject key alias * @param value the encrypted key bytes * @return the raw key bytes * @throws IOException * @throws KeyException */ public static Key unwrapKey(Configuration conf, String subject, byte[] value) throws IOException, KeyException { EncryptionProtos.WrappedKey wrappedKey = EncryptionProtos.WrappedKey.PARSER .parseDelimitedFrom(new ByteArrayInputStream(value)); Cipher cipher = Encryption.getCipher(conf, "AES"); if (cipher == null) { throw new RuntimeException("Algorithm 'AES' not available"); } ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] iv = wrappedKey.hasIv() ? wrappedKey.getIv().toByteArray() : null; Encryption.decryptWithSubjectKey(out, wrappedKey.getData().newInput(), wrappedKey.getLength(), subject, conf, cipher, iv); byte[] keyBytes = out.toByteArray(); if (wrappedKey.hasHash()) { if (!Bytes.equals(wrappedKey.getHash().toByteArray(), Encryption.hash128(keyBytes))) { throw new KeyException("Key was not successfully unwrapped"); } } return new SecretKeySpec(keyBytes, wrappedKey.getAlgorithm()); }
@Override protected WALHeader buildWALHeader(Configuration conf, WALHeader.Builder builder) throws IOException { builder.setWriterClsName(SecureProtobufLogWriter.class.getSimpleName()); if (conf.getBoolean(HConstants.ENABLE_WAL_ENCRYPTION, false)) { EncryptionTest.testKeyProvider(conf); EncryptionTest.testCipherProvider(conf); // Get an instance of our cipher final String cipherName = conf.get(HConstants.CRYPTO_WAL_ALGORITHM_CONF_KEY, HConstants.CIPHER_AES); Cipher cipher = Encryption.getCipher(conf, cipherName); if (cipher == null) { throw new RuntimeException("Cipher '" + cipherName + "' is not available"); } // Generate an encryption key for this WAL SecureRandom rng = new SecureRandom(); byte[] keyBytes = new byte[cipher.getKeyLength()]; rng.nextBytes(keyBytes); Key key = new SecretKeySpec(keyBytes, cipher.getName()); builder.setEncryptionKey(ByteStringer.wrap(EncryptionUtil.wrapKey(conf, conf.get(HConstants.CRYPTO_WAL_KEY_NAME_CONF_KEY, conf.get(HConstants.CRYPTO_MASTERKEY_NAME_CONF_KEY, User.getCurrent().getShortName())), key))); // Set up the encryptor encryptor = cipher.getEncryptor(); encryptor.setKey(key); if (LOG.isTraceEnabled()) { LOG.trace("Initialized secure protobuf WAL: cipher=" + cipher.getName()); } } builder.setCellCodecClsName(SecureWALCellCodec.class.getName()); return super.buildWALHeader(conf, builder); }
/** * Protect a key by encrypting 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 key the key * @return the encrypted key bytes */ public static byte[] wrapKey(Configuration conf, String subject, Key key) throws IOException { // Wrap the key with the configured encryption algorithm. String algorithm = conf.get(HConstants.CRYPTO_KEY_ALGORITHM_CONF_KEY, HConstants.CIPHER_AES); Cipher cipher = Encryption.getCipher(conf, algorithm); if (cipher == null) { throw new RuntimeException("Cipher '" + algorithm + "' not available"); } EncryptionProtos.WrappedKey.Builder builder = EncryptionProtos.WrappedKey.newBuilder(); builder.setAlgorithm(key.getAlgorithm()); byte[] iv = null; if (cipher.getIvLength() > 0) { iv = new byte[cipher.getIvLength()]; RNG.nextBytes(iv); builder.setIv(ByteStringer.wrap(iv)); } byte[] keyBytes = key.getEncoded(); builder.setLength(keyBytes.length); builder.setHash(ByteStringer.wrap(Encryption.hash128(keyBytes))); ByteArrayOutputStream out = new ByteArrayOutputStream(); Encryption.encryptWithSubjectKey(out, new ByteArrayInputStream(keyBytes), subject, conf, cipher, iv); builder.setData(ByteStringer.wrap(out.toByteArray())); // Build and return the protobuf message out.reset(); builder.build().writeDelimitedTo(out); return out.toByteArray(); }
/** * Unwrap a 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 * @throws KeyException */ public static Key unwrapKey(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_KEY_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); }
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(), wrappedKey.getLength(), subject, conf, cipher, iv); byte[] keyBytes = out.toByteArray(); if (wrappedKey.hasHash()) { if (!Bytes.equals(wrappedKey.getHash().toByteArray(), Encryption.hash128(keyBytes))) { throw new KeyException("Key was not successfully unwrapped"); } } 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); }
private javax.crypto.Cipher getJCECipherInstance() { try { if (cipherProvider != null) { return javax.crypto.Cipher.getInstance(cipherMode, cipherProvider); } return javax.crypto.Cipher.getInstance(cipherMode); } catch (GeneralSecurityException e) { throw new RuntimeException(e); } }
@Test public void testAESAlgorithm() throws Exception { Configuration conf = HBaseConfiguration.create(); Cipher aes = Encryption.getCipher(conf, "AES"); assertEquals(aes.getKeyLength(), AES.KEY_LENGTH); assertEquals(aes.getIvLength(), AES.IV_LENGTH); Encryptor e = aes.getEncryptor(); e.setKey(new SecretKeySpec(Bytes.fromHex("2b7e151628aed2a6abf7158809cf4f3c"), "AES")); e.setIv(Bytes.fromHex("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff")); ByteArrayOutputStream out = new ByteArrayOutputStream(); OutputStream cout = e.createEncryptionStream(out); cout.write(Bytes.fromHex("6bc1bee22e409f96e93d7e117393172a")); cout.write(Bytes.fromHex("ae2d8a571e03ac9c9eb76fac45af8e51")); cout.write(Bytes.fromHex("30c81c46a35ce411e5fbc1191a0a52ef")); cout.write(Bytes.fromHex("f69f2445df4f9b17ad2b417be66c3710")); cout.close(); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); byte[] b = new byte[16]; IOUtils.readFully(in, b); assertTrue("Failed #1", Bytes.equals(b, Bytes.fromHex("874d6191b620e3261bef6864990db6ce"))); IOUtils.readFully(in, b); assertTrue("Failed #2", Bytes.equals(b, Bytes.fromHex("9806f66b7970fdff8617187bb9fffdff"))); IOUtils.readFully(in, b); assertTrue("Failed #3", Bytes.equals(b, Bytes.fromHex("5ae4df3edbd5d35e5b4f09020db03eab"))); IOUtils.readFully(in, b); assertTrue("Failed #4", Bytes.equals(b, Bytes.fromHex("1e031dda2fbe03d1792170a0f3009cee"))); }
@Override protected WALHeader buildWALHeader(Configuration conf, WALHeader.Builder builder) throws IOException { builder.setWriterClsName(SecureProtobufLogWriter.class.getSimpleName()); if (conf.getBoolean(HConstants.ENABLE_WAL_ENCRYPTION, false)) { EncryptionTest.testKeyProvider(conf); EncryptionTest.testCipherProvider(conf); // Get an instance of our cipher final String cipherName = conf.get(HConstants.CRYPTO_WAL_ALGORITHM_CONF_KEY, DEFAULT_CIPHER); Cipher cipher = Encryption.getCipher(conf, cipherName); if (cipher == null) { throw new RuntimeException("Cipher '" + cipherName + "' is not available"); } // Generate an encryption key for this WAL SecureRandom rng = new SecureRandom(); byte[] keyBytes = new byte[cipher.getKeyLength()]; rng.nextBytes(keyBytes); Key key = new SecretKeySpec(keyBytes, cipher.getName()); builder.setEncryptionKey(ByteStringer.wrap(EncryptionUtil.wrapKey(conf, conf.get(HConstants.CRYPTO_WAL_KEY_NAME_CONF_KEY, conf.get(HConstants.CRYPTO_MASTERKEY_NAME_CONF_KEY, User.getCurrent().getShortName())), key))); // Set up the encryptor encryptor = cipher.getEncryptor(); encryptor.setKey(key); if (LOG.isTraceEnabled()) { LOG.trace("Initialized secure protobuf WAL: cipher=" + cipher.getName()); } } builder.setCellCodecClsName(SecureWALCellCodec.class.getName()); return super.buildWALHeader(conf, builder); }
/** * Protect a key by encrypting it with the secret key of the given subject. * The configuration must be set up correctly for key alias resolution. Keys * are always wrapped using AES. * @param conf configuration * @param subject subject key alias * @param key the key * @return the encrypted key bytes */ public static byte[] wrapKey(Configuration conf, String subject, Key key) throws IOException { // Wrap the key with AES Cipher cipher = Encryption.getCipher(conf, "AES"); if (cipher == null) { throw new RuntimeException("Cipher 'AES' not available"); } EncryptionProtos.WrappedKey.Builder builder = EncryptionProtos.WrappedKey.newBuilder(); builder.setAlgorithm(key.getAlgorithm()); byte[] iv = null; if (cipher.getIvLength() > 0) { iv = new byte[cipher.getIvLength()]; RNG.nextBytes(iv); builder.setIv(ByteStringer.wrap(iv)); } byte[] keyBytes = key.getEncoded(); builder.setLength(keyBytes.length); builder.setHash(ByteStringer.wrap(Encryption.hash128(keyBytes))); ByteArrayOutputStream out = new ByteArrayOutputStream(); Encryption.encryptWithSubjectKey(out, new ByteArrayInputStream(keyBytes), subject, conf, cipher, iv); builder.setData(ByteStringer.wrap(out.toByteArray())); // Build and return the protobuf message out.reset(); builder.build().writeDelimitedTo(out); return out.toByteArray(); }
@Override protected WALHeader buildWALHeader(WALHeader.Builder builder) throws IOException { if (conf.getBoolean(HConstants.ENABLE_WAL_ENCRYPTION, false)) { // Get an instance of our cipher Cipher cipher = Encryption.getCipher(conf, conf.get(HConstants.CRYPTO_WAL_ALGORITHM_CONF_KEY, DEFAULT_CIPHER)); if (cipher == null) { throw new RuntimeException("Cipher '" + cipher + "' is not available"); } // Generate an encryption key for this WAL SecureRandom rng = new SecureRandom(); byte[] keyBytes = new byte[cipher.getKeyLength()]; rng.nextBytes(keyBytes); Key key = new SecretKeySpec(keyBytes, cipher.getName()); builder.setEncryptionKey(HBaseZeroCopyByteString.wrap(EncryptionUtil.wrapKey(conf, conf.get(HConstants.CRYPTO_WAL_KEY_NAME_CONF_KEY, conf.get(HConstants.CRYPTO_MASTERKEY_NAME_CONF_KEY, User.getCurrent().getShortName())), key))); // Set up the encryptor encryptor = cipher.getEncryptor(); encryptor.setKey(key); if (LOG.isTraceEnabled()) { LOG.trace("Initialized secure protobuf WAL: cipher=" + cipher.getName()); } } return super.buildWALHeader(builder); }
/** * Protect a key by encrypting it with the secret key of the given subject. * The configuration must be set up correctly for key alias resolution. Keys * are always wrapped using AES. * @param conf configuration * @param subject subject key alias * @param key the key * @return the encrypted key bytes */ public static byte[] wrapKey(Configuration conf, String subject, Key key) throws IOException { // Wrap the key with AES Cipher cipher = Encryption.getCipher(conf, "AES"); if (cipher == null) { throw new RuntimeException("Cipher 'AES' not available"); } EncryptionProtos.WrappedKey.Builder builder = EncryptionProtos.WrappedKey.newBuilder(); builder.setAlgorithm(key.getAlgorithm()); byte[] iv = null; if (cipher.getIvLength() > 0) { iv = new byte[cipher.getIvLength()]; RNG.nextBytes(iv); builder.setIv(HBaseZeroCopyByteString.wrap(iv)); } byte[] keyBytes = key.getEncoded(); builder.setLength(keyBytes.length); builder.setHash(HBaseZeroCopyByteString.wrap(Encryption.hash128(keyBytes))); ByteArrayOutputStream out = new ByteArrayOutputStream(); Encryption.encryptWithSubjectKey(out, new ByteArrayInputStream(keyBytes), subject, conf, cipher, iv); builder.setData(HBaseZeroCopyByteString.wrap(out.toByteArray())); // Build and return the protobuf message out.reset(); builder.build().writeDelimitedTo(out); return out.toByteArray(); }
protected final WALHeader buildSecureWALHeader(Configuration conf, WALHeader.Builder builder) throws IOException { builder.setWriterClsName(getWriterClassName()); if (conf.getBoolean(HConstants.ENABLE_WAL_ENCRYPTION, false)) { EncryptionTest.testKeyProvider(conf); EncryptionTest.testCipherProvider(conf); // Get an instance of our cipher final String cipherName = conf.get(HConstants.CRYPTO_WAL_ALGORITHM_CONF_KEY, HConstants.CIPHER_AES); Cipher cipher = Encryption.getCipher(conf, cipherName); if (cipher == null) { throw new RuntimeException("Cipher '" + cipherName + "' is not available"); } // Generate an encryption key for this WAL SecureRandom rng = new SecureRandom(); byte[] keyBytes = new byte[cipher.getKeyLength()]; rng.nextBytes(keyBytes); Key key = new SecretKeySpec(keyBytes, cipher.getName()); builder.setEncryptionKey(UnsafeByteOperations.unsafeWrap(EncryptionUtil.wrapKey(conf, conf.get(HConstants.CRYPTO_WAL_KEY_NAME_CONF_KEY, conf.get(HConstants.CRYPTO_MASTERKEY_NAME_CONF_KEY, User.getCurrent().getShortName())), key))); // Set up the encryptor Encryptor encryptor = cipher.getEncryptor(); encryptor.setKey(key); setEncryptor(encryptor); if (LOG.isTraceEnabled()) { LOG.trace("Initialized secure protobuf WAL: cipher=" + cipher.getName()); } } builder.setCellCodecClsName(SecureWALCellCodec.class.getName()); return buildWALHeader0(conf, builder); }
protected HFileContext createHFileContext(FSDataInputStreamWrapper fsdis, long fileSize, HFileSystem hfs, Path path, FixedFileTrailer trailer) throws IOException { HFileContextBuilder builder = new HFileContextBuilder() .withIncludesMvcc(shouldIncludeMemStoreTS()) .withHBaseCheckSum(true) .withHFileName(this.getName()) .withCompression(this.compressAlgo); // Check for any key material available byte[] keyBytes = trailer.getEncryptionKey(); if (keyBytes != null) { Encryption.Context cryptoContext = Encryption.newContext(conf); Key key; key = EncryptionUtil.unwrapKey(conf, keyBytes); // Use the algorithm the key wants Cipher cipher = Encryption.getCipher(conf, key.getAlgorithm()); if (cipher == null) { throw new IOException("Cipher '" + key.getAlgorithm() + "' is not available"); } cryptoContext.setCipher(cipher); cryptoContext.setKey(key); builder.withEncryptionContext(cryptoContext); } HFileContext context = builder.build(); if (LOG.isTraceEnabled()) { LOG.trace("Reader" + (path != null? " for " + path: "") + " initialized with cacheConf: " + cacheConf + " comparator: " + comparator.getClass().getSimpleName() + " fileContext: " + context); } return context; }
/** * Protect a key by encrypting 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 key the key * @return the encrypted key bytes */ public static byte[] wrapKey(Configuration conf, String subject, Key key) throws IOException { // Wrap the key with the configured encryption algorithm. String algorithm = conf.get(HConstants.CRYPTO_KEY_ALGORITHM_CONF_KEY, HConstants.CIPHER_AES); Cipher cipher = Encryption.getCipher(conf, algorithm); if (cipher == null) { throw new RuntimeException("Cipher '" + algorithm + "' not available"); } EncryptionProtos.WrappedKey.Builder builder = EncryptionProtos.WrappedKey.newBuilder(); builder.setAlgorithm(key.getAlgorithm()); byte[] iv = null; if (cipher.getIvLength() > 0) { iv = new byte[cipher.getIvLength()]; RNG.nextBytes(iv); builder.setIv(UnsafeByteOperations.unsafeWrap(iv)); } byte[] keyBytes = key.getEncoded(); builder.setLength(keyBytes.length); builder.setHash(UnsafeByteOperations.unsafeWrap(Encryption.hash128(keyBytes))); ByteArrayOutputStream out = new ByteArrayOutputStream(); Encryption.encryptWithSubjectKey(out, new ByteArrayInputStream(keyBytes), subject, conf, cipher, iv); builder.setData(UnsafeByteOperations.unsafeWrap(out.toByteArray())); // Build and return the protobuf message out.reset(); builder.build().writeDelimitedTo(out); return out.toByteArray(); }
/** * Helper to create an encyption context. * * @param conf The current configuration. * @param family The current column descriptor. * @return The created encryption context. * @throws IOException if an encryption key for the column cannot be unwrapped */ public static Encryption.Context createEncryptionContext(Configuration conf, ColumnFamilyDescriptor family) throws IOException { Encryption.Context cryptoContext = Encryption.Context.NONE; String cipherName = family.getEncryptionType(); if (cipherName != null) { Cipher cipher; Key key; byte[] keyBytes = family.getEncryptionKey(); if (keyBytes != null) { // Family provides specific key material key = unwrapKey(conf, keyBytes); // Use the algorithm the key wants cipher = Encryption.getCipher(conf, key.getAlgorithm()); if (cipher == null) { throw new RuntimeException("Cipher '" + key.getAlgorithm() + "' is not available"); } // Fail if misconfigured // We use the encryption type specified in the column schema as a sanity check on // what the wrapped key is telling us if (!cipher.getName().equalsIgnoreCase(cipherName)) { throw new RuntimeException("Encryption for family '" + family.getNameAsString() + "' configured with type '" + cipherName + "' but key specifies algorithm '" + cipher.getName() + "'"); } } else { // Family does not provide key material, create a random key cipher = Encryption.getCipher(conf, cipherName); if (cipher == null) { throw new RuntimeException("Cipher '" + cipherName + "' is not available"); } key = cipher.getRandomKey(); } cryptoContext = Encryption.newContext(conf); cryptoContext.setCipher(cipher); cryptoContext.setKey(key); } return cryptoContext; }
@Test public void testAESAlgorithm() throws Exception { Configuration conf = HBaseConfiguration.create(); Cipher aes = Encryption.getCipher(conf, "AES"); assertEquals(AES.KEY_LENGTH, aes.getKeyLength()); assertEquals(AES.IV_LENGTH, aes.getIvLength()); Encryptor e = aes.getEncryptor(); e.setKey(new SecretKeySpec(Bytes.fromHex("2b7e151628aed2a6abf7158809cf4f3c"), "AES")); e.setIv(Bytes.fromHex("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff")); ByteArrayOutputStream out = new ByteArrayOutputStream(); OutputStream cout = e.createEncryptionStream(out); cout.write(Bytes.fromHex("6bc1bee22e409f96e93d7e117393172a")); cout.write(Bytes.fromHex("ae2d8a571e03ac9c9eb76fac45af8e51")); cout.write(Bytes.fromHex("30c81c46a35ce411e5fbc1191a0a52ef")); cout.write(Bytes.fromHex("f69f2445df4f9b17ad2b417be66c3710")); cout.close(); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); byte[] b = new byte[16]; IOUtils.readFully(in, b); assertTrue("Failed #1", Bytes.equals(b, Bytes.fromHex("874d6191b620e3261bef6864990db6ce"))); IOUtils.readFully(in, b); assertTrue("Failed #2", Bytes.equals(b, Bytes.fromHex("9806f66b7970fdff8617187bb9fffdff"))); IOUtils.readFully(in, b); assertTrue("Failed #3", Bytes.equals(b, Bytes.fromHex("5ae4df3edbd5d35e5b4f09020db03eab"))); IOUtils.readFully(in, b); assertTrue("Failed #4", Bytes.equals(b, Bytes.fromHex("1e031dda2fbe03d1792170a0f3009cee"))); }
@Test public void testAESAlgorithm() throws Exception { Configuration conf = HBaseConfiguration.create(); Cipher aes = Encryption.getCipher(conf, "AES"); assertEquals(CommonsCryptoAES.KEY_LENGTH, aes.getKeyLength()); assertEquals(CommonsCryptoAES.IV_LENGTH, aes.getIvLength()); Encryptor e = aes.getEncryptor(); e.setKey(new SecretKeySpec(Bytes.fromHex("2b7e151628aed2a6abf7158809cf4f3c"), "AES")); e.setIv(Bytes.fromHex("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff")); ByteArrayOutputStream out = new ByteArrayOutputStream(); OutputStream cout = e.createEncryptionStream(out); cout.write(Bytes.fromHex("6bc1bee22e409f96e93d7e117393172a")); cout.write(Bytes.fromHex("ae2d8a571e03ac9c9eb76fac45af8e51")); cout.write(Bytes.fromHex("30c81c46a35ce411e5fbc1191a0a52ef")); cout.write(Bytes.fromHex("f69f2445df4f9b17ad2b417be66c3710")); cout.close(); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); byte[] b = new byte[16]; IOUtils.readFully(in, b); assertTrue("Failed #1", Bytes.equals(b, Bytes.fromHex("874d6191b620e3261bef6864990db6ce"))); IOUtils.readFully(in, b); assertTrue("Failed #2", Bytes.equals(b, Bytes.fromHex("9806f66b7970fdff8617187bb9fffdff"))); IOUtils.readFully(in, b); assertTrue("Failed #3", Bytes.equals(b, Bytes.fromHex("5ae4df3edbd5d35e5b4f09020db03eab"))); IOUtils.readFully(in, b); assertTrue("Failed #4", Bytes.equals(b, Bytes.fromHex("1e031dda2fbe03d1792170a0f3009cee"))); }
@Override protected HFileContext createHFileContext(FSDataInputStreamWrapper fsdis, long fileSize, HFileSystem hfs, Path path, FixedFileTrailer trailer) throws IOException { trailer.expectMajorVersion(3); HFileContextBuilder builder = new HFileContextBuilder() .withIncludesMvcc(shouldIncludeMemstoreTS()) .withHBaseCheckSum(true) .withCompression(this.compressAlgo); // Check for any key material available byte[] keyBytes = trailer.getEncryptionKey(); if (keyBytes != null) { Encryption.Context cryptoContext = Encryption.newContext(conf); Key key; String masterKeyName = conf.get(HConstants.CRYPTO_MASTERKEY_NAME_CONF_KEY, User.getCurrent().getShortName()); try { // First try the master key key = EncryptionUtil.unwrapKey(conf, masterKeyName, keyBytes); } catch (KeyException e) { // If the current master key fails to unwrap, try the alternate, if // one is configured if (LOG.isDebugEnabled()) { LOG.debug("Unable to unwrap key with current master key '" + masterKeyName + "'"); } String alternateKeyName = conf.get(HConstants.CRYPTO_MASTERKEY_ALTERNATE_NAME_CONF_KEY); if (alternateKeyName != null) { try { key = EncryptionUtil.unwrapKey(conf, alternateKeyName, keyBytes); } catch (KeyException ex) { throw new IOException(ex); } } else { throw new IOException(e); } } // Use the algorithm the key wants Cipher cipher = Encryption.getCipher(conf, key.getAlgorithm()); if (cipher == null) { throw new IOException("Cipher '" + key.getAlgorithm() + "' is not available"); } cryptoContext.setCipher(cipher); cryptoContext.setKey(key); builder.withEncryptionContext(cryptoContext); } HFileContext context = builder.build(); if (LOG.isTraceEnabled()) { LOG.trace("Reader" + (path != null ? " for " + path : "" ) + " initialized with cacheConf: " + cacheConf + " comparator: " + comparator.getClass().getSimpleName() + " fileContext: " + context); } return context; }
@Override public Cipher getCipher(String name) { return null; }
@Override protected HFileContext createHFileContext(FSDataInputStreamWrapper fsdis, long fileSize, HFileSystem hfs, Path path, FixedFileTrailer trailer) throws IOException { trailer.expectMajorVersion(3); HFileContextBuilder builder = new HFileContextBuilder() .withIncludesMvcc(this.includesMemstoreTS) .withHBaseCheckSum(true) .withCompression(this.compressAlgo); // Check for any key material available byte[] keyBytes = trailer.getEncryptionKey(); if (keyBytes != null) { Encryption.Context cryptoContext = Encryption.newContext(conf); Key key; String masterKeyName = conf.get(HConstants.CRYPTO_MASTERKEY_NAME_CONF_KEY, User.getCurrent().getShortName()); try { // First try the master key key = EncryptionUtil.unwrapKey(conf, masterKeyName, keyBytes); } catch (KeyException e) { // If the current master key fails to unwrap, try the alternate, if // one is configured if (LOG.isDebugEnabled()) { LOG.debug("Unable to unwrap key with current master key '" + masterKeyName + "'"); } String alternateKeyName = conf.get(HConstants.CRYPTO_MASTERKEY_ALTERNATE_NAME_CONF_KEY); if (alternateKeyName != null) { try { key = EncryptionUtil.unwrapKey(conf, alternateKeyName, keyBytes); } catch (KeyException ex) { throw new IOException(ex); } } else { throw new IOException(e); } } // Use the algorithm the key wants Cipher cipher = Encryption.getCipher(conf, key.getAlgorithm()); if (cipher == null) { throw new IOException("Cipher '" + key.getAlgorithm() + "' is not available"); } cryptoContext.setCipher(cipher); cryptoContext.setKey(key); builder.withEncryptionContext(cryptoContext); } HFileContext context = builder.build(); if (LOG.isTraceEnabled()) { LOG.trace("Reader" + (path != null ? " for " + path : "" ) + " initialized with cacheConf: " + cacheConf + " comparator: " + comparator.getClass().getSimpleName() + " fileContext: " + context); } return context; }