diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/CryptoCipherProvider.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/CryptoCipherProvider.java
new file mode 100644
index 0000000..3f5cd2d
--- /dev/null
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/CryptoCipherProvider.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.hadoop.hbase.io.crypto;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.classification.InterfaceAudience;
+import org.apache.hadoop.hbase.classification.InterfaceStability;
+import org.apache.hadoop.hbase.io.crypto.aes.CommonsCryptoAES;
+
+/**
+ * The default cipher provider. Supports AES via the Commons Crypto.
+ */
+@InterfaceAudience.Public
+@InterfaceStability.Evolving
+public final class CryptoCipherProvider implements CipherProvider {
+
+ private static CryptoCipherProvider instance;
+
+ public static CryptoCipherProvider getInstance() {
+ if (instance != null) {
+ return instance;
+ }
+ instance = new CryptoCipherProvider();
+ return instance;
+ }
+
+ private Configuration conf = HBaseConfiguration.create();
+
+ // Prevent instantiation
+ private CryptoCipherProvider() { }
+
+ @Override
+ public Configuration getConf() {
+ return conf;
+ }
+
+ @Override
+ public void setConf(Configuration conf) {
+ this.conf = conf;
+ }
+
+ @Override
+ public String getName() {
+ return "commons";
+ }
+
+ @Override
+ public Cipher getCipher(String name) {
+ if (name.equalsIgnoreCase("AES")) {
+ return new CommonsCryptoAES(this);
+ }
+ throw new RuntimeException("Cipher '" + name + "' is not supported by provider '" +
+ getName() + "'");
+ }
+
+ @Override
+ public String[] getSupportedCiphers() {
+ return new String[] { "AES" };
+ }
+
+}
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/aes/CommonsCryptoAES.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/aes/CommonsCryptoAES.java
new file mode 100644
index 0000000..9d87f49
--- /dev/null
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/aes/CommonsCryptoAES.java
@@ -0,0 +1,160 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.io.crypto.aes;
+
+import com.google.common.base.Preconditions;
+import org.apache.commons.crypto.cipher.CryptoCipherFactory;
+import org.apache.commons.crypto.random.CryptoRandomFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.classification.InterfaceAudience;
+import org.apache.hadoop.hbase.classification.InterfaceStability;
+import org.apache.hadoop.hbase.io.crypto.*;
+
+import javax.crypto.spec.SecretKeySpec;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.GeneralSecurityException;
+import java.security.Key;
+import java.security.SecureRandom;
+import java.util.Properties;
+import java.util.Random;
+
+@InterfaceAudience.Private
+@InterfaceStability.Evolving
+public class CommonsCryptoAES extends Cipher {
+
+ private static final Log LOG = LogFactory.getLog(CommonsCryptoAES.class);
+
+ public static final int KEY_LENGTH = 16;
+ public static final int BLOCK_SIZE = 16;
+ public static final int IV_LENGTH = 16;
+
+ public static final String CIPHER_MODE_KEY = "hbase.crypto.commons.mode";
+ public static final String CIPHER_CLASSES_KEY = "hbase.crypto.commons.cipher.classes";
+ public static final String CIPHER_JCE_PROVIDER_KEY = "hbase.crypto.commons.cipher.jce.provider";
+
+ public static final String RNG_CLASSES_KEY = "hbase.crypto.commons.secure.random.classes";
+ public static final String RNG_JAVA_ALGORITHM_KEY = "hbase.crypto.commons.secure.random.java.algorithm";
+ public static final String RNG_DEVICE_FILE_PATH_KEY = "hbase.crypto.commons.secure.random.device.file.path";
+
+ private final String cipherMode;
+ private Random rng;
+ private Properties props;
+
+ public CommonsCryptoAES(CipherProvider provider) {
+ super(provider);
+ // The mode for Commons Crypto Ciphers
+ cipherMode = provider.getConf().get(CIPHER_MODE_KEY, "AES/CTR/NoPadding");
+ // Reads Commons Crypto properties from HBase conf
+ props = readCryptoProps(provider.getConf());
+ // RNG provider, null if default
+ try {
+ rng = (Random) CryptoRandomFactory.getCryptoRandom();
+ } catch (GeneralSecurityException e) {
+ LOG.warn("Could not instantiate specified RNG, falling back to default", e);
+ rng = new SecureRandom();
+ }
+ }
+
+ private static Properties readCryptoProps(Configuration conf) {
+ Properties props = new Properties();
+
+ props.setProperty(CryptoCipherFactory.CLASSES_KEY, conf.get(CIPHER_CLASSES_KEY));
+ props.setProperty(CryptoCipherFactory.JCE_PROVIDER_KEY, conf.get(CIPHER_JCE_PROVIDER_KEY));
+
+ props.setProperty(CryptoRandomFactory.CLASSES_KEY, conf.get(RNG_CLASSES_KEY));
+ props.setProperty(CryptoRandomFactory.JAVA_ALGORITHM_KEY, conf.get(RNG_JAVA_ALGORITHM_KEY));
+ props.setProperty(CryptoRandomFactory.DEVICE_FILE_PATH_KEY, conf.get(RNG_DEVICE_FILE_PATH_KEY));
+
+ return props;
+ }
+
+ @Override
+ public String getName() {
+ return "AES";
+ }
+
+ @Override
+ public int getKeyLength() {
+ return KEY_LENGTH;
+ }
+
+ @Override
+ public int getIvLength() {
+ return IV_LENGTH;
+ }
+
+ @Override
+ public Key getRandomKey() {
+ byte[] keyBytes = new byte[getKeyLength()];
+ rng.nextBytes(keyBytes);
+ return new SecretKeySpec(keyBytes, getName());
+ }
+
+ @Override
+ public Encryptor getEncryptor() {
+ return new CommonsCryptoAESEncryptor(cipherMode, props);
+ }
+
+ @Override
+ public Decryptor getDecryptor() {
+ return new CommonsCryptoAESDecryptor(cipherMode, props);
+ }
+
+ @Override
+ public OutputStream createEncryptionStream(OutputStream out, Context context,
+ byte[] iv) throws IOException {
+ Preconditions.checkNotNull(context);
+ Preconditions.checkState(context.getKey() != null, "Context does not have a key");
+ Preconditions.checkNotNull(iv);
+ Encryptor e = getEncryptor();
+ e.setKey(context.getKey());
+ e.setIv(iv);
+ return e.createEncryptionStream(out);
+ }
+
+ @Override
+ public OutputStream createEncryptionStream(OutputStream out,
+ Encryptor encryptor) throws
+ IOException {
+ return encryptor.createEncryptionStream(out);
+ }
+
+ @Override
+ public InputStream createDecryptionStream(InputStream in, Context context,
+ byte[] iv) throws IOException {
+ Preconditions.checkNotNull(context);
+ Preconditions.checkState(context.getKey() != null, "Context does not have a key");
+ Preconditions.checkNotNull(iv);
+ Decryptor d = getDecryptor();
+ d.setKey(context.getKey());
+ d.setIv(iv);
+ return d.createDecryptionStream(in);
+ }
+
+ @Override
+ public InputStream createDecryptionStream(InputStream in,
+ Decryptor decryptor) throws
+ IOException {
+ Preconditions.checkNotNull(decryptor);
+ return decryptor.createDecryptionStream(in);
+ }
+}
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/aes/CommonsCryptoAESDecryptor.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/aes/CommonsCryptoAESDecryptor.java
new file mode 100644
index 0000000..76f2c62
--- /dev/null
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/aes/CommonsCryptoAESDecryptor.java
@@ -0,0 +1,84 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.io.crypto.aes;
+
+import com.google.common.base.Preconditions;
+import org.apache.commons.crypto.stream.CryptoInputStream;
+import org.apache.hadoop.hbase.classification.InterfaceAudience;
+import org.apache.hadoop.hbase.classification.InterfaceStability;
+import org.apache.hadoop.hbase.io.crypto.Decryptor;
+
+import javax.crypto.spec.IvParameterSpec;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.Key;
+import java.util.Properties;
+
+@InterfaceAudience.Private
+@InterfaceStability.Evolving
+public class CommonsCryptoAESDecryptor implements Decryptor {
+
+ private String cipherMode;
+ private Properties properties;
+ private Key key;
+ private byte[] iv;
+
+ public CommonsCryptoAESDecryptor(String cipherMode, Properties properties) {
+ this.cipherMode = cipherMode;
+ this.properties = properties;
+ }
+
+ @Override
+ public void setKey(Key key) {
+ Preconditions.checkNotNull(key, "Key cannot be null");
+ this.key = key;
+ }
+
+ @Override
+ public int getIvLength() {
+ return CommonsCryptoAES.IV_LENGTH;
+ }
+
+ @Override
+ public int getBlockSize() {
+ return CommonsCryptoAES.BLOCK_SIZE;
+ }
+
+ @Override
+ public void setIv(byte[] iv) {
+ Preconditions.checkNotNull(iv, "IV cannot be null");
+ Preconditions.checkArgument(iv.length == CommonsCryptoAES.IV_LENGTH, "Invalid IV length");
+ this.iv = iv;
+ }
+
+ @Override
+ public InputStream createDecryptionStream(InputStream in) {
+ try {
+ return new CryptoInputStream(cipherMode, properties, in, key, new
+ IvParameterSpec(iv));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void reset() {
+ ;
+ }
+
+}
diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/aes/CommonsCryptoAESEncryptor.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/aes/CommonsCryptoAESEncryptor.java
new file mode 100644
index 0000000..5ce89fe
--- /dev/null
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/aes/CommonsCryptoAESEncryptor.java
@@ -0,0 +1,87 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.io.crypto.aes;
+
+import com.google.common.base.Preconditions;
+import org.apache.commons.crypto.stream.CryptoOutputStream;
+import org.apache.hadoop.hbase.classification.InterfaceAudience;
+import org.apache.hadoop.hbase.classification.InterfaceStability;
+import org.apache.hadoop.hbase.io.crypto.Encryptor;
+
+import javax.crypto.spec.IvParameterSpec;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.Key;
+import java.util.Properties;
+
+@InterfaceAudience.Private
+@InterfaceStability.Evolving
+public class CommonsCryptoAESEncryptor implements Encryptor {
+
+ private String cipherMode;
+ private Properties properties;
+ private Key key;
+ private byte[] iv;
+
+ public CommonsCryptoAESEncryptor(String cipherMode, Properties properties) {
+ this.cipherMode = cipherMode;
+ this.properties = properties;
+ }
+
+ @Override
+ public void setKey(Key key) {
+ this.key = key;
+ }
+
+ @Override
+ public int getIvLength() {
+ return CommonsCryptoAES.IV_LENGTH;
+ }
+
+ @Override
+ public int getBlockSize() {
+ return CommonsCryptoAES.BLOCK_SIZE;
+ }
+
+ @Override
+ public byte[] getIv() {
+ return iv;
+ }
+
+ @Override
+ public void setIv(byte[] iv) {
+ Preconditions.checkNotNull(iv, "IV cannot be null");
+ Preconditions.checkArgument(iv.length == CommonsCryptoAES.IV_LENGTH, "Invalid IV length");
+ this.iv = iv;
+ }
+
+ @Override
+ public OutputStream createEncryptionStream(OutputStream out) {
+ try {
+ return new CryptoOutputStream(cipherMode, properties, out, key, new
+ IvParameterSpec(iv));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void reset() {
+ ;
+ }
+}
diff --git a/pom.xml b/pom.xml
index b26c015..6f8cf91 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1179,6 +1179,7 @@
1.2
2.2
3.1
+ 1.0.0
3.3.0
3.2.2
@@ -1794,6 +1795,11 @@
log4j
log4j
+
+ org.apache.commons
+ commons-crypto
+ ${commons-crypto.version}
+
junit