http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/95a8d486/src/main/java/org/apache/commons/crypto/conf/ConfigurationKeys.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/crypto/conf/ConfigurationKeys.java 
b/src/main/java/org/apache/commons/crypto/conf/ConfigurationKeys.java
index 7bab928..c6005a5 100644
--- a/src/main/java/org/apache/commons/crypto/conf/ConfigurationKeys.java
+++ b/src/main/java/org/apache/commons/crypto/conf/ConfigurationKeys.java
@@ -25,112 +25,112 @@ import org.apache.commons.crypto.random.CryptoRandom;
  */
 public class ConfigurationKeys {
 
-  /**
-   * The prefix of crypto configuration.
-   */
-  public static final String CONF_PREFIX = "commons.crypto.";
-
-  /**
-   * The filename of configuration file.
-   */
-  public static final String COMMONS_CRYPTO_SYSTEM_PROPERTIES_FILE =
-      CONF_PREFIX + "properties";
-
-  /**
-   * The configuration key of implementation class for crypto cipher.
-   * The values of COMMONS_CRYPTO_CIPHER_CLASSES_KEY can be
-   * "org.apache.commons.crypto.cipher.JceCipher" and 
"org.apache.commons.crypto.cipher.OpensslCipher".
-   * And it takes a common separated list.
-   * The "org.apache.commons.crypto.cipher.JceCipher" use jce provider to
-   * implement CryptoCipher and
-   * the "org.apache.commons.crypto.cipher.OpensslCipher" use jni into openssl 
to implement.
-   * Note that for each value,the first value which can be created without 
exception
-   * will be used (priority by order).
-    */
-  public static final String COMMONS_CRYPTO_CIPHER_CLASSES_KEY =
-      CONF_PREFIX + "cipher.classes";
-
-  /**
-   * The default value for crypto cipher.
-   */
-  public static final String COMMONS_CRYPTO_CIPHER_CLASSES_DEFAULT =
-      OpensslCipher.class.getName();
-
-  /**
-   * The configuration key of the provider class for JCE cipher.
-   */
-  public static final String COMMONS_CRYPTO_CIPHER_JCE_PROVIDER_KEY =
-      CONF_PREFIX + "cipher.jce.provider";
-
-  // security random related configuration keys
-  /**
-   * The configuration key of the file path for secure random device.
-   */
-  public static final String COMMONS_CRYPTO_SECURE_RANDOM_DEVICE_FILE_PATH_KEY 
=
-      CONF_PREFIX + "secure.random.device.file.path";
-
-  /**
-   * The default value of the file path for secure random device.
-   */
-  public static final String 
COMMONS_CRYPTO_SECURE_RANDOM_DEVICE_FILE_PATH_DEFAULT =
-      "/dev/urandom";
-
-  /**
-   * The configuration key of the algorithm of secure random.
-   */
-  public static final String COMMONS_CRYPTO_SECURE_RANDOM_JAVA_ALGORITHM_KEY =
-      CONF_PREFIX + "secure.random.java.algorithm";
-
-  /**
-   * The default value of the algorithm of secure random.
-   */
-  public static final String
-      COMMONS_CRYPTO_SECURE_RANDOM_JAVA_ALGORITHM_DEFAULT = "SHA1PRNG";
-
-  /**
-   * The configuration key of the implementation class for secure random.
-   * The values of COMMONS_CRYPTO_SECURE_RANDOM_CLASSES_KEY can be
-   * "org.apache.commons.crypto.random.JavaCryptoRandom" and 
"org.apache.commons.crypto.random.OpensslCryptoRandom".
-   * And it takes a common separated list.
-   * The "org.apache.commons.crypto.random.JavaCryptoRandom" use java to
-   * implement {@link CryptoRandom} and
-   * the "org.apache.commons.crypto.random.OpensslCryptoRandom" use jni into 
openssl to implement.
-   * Note that for each value,the first value which can be created without 
exception
-   * will be used (priority by order).
-   */
-  public static final String COMMONS_CRYPTO_SECURE_RANDOM_CLASSES_KEY =
-      CONF_PREFIX + "secure.random.classes";
-
-  /**
-   * The configuration key of the buffer size for stream.
-   */
-  public static final String COMMONS_CRYPTO_STREAM_BUFFER_SIZE_KEY =
-      CONF_PREFIX + "stream.buffer.size";
-
-  // stream related configuration keys
-  /**
-   * The default value of the buffer size for stream.
-   */
-  public static final int COMMONS_CRYPTO_STREAM_BUFFER_SIZE_DEFAULT = 8192;
-
-  // native lib related configuration keys
-  /**
-   * The configuration key of the path for loading crypto library.
-   */
-  public static final String COMMONS_CRYPTO_LIB_PATH_KEY =
-      CONF_PREFIX + "lib.path";
-
-  /**
-   * The configuration key of the file name for loading crypto library.
-   */
-  public static final String COMMONS_CRYPTO_LIB_NAME_KEY =
-      CONF_PREFIX + "lib.name";
-
-  /**
-   * The configuration key of temp directory for extracting crypto library.
-   */
-  public static final String COMMONS_CRYPTO_LIB_TEMPDIR_KEY =
-      CONF_PREFIX + "lib.tempdir";
-
-  private ConfigurationKeys() {}
+    /**
+     * The prefix of crypto configuration.
+     */
+    public static final String CONF_PREFIX = "commons.crypto.";
+
+    /**
+     * The filename of configuration file.
+     */
+    public static final String COMMONS_CRYPTO_SYSTEM_PROPERTIES_FILE = 
CONF_PREFIX
+            + "properties";
+
+    /**
+     * The configuration key of implementation class for crypto cipher. The
+     * values of COMMONS_CRYPTO_CIPHER_CLASSES_KEY can be
+     * "org.apache.commons.crypto.cipher.JceCipher" and
+     * "org.apache.commons.crypto.cipher.OpensslCipher". And it takes a common
+     * separated list. The "org.apache.commons.crypto.cipher.JceCipher" use jce
+     * provider to implement CryptoCipher and the
+     * "org.apache.commons.crypto.cipher.OpensslCipher" use jni into openssl to
+     * implement. Note that for each value,the first value which can be created
+     * without exception will be used (priority by order).
+     */
+    public static final String COMMONS_CRYPTO_CIPHER_CLASSES_KEY = CONF_PREFIX
+            + "cipher.classes";
+
+    /**
+     * The default value for crypto cipher.
+     */
+    public static final String COMMONS_CRYPTO_CIPHER_CLASSES_DEFAULT = 
OpensslCipher.class
+            .getName();
+
+    /**
+     * The configuration key of the provider class for JCE cipher.
+     */
+    public static final String COMMONS_CRYPTO_CIPHER_JCE_PROVIDER_KEY = 
CONF_PREFIX
+            + "cipher.jce.provider";
+
+    // security random related configuration keys
+    /**
+     * The configuration key of the file path for secure random device.
+     */
+    public static final String 
COMMONS_CRYPTO_SECURE_RANDOM_DEVICE_FILE_PATH_KEY = CONF_PREFIX
+            + "secure.random.device.file.path";
+
+    /**
+     * The default value of the file path for secure random device.
+     */
+    public static final String 
COMMONS_CRYPTO_SECURE_RANDOM_DEVICE_FILE_PATH_DEFAULT = "/dev/urandom";
+
+    /**
+     * The configuration key of the algorithm of secure random.
+     */
+    public static final String COMMONS_CRYPTO_SECURE_RANDOM_JAVA_ALGORITHM_KEY 
= CONF_PREFIX
+            + "secure.random.java.algorithm";
+
+    /**
+     * The default value of the algorithm of secure random.
+     */
+    public static final String 
COMMONS_CRYPTO_SECURE_RANDOM_JAVA_ALGORITHM_DEFAULT = "SHA1PRNG";
+
+    /**
+     * The configuration key of the implementation class for secure random. The
+     * values of COMMONS_CRYPTO_SECURE_RANDOM_CLASSES_KEY can be
+     * "org.apache.commons.crypto.random.JavaCryptoRandom" and
+     * "org.apache.commons.crypto.random.OpensslCryptoRandom". And it takes a
+     * common separated list. The
+     * "org.apache.commons.crypto.random.JavaCryptoRandom" use java to 
implement
+     * {@link CryptoRandom} and the
+     * "org.apache.commons.crypto.random.OpensslCryptoRandom" use jni into
+     * openssl to implement. Note that for each value,the first value which can
+     * be created without exception will be used (priority by order).
+     */
+    public static final String COMMONS_CRYPTO_SECURE_RANDOM_CLASSES_KEY = 
CONF_PREFIX
+            + "secure.random.classes";
+
+    /**
+     * The configuration key of the buffer size for stream.
+     */
+    public static final String COMMONS_CRYPTO_STREAM_BUFFER_SIZE_KEY = 
CONF_PREFIX
+            + "stream.buffer.size";
+
+    // stream related configuration keys
+    /**
+     * The default value of the buffer size for stream.
+     */
+    public static final int COMMONS_CRYPTO_STREAM_BUFFER_SIZE_DEFAULT = 8192;
+
+    // native lib related configuration keys
+    /**
+     * The configuration key of the path for loading crypto library.
+     */
+    public static final String COMMONS_CRYPTO_LIB_PATH_KEY = CONF_PREFIX
+            + "lib.path";
+
+    /**
+     * The configuration key of the file name for loading crypto library.
+     */
+    public static final String COMMONS_CRYPTO_LIB_NAME_KEY = CONF_PREFIX
+            + "lib.name";
+
+    /**
+     * The configuration key of temp directory for extracting crypto library.
+     */
+    public static final String COMMONS_CRYPTO_LIB_TEMPDIR_KEY = CONF_PREFIX
+            + "lib.tempdir";
+
+    private ConfigurationKeys() {
+    }
 }

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/95a8d486/src/main/java/org/apache/commons/crypto/conf/package-info.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/crypto/conf/package-info.java 
b/src/main/java/org/apache/commons/crypto/conf/package-info.java
index 837b195..6e340a9 100644
--- a/src/main/java/org/apache/commons/crypto/conf/package-info.java
+++ b/src/main/java/org/apache/commons/crypto/conf/package-info.java
@@ -19,3 +19,4 @@
  * Configuration classes
  */
 package org.apache.commons.crypto.conf;
+

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/95a8d486/src/main/java/org/apache/commons/crypto/random/CryptoRandom.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/crypto/random/CryptoRandom.java 
b/src/main/java/org/apache/commons/crypto/random/CryptoRandom.java
index 8194a9b..6c8c983 100644
--- a/src/main/java/org/apache/commons/crypto/random/CryptoRandom.java
+++ b/src/main/java/org/apache/commons/crypto/random/CryptoRandom.java
@@ -24,13 +24,13 @@ import java.io.Closeable;
  */
 public interface CryptoRandom extends Closeable {
 
-  /**
-   * Generates random bytes and places them into a user-supplied
-   * byte array.  The number of random bytes produced is equal to
-   * the length of the byte array.
-   *
-   * @param bytes the byte array to fill with random bytes
-   */
-  void nextBytes(byte[] bytes);
+    /**
+     * Generates random bytes and places them into a user-supplied byte array.
+     * The number of random bytes produced is equal to the length of the byte
+     * array.
+     *
+     * @param bytes the byte array to fill with random bytes
+     */
+    void nextBytes(byte[] bytes);
 
 }

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/95a8d486/src/main/java/org/apache/commons/crypto/random/CryptoRandomFactory.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/crypto/random/CryptoRandomFactory.java 
b/src/main/java/org/apache/commons/crypto/random/CryptoRandomFactory.java
index 8c9fd35..df57cd8 100644
--- a/src/main/java/org/apache/commons/crypto/random/CryptoRandomFactory.java
+++ b/src/main/java/org/apache/commons/crypto/random/CryptoRandomFactory.java
@@ -26,51 +26,56 @@ import org.slf4j.LoggerFactory;
 import org.apache.commons.crypto.utils.Utils;
 import org.apache.commons.crypto.utils.ReflectionUtils;
 
-import static org.apache.commons.crypto.conf.ConfigurationKeys
-    .COMMONS_CRYPTO_SECURE_RANDOM_CLASSES_KEY;
+import static 
org.apache.commons.crypto.conf.ConfigurationKeys.COMMONS_CRYPTO_SECURE_RANDOM_CLASSES_KEY;
 
 /**
  * This is the factory class used for {@link CryptoRandom}.
  */
 public class CryptoRandomFactory {
-  public final static Logger LOG = LoggerFactory
-      .getLogger(CryptoRandomFactory.class);
+    public final static Logger LOG = LoggerFactory
+            .getLogger(CryptoRandomFactory.class);
 
-  private CryptoRandomFactory() {}
-
-  /**
-   * Gets a CryptoRandom instance for specified props.
-   *
-   * @param props the configuration properties.
-   * @return CryptoRandom the cryptoRandom object.Null value will be returned 
if no CryptoRandom
-   *         classes with props.
-   * @throws GeneralSecurityException if fail to create the {@link 
CryptoRandom}.
-   */
-  public static CryptoRandom getCryptoRandom(Properties props) throws 
GeneralSecurityException {
-    String cryptoRandomClasses = props.getProperty(
-        COMMONS_CRYPTO_SECURE_RANDOM_CLASSES_KEY);
-    if (cryptoRandomClasses == null) {
-      cryptoRandomClasses = System.getProperty(
-          COMMONS_CRYPTO_SECURE_RANDOM_CLASSES_KEY);
+    private CryptoRandomFactory() {
     }
 
-    CryptoRandom random = null;
-    if (cryptoRandomClasses != null) {
-      for (String klassName : Utils.splitClassNames(cryptoRandomClasses, ",")) 
{
-        try {
-          final Class<?> klass = ReflectionUtils.getClassByName(klassName);
-          random = (CryptoRandom) ReflectionUtils.newInstance(klass, props);
-          if (random != null) {
-            break;
-          }
-        } catch (ClassCastException e) {
-          LOG.error("Class {} is not a CryptoCipher.", klassName);
-        } catch (ClassNotFoundException e) {
-          LOG.error("CryptoCipher {} not found.", klassName);
+    /**
+     * Gets a CryptoRandom instance for specified props.
+     *
+     * @param props the configuration properties.
+     * @return CryptoRandom the cryptoRandom object.Null value will be returned
+     *         if no CryptoRandom classes with props.
+     * @throws GeneralSecurityException if fail to create the
+     *         {@link CryptoRandom}.
+     */
+    public static CryptoRandom getCryptoRandom(Properties props)
+            throws GeneralSecurityException {
+        String cryptoRandomClasses = props
+                .getProperty(COMMONS_CRYPTO_SECURE_RANDOM_CLASSES_KEY);
+        if (cryptoRandomClasses == null) {
+            cryptoRandomClasses = System
+                    .getProperty(COMMONS_CRYPTO_SECURE_RANDOM_CLASSES_KEY);
         }
-      }
-    }
 
-    return (random == null) ? new JavaCryptoRandom(props) : random;
-  }
+        CryptoRandom random = null;
+        if (cryptoRandomClasses != null) {
+            for (String klassName : Utils.splitClassNames(cryptoRandomClasses,
+                    ",")) {
+                try {
+                    final Class<?> klass = ReflectionUtils
+                            .getClassByName(klassName);
+                    random = (CryptoRandom) ReflectionUtils.newInstance(klass,
+                            props);
+                    if (random != null) {
+                        break;
+                    }
+                } catch (ClassCastException e) {
+                    LOG.error("Class {} is not a CryptoCipher.", klassName);
+                } catch (ClassNotFoundException e) {
+                    LOG.error("CryptoCipher {} not found.", klassName);
+                }
+            }
+        }
+
+        return (random == null) ? new JavaCryptoRandom(props) : random;
+    }
 }

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/95a8d486/src/main/java/org/apache/commons/crypto/random/JavaCryptoRandom.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/crypto/random/JavaCryptoRandom.java 
b/src/main/java/org/apache/commons/crypto/random/JavaCryptoRandom.java
index ac0ab3e..69fbf98 100644
--- a/src/main/java/org/apache/commons/crypto/random/JavaCryptoRandom.java
+++ b/src/main/java/org/apache/commons/crypto/random/JavaCryptoRandom.java
@@ -30,42 +30,45 @@ import org.apache.commons.crypto.conf.ConfigurationKeys;
  * A CryptoRandom of Java implementation.
  */
 public class JavaCryptoRandom implements CryptoRandom {
-  private static final Log LOG =
-      LogFactory.getLog(JavaCryptoRandom.class.getName());
+    private static final Log LOG = LogFactory.getLog(JavaCryptoRandom.class
+            .getName());
 
-  private final SecureRandom instance;
+    private final SecureRandom instance;
 
-  /**
-   * Constructs a {@link JavaCryptoRandom}.
-   *
-   * @param properties the configuration properties.
-   * @throws NoSuchAlgorithmException if no Provider supports a 
SecureRandomSpi implementation for
-   *         the specified algorithm.
-   */
-  public JavaCryptoRandom(Properties properties) throws 
NoSuchAlgorithmException {
-    instance = SecureRandom.getInstance(properties
-      
.getProperty(ConfigurationKeys.COMMONS_CRYPTO_SECURE_RANDOM_JAVA_ALGORITHM_KEY,
-        
ConfigurationKeys.COMMONS_CRYPTO_SECURE_RANDOM_JAVA_ALGORITHM_DEFAULT));
-  }
+    /**
+     * Constructs a {@link JavaCryptoRandom}.
+     *
+     * @param properties the configuration properties.
+     * @throws NoSuchAlgorithmException if no Provider supports a
+     *         SecureRandomSpi implementation for the specified algorithm.
+     */
+    public JavaCryptoRandom(Properties properties)
+            throws NoSuchAlgorithmException {
+        instance = SecureRandom
+                .getInstance(properties
+                        .getProperty(
+                                
ConfigurationKeys.COMMONS_CRYPTO_SECURE_RANDOM_JAVA_ALGORITHM_KEY,
+                                
ConfigurationKeys.COMMONS_CRYPTO_SECURE_RANDOM_JAVA_ALGORITHM_DEFAULT));
+    }
 
-  /**
-   * Overrides {@link java.lang.AutoCloseable#close()}.
-   * For{@link JavaCryptoRandom}, we don't need to recycle resource.
-   */
-  @Override
-  public void close() {
-    // do nothing
-  }
+    /**
+     * Overrides {@link java.lang.AutoCloseable#close()}. For
+     * {@link JavaCryptoRandom}, we don't need to recycle resource.
+     */
+    @Override
+    public void close() {
+        // do nothing
+    }
 
-  /**
-   * Overrides {@link CryptoRandom#nextBytes(byte[])}.
-   * Generates random bytes and places them into a user-supplied byte array.
-   * The number of random bytes produced is equal to the length of the byte 
array.
-   *
-   * @param bytes the array to be filled in with random bytes.
-   */
-  @Override
-  public void nextBytes(byte[] bytes) {
-    instance.nextBytes(bytes);
-  }
+    /**
+     * Overrides {@link CryptoRandom#nextBytes(byte[])}. Generates random bytes
+     * and places them into a user-supplied byte array. The number of random
+     * bytes produced is equal to the length of the byte array.
+     *
+     * @param bytes the array to be filled in with random bytes.
+     */
+    @Override
+    public void nextBytes(byte[] bytes) {
+        instance.nextBytes(bytes);
+    }
 }

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/95a8d486/src/main/java/org/apache/commons/crypto/random/OpensslCryptoRandom.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/crypto/random/OpensslCryptoRandom.java 
b/src/main/java/org/apache/commons/crypto/random/OpensslCryptoRandom.java
index 315e259..3adb9b6 100644
--- a/src/main/java/org/apache/commons/crypto/random/OpensslCryptoRandom.java
+++ b/src/main/java/org/apache/commons/crypto/random/OpensslCryptoRandom.java
@@ -33,118 +33,120 @@ import org.apache.commons.crypto.utils.Utils;
  * </p>
  *
  * <p>
- * If using an Intel chipset with RDRAND, the high-performance hardware
- * random number generator will be used and it's much faster than
- * SecureRandom. If RDRAND is unavailable, default OpenSSL secure random
- * generator will be used. It's still faster and can generate strong random 
bytes.
+ * If using an Intel chipset with RDRAND, the high-performance hardware random
+ * number generator will be used and it's much faster than SecureRandom. If
+ * RDRAND is unavailable, default OpenSSL secure random generator will be used.
+ * It's still faster and can generate strong random bytes.
  * </p>
+ *
  * @see <a href="https://wiki.openssl.org/index.php/Random_Numbers";>
  *      https://wiki.openssl.org/index.php/Random_Numbers</a>
  * @see <a href="http://en.wikipedia.org/wiki/RdRand";>
  *      http://en.wikipedia.org/wiki/RdRand</a>
  */
 public class OpensslCryptoRandom extends Random implements CryptoRandom {
-  private static final long serialVersionUID = -7828193502768789584L;
-  private static final Log LOG =
-      LogFactory.getLog(OpensslCryptoRandom.class.getName());
+    private static final long serialVersionUID = -7828193502768789584L;
+    private static final Log LOG = LogFactory.getLog(OpensslCryptoRandom.class
+            .getName());
 
-  /** If native SecureRandom unavailable, use java SecureRandom */
-  private final JavaCryptoRandom fallback;
-  private static final boolean nativeEnabled;
+    /** If native SecureRandom unavailable, use java SecureRandom */
+    private final JavaCryptoRandom fallback;
+    private static final boolean nativeEnabled;
 
-  static {
-    boolean opensslLoaded = false;
-    if (NativeCodeLoader.isNativeCodeLoaded()) {
-      try {
-        OpensslCryptoRandomNative.initSR();
-        opensslLoaded = true;
-      } catch (Throwable t) {
-        LOG.error("Failed to load Openssl CryptoRandom", t);
-      }
+    static {
+        boolean opensslLoaded = false;
+        if (NativeCodeLoader.isNativeCodeLoaded()) {
+            try {
+                OpensslCryptoRandomNative.initSR();
+                opensslLoaded = true;
+            } catch (Throwable t) {
+                LOG.error("Failed to load Openssl CryptoRandom", t);
+            }
+        }
+        nativeEnabled = opensslLoaded;
     }
-    nativeEnabled = opensslLoaded;
-  }
 
-  /**
-   * Judges whether loading native library successfully.
-   *
-   * @return true if loading library successfully.
-   */
-  public static boolean isNativeCodeLoaded() {
-    return nativeEnabled;
-  }
+    /**
+     * Judges whether loading native library successfully.
+     *
+     * @return true if loading library successfully.
+     */
+    public static boolean isNativeCodeLoaded() {
+        return nativeEnabled;
+    }
 
-  /**
-   * Constructs a {@link OpensslCryptoRandom}.
-   *
-   * @param props the configuration properties.
-   * @throws NoSuchAlgorithmException if no Provider supports a 
SecureRandomSpi implementation for
-   *         the specified algorithm.
-   */
-  public OpensslCryptoRandom(Properties props) throws NoSuchAlgorithmException 
{
-    if (!nativeEnabled) {
-      fallback = new JavaCryptoRandom(props);
-    } else {
-      fallback = null;
+    /**
+     * Constructs a {@link OpensslCryptoRandom}.
+     *
+     * @param props the configuration properties.
+     * @throws NoSuchAlgorithmException if no Provider supports a
+     *         SecureRandomSpi implementation for the specified algorithm.
+     */
+    public OpensslCryptoRandom(Properties props)
+            throws NoSuchAlgorithmException {
+        if (!nativeEnabled) {
+            fallback = new JavaCryptoRandom(props);
+        } else {
+            fallback = null;
+        }
     }
-  }
 
-  /**
-   * Generates a user-specified number of random bytes.
-   * It's thread-safe.
-   *
-   * @param bytes the array to be filled in with random bytes.
-   */
-  @Override
-  public void nextBytes(byte[] bytes) {
-    if (!nativeEnabled || !OpensslCryptoRandomNative.nextRandBytes(bytes)) {
-      fallback.nextBytes(bytes);
+    /**
+     * Generates a user-specified number of random bytes. It's thread-safe.
+     *
+     * @param bytes the array to be filled in with random bytes.
+     */
+    @Override
+    public void nextBytes(byte[] bytes) {
+        if (!nativeEnabled || !OpensslCryptoRandomNative.nextRandBytes(bytes)) 
{
+            fallback.nextBytes(bytes);
+        }
     }
-  }
 
-  /**
-   * Overrides {@link OpensslCryptoRandom}.
-   * For {@link OpensslCryptoRandom}, we don't need to set seed.
-   *
-   * @param seed the initial seed.
-   */
-  @Override
-  public void setSeed(long seed) {
-    // Self-seeding.
-  }
+    /**
+     * Overrides {@link OpensslCryptoRandom}. For {@link OpensslCryptoRandom},
+     * we don't need to set seed.
+     *
+     * @param seed the initial seed.
+     */
+    @Override
+    public void setSeed(long seed) {
+        // Self-seeding.
+    }
 
-  /**
-   * Overrides Random#next(). Generates an integer containing the
-   * user-specified number of random bits(right justified, with leading
-   * zeros).
-   *
-   * @param numBits number of random bits to be generated, where 0
-   *        {@literal <=} <code>numBits</code> {@literal <=} 32.
-   * @return int an <code>int</code> containing the user-specified number of
-   *         random bits (right justified, with leading zeros).
-   */
-  @Override
-  final protected int next(int numBits) {
-    Utils.checkArgument(numBits >= 0 && numBits <= 32);
-    int numBytes = (numBits + 7) / 8;
-    byte b[] = new byte[numBytes];
-    int next = 0;
+    /**
+     * Overrides Random#next(). Generates an integer containing the
+     * user-specified number of random bits(right justified, with leading
+     * zeros).
+     *
+     * @param numBits number of random bits to be generated, where 0
+     *        {@literal <=} <code>numBits</code> {@literal <=} 32.
+     * @return int an <code>int</code> containing the user-specified number of
+     *         random bits (right justified, with leading zeros).
+     */
+    @Override
+    final protected int next(int numBits) {
+        Utils.checkArgument(numBits >= 0 && numBits <= 32);
+        int numBytes = (numBits + 7) / 8;
+        byte b[] = new byte[numBytes];
+        int next = 0;
 
-    nextBytes(b);
-    for (int i = 0; i < numBytes; i++) {
-      next = (next << 8) + (b[i] & 0xFF);
-    }
+        nextBytes(b);
+        for (int i = 0; i < numBytes; i++) {
+            next = (next << 8) + (b[i] & 0xFF);
+        }
 
-    return next >>> (numBytes * 8 - numBits);
-  }
+        return next >>> (numBytes * 8 - numBits);
+    }
 
-  /**
-   * Overrides {@link java.lang.AutoCloseable#close()}. Closes openssl context 
if native enabled.
-   */
-  @Override
-  public void close() {
-    if (!nativeEnabled && fallback !=null) {
-      fallback.close();
+    /**
+     * Overrides {@link java.lang.AutoCloseable#close()}. Closes openssl 
context
+     * if native enabled.
+     */
+    @Override
+    public void close() {
+        if (!nativeEnabled && fallback != null) {
+            fallback.close();
+        }
     }
-  }
 }

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/95a8d486/src/main/java/org/apache/commons/crypto/random/OpensslCryptoRandomNative.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/crypto/random/OpensslCryptoRandomNative.java 
b/src/main/java/org/apache/commons/crypto/random/OpensslCryptoRandomNative.java
index 8b4a0a1..65078c3 100644
--- 
a/src/main/java/org/apache/commons/crypto/random/OpensslCryptoRandomNative.java
+++ 
b/src/main/java/org/apache/commons/crypto/random/OpensslCryptoRandomNative.java
@@ -18,26 +18,26 @@
 package org.apache.commons.crypto.random;
 
 /**
- * JNI interface of {@link CryptoRandom} implementation.
- * The native method in this class is defined in
- * OpensslCryptoRandomNative.h(genereted by javah).
+ * JNI interface of {@link CryptoRandom} implementation. The native method in
+ * this class is defined in OpensslCryptoRandomNative.h(genereted by javah).
  */
 public class OpensslCryptoRandomNative {
 
-  private OpensslCryptoRandomNative() {}
+    private OpensslCryptoRandomNative() {
+    }
 
-  /**
-   * Declares a native method to initialize SR.
-   */
-  public native static void initSR();
+    /**
+     * Declares a native method to initialize SR.
+     */
+    public native static void initSR();
 
-  /**
-   * Judges whether use {@link OpensslCryptoRandomNative} to
-   * generate the user-specified number of random bits.
-   *
-   * @param bytes the array to be filled in with random bytes.
-   * @return true if use {@link OpensslCryptoRandomNative} to
-   * generate the user-specified number of random bits.
-   */
-  public native static boolean nextRandBytes(byte[] bytes);
+    /**
+     * Judges whether use {@link OpensslCryptoRandomNative} to generate the
+     * user-specified number of random bits.
+     *
+     * @param bytes the array to be filled in with random bytes.
+     * @return true if use {@link OpensslCryptoRandomNative} to generate the
+     *         user-specified number of random bits.
+     */
+    public native static boolean nextRandBytes(byte[] bytes);
 }

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/95a8d486/src/main/java/org/apache/commons/crypto/random/OsCryptoRandom.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/crypto/random/OsCryptoRandom.java 
b/src/main/java/org/apache/commons/crypto/random/OsCryptoRandom.java
index 7c8bc07..eca62d2 100644
--- a/src/main/java/org/apache/commons/crypto/random/OsCryptoRandom.java
+++ b/src/main/java/org/apache/commons/crypto/random/OsCryptoRandom.java
@@ -29,105 +29,105 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 /**
- * A Random implementation that uses random bytes sourced from the
- * operating system.
+ * A Random implementation that uses random bytes sourced from the operating
+ * system.
  */
 public class OsCryptoRandom extends Random implements CryptoRandom {
-  public static final Log LOG = LogFactory.getLog(OsCryptoRandom.class);
+    public static final Log LOG = LogFactory.getLog(OsCryptoRandom.class);
 
-  private static final long serialVersionUID = 6391500337172057900L;
+    private static final long serialVersionUID = 6391500337172057900L;
 
-  private final int RESERVOIR_LENGTH = 8192;
+    private final int RESERVOIR_LENGTH = 8192;
 
-  private String randomDevPath;
+    private String randomDevPath;
 
-  private transient FileInputStream stream;
+    private transient FileInputStream stream;
 
-  private final byte[] reservoir = new byte[RESERVOIR_LENGTH];
+    private final byte[] reservoir = new byte[RESERVOIR_LENGTH];
 
-  private int pos = reservoir.length;
+    private int pos = reservoir.length;
 
-  private void fillReservoir(int min) {
-    if (pos >= reservoir.length - min) {
-      try {
-        IOUtils.readFully(stream, reservoir, 0, reservoir.length);
-      } catch (IOException e) {
-        throw new RuntimeException("failed to fill reservoir", e);
-      }
-      pos = 0;
-    }
-  }
-
-  /**
-   * Constructs a {@link OsCryptoRandom}.
-   *
-   * @param props the configuration properties.
-   */
-  public OsCryptoRandom(Properties props) {
-    randomDevPath = Utils.getRandomDevPath(props);
-    File randomDevFile = new File(randomDevPath);
-
-    try {
-      close();
-      this.stream = new FileInputStream(randomDevFile);
-    } catch (IOException e) {
-      throw new RuntimeException(e);
+    private void fillReservoir(int min) {
+        if (pos >= reservoir.length - min) {
+            try {
+                IOUtils.readFully(stream, reservoir, 0, reservoir.length);
+            } catch (IOException e) {
+                throw new RuntimeException("failed to fill reservoir", e);
+            }
+            pos = 0;
+        }
     }
 
-    try {
-      fillReservoir(0);
-    } catch (RuntimeException e) {
-      close();
-      throw e;
+    /**
+     * Constructs a {@link OsCryptoRandom}.
+     *
+     * @param props the configuration properties.
+     */
+    public OsCryptoRandom(Properties props) {
+        randomDevPath = Utils.getRandomDevPath(props);
+        File randomDevFile = new File(randomDevPath);
+
+        try {
+            close();
+            this.stream = new FileInputStream(randomDevFile);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+        try {
+            fillReservoir(0);
+        } catch (RuntimeException e) {
+            close();
+            throw e;
+        }
     }
-  }
-
-  /**
-   * Overrides {@link CryptoRandom#nextBytes(byte[])}.
-   * Generates random bytes and places them into a user-supplied byte array.
-   * The number of random bytes produced is equal to the length of the byte 
array.
-   *
-   * @param bytes the array to be filled in with random bytes.
-   */
-  @Override
-  synchronized public void nextBytes(byte[] bytes) {
-    int off = 0;
-    int n = 0;
-    while (off < bytes.length) {
-      fillReservoir(0);
-      n = Math.min(bytes.length - off, reservoir.length - pos);
-      System.arraycopy(reservoir, pos, bytes, off, n);
-      off += n;
-      pos += n;
+
+    /**
+     * Overrides {@link CryptoRandom#nextBytes(byte[])}. Generates random bytes
+     * and places them into a user-supplied byte array. The number of random
+     * bytes produced is equal to the length of the byte array.
+     *
+     * @param bytes the array to be filled in with random bytes.
+     */
+    @Override
+    synchronized public void nextBytes(byte[] bytes) {
+        int off = 0;
+        int n = 0;
+        while (off < bytes.length) {
+            fillReservoir(0);
+            n = Math.min(bytes.length - off, reservoir.length - pos);
+            System.arraycopy(reservoir, pos, bytes, off, n);
+            off += n;
+            pos += n;
+        }
     }
-  }
-
-  /**
-   * Overrides Random#next(). Generates the next pseudorandom number.
-   * Subclasses should override this, as this is used by all other methods.
-   *
-   * @param  nbits random bits.
-   * @return the next pseudorandom value from this random number
-   *         generator's sequence.
-   */
-  @Override
-  synchronized protected int next(int nbits) {
-    fillReservoir(4);
-    int n = 0;
-    for (int i = 0; i < 4; i++) {
-      n = ((n << 8) | (reservoir[pos++] & 0xff));
+
+    /**
+     * Overrides Random#next(). Generates the next pseudorandom number.
+     * Subclasses should override this, as this is used by all other methods.
+     *
+     * @param nbits random bits.
+     * @return the next pseudorandom value from this random number generator's
+     *         sequence.
+     */
+    @Override
+    synchronized protected int next(int nbits) {
+        fillReservoir(4);
+        int n = 0;
+        for (int i = 0; i < 4; i++) {
+            n = ((n << 8) | (reservoir[pos++] & 0xff));
+        }
+        return n & (0xffffffff >> (32 - nbits));
     }
-    return n & (0xffffffff >> (32 - nbits));
-  }
-
-  /**
-   * Overrides {@link java.lang.AutoCloseable#close()}. Closes the OS stream.
-   */
-  @Override
-  synchronized public void close() {
-    if (stream != null) {
-      IOUtils.cleanup(LOG, stream);
-      stream = null;
+
+    /**
+     * Overrides {@link java.lang.AutoCloseable#close()}. Closes the OS stream.
+     */
+    @Override
+    synchronized public void close() {
+        if (stream != null) {
+            IOUtils.cleanup(LOG, stream);
+            stream = null;
+        }
     }
-  }
 }

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/95a8d486/src/main/java/org/apache/commons/crypto/random/package-info.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/crypto/random/package-info.java 
b/src/main/java/org/apache/commons/crypto/random/package-info.java
index f8fd4de..9e392a7 100644
--- a/src/main/java/org/apache/commons/crypto/random/package-info.java
+++ b/src/main/java/org/apache/commons/crypto/random/package-info.java
@@ -19,3 +19,4 @@
  * Random classes
  */
 package org.apache.commons.crypto.random;
+

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/95a8d486/src/main/java/org/apache/commons/crypto/stream/CTRCryptoInputStream.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/crypto/stream/CTRCryptoInputStream.java 
b/src/main/java/org/apache/commons/crypto/stream/CTRCryptoInputStream.java
index 481b0d6..b357000 100644
--- a/src/main/java/org/apache/commons/crypto/stream/CTRCryptoInputStream.java
+++ b/src/main/java/org/apache/commons/crypto/stream/CTRCryptoInputStream.java
@@ -41,588 +41,581 @@ import org.apache.commons.crypto.utils.Utils;
  * <p>
  * CTRCryptoInputStream decrypts data. AES CTR mode is required in order to
  * ensure that the plain text and cipher text have a 1:1 mapping. CTR crypto
- * stream has stream characteristic which is useful for implement features
- * like random seek. The decryption is buffer based. The key points of the
- * decryption are (1) calculating the counter and (2) padding through stream
- * position:
+ * stream has stream characteristic which is useful for implement features like
+ * random seek. The decryption is buffer based. The key points of the 
decryption
+ * are (1) calculating the counter and (2) padding through stream position:
  * </p>
  * <p>
- * counter = base + pos/(algorithm blocksize);
- * padding = pos%(algorithm blocksize);
+ * counter = base + pos/(algorithm blocksize); padding = pos%(algorithm
+ * blocksize);
  * </p>
  * The underlying stream offset is maintained as state. It is not thread-safe.
  */
 public class CTRCryptoInputStream extends CryptoInputStream {
-  /**
-   * Underlying stream offset
-   */
-  long streamOffset = 0;
-
-  /**
-   * The initial IV.
-   */
-  protected final byte[] initIV;
-
-  /**
-   * Initialization vector for the cipher.
-   */
-  protected byte[] iv;
-
-  /**
-   * Padding = pos%(algorithm blocksize); Padding is put into {@link #inBuffer}
-   * before any other data goes in. The purpose of padding is to put the input
-   * data at proper position.
-   */
-  private byte padding;
-
-  /**
-   * Flag to mark whether the cipher has been reset
-   */
-  private boolean cipherReset = false;
-
-  /**
-   * Constructs a {@link CTRCryptoInputStream}.
-   *
-   * @param props The <code>Properties</code> class represents a set of
-   *              properties.
-   * @param in the input stream.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoInputStream(Properties props, InputStream in,
-                              byte[] key, byte[] iv)
-      throws IOException {
-    this(props, in, key, iv, 0);
-  }
-
-  /**
-   * Constructs a {@link CTRCryptoInputStream}.
-   *
-   * @param props The <code>Properties</code> class represents a set of
-   *              properties.
-   * @param in the ReadableByteChannel instance.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoInputStream(Properties props, ReadableByteChannel in,
-                              byte[] key, byte[] iv)
-      throws IOException {
-    this(props, in, key, iv, 0);
-  }
-
-  /**
-   * Constructs a {@link CTRCryptoInputStream}.
-   *
-   * @param in the input stream.
-   * @param cipher the CryptoCipher instance.
-   * @param bufferSize the bufferSize.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoInputStream(InputStream in, CryptoCipher cipher, int 
bufferSize,
-                              byte[] key, byte[] iv) throws IOException {
-    this(in, cipher, bufferSize, key, iv, 0);
-  }
-
-  /**
-   * Constructs a {@link CTRCryptoInputStream}.
-   *
-   * @param in the ReadableByteChannel instance.
-   * @param cipher the cipher instance.
-   * @param bufferSize the bufferSize.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoInputStream(ReadableByteChannel in, CryptoCipher cipher,
-                              int bufferSize, byte[] key, byte[] iv) throws 
IOException {
-    this(in, cipher, bufferSize, key, iv, 0);
-  }
-
-  /**
-   * Constructs a {@link CTRCryptoInputStream}.
-   *
-   * @param input the input data.
-   * @param cipher the CryptoCipher instance.
-   * @param bufferSize the bufferSize.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoInputStream(
-      Input input,
-      CryptoCipher cipher,
-      int bufferSize,
-      byte[] key,
-      byte[] iv) throws IOException {
-    this(input, cipher, bufferSize, key, iv, 0);
-  }
-
-  /**
-   * Constructs a {@link CTRCryptoInputStream}.
-   *
-   * @param props The <code>Properties</code> class represents a set of
-   *              properties.
-   * @param in the InputStream instance.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @param streamOffset the start offset in the stream.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoInputStream(Properties props, InputStream in,
-                              byte[] key, byte[] iv, long streamOffset)
-      throws IOException {
-    this(in, Utils.getCipherInstance(CipherTransformation.AES_CTR_NOPADDING, 
props),
-        Utils.getBufferSize(props), key, iv, streamOffset);
-  }
-
-  /**
-   *Constructs a {@link CTRCryptoInputStream}.
-   *
-   * @param props The <code>Properties</code> class represents a set of
-   *              properties.
-   * @param in the ReadableByteChannel instance.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @param streamOffset the start offset in the stream.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoInputStream(Properties props, ReadableByteChannel in,
-                              byte[] key, byte[] iv, long streamOffset)
-      throws IOException {
-    this(in, Utils.getCipherInstance(CipherTransformation.AES_CTR_NOPADDING, 
props),
-        Utils.getBufferSize(props), key, iv, streamOffset);
-  }
-
-  /**
-   * Constructs a {@link CTRCryptoInputStream}.
-   *
-   * @param in the InputStream instance.
-   * @param cipher the CryptoCipher instance.
-   * @param bufferSize the bufferSize.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @param streamOffset the start offset in the stream.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoInputStream(InputStream in, CryptoCipher cipher, int 
bufferSize,
-                              byte[] key, byte[] iv, long streamOffset) throws 
IOException {
-    this(new StreamInput(in, bufferSize), cipher, bufferSize, key, iv, 
streamOffset);
-  }
-
-  /**
-   * Constructs a {@link CTRCryptoInputStream}.
-   *
-   * @param in the ReadableByteChannel instance.
-   * @param cipher the CryptoCipher instance.
-   * @param bufferSize the bufferSize.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @param streamOffset the start offset in the stream.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoInputStream(ReadableByteChannel in, CryptoCipher cipher,
-                              int bufferSize, byte[] key, byte[] iv, long 
streamOffset) throws IOException {
-    this(new ChannelInput(in), cipher, bufferSize, key, iv, streamOffset);
-  }
-
-  /**
-   * Constructs a {@link CTRCryptoInputStream}.
-   *
-   * @param input the input data.
-   * @param cipher the CryptoCipher instance.
-   * @param bufferSize the bufferSize.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @param streamOffset the start offset in the stream.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoInputStream(
-      Input input,
-      CryptoCipher cipher,
-      int bufferSize,
-      byte[] key,
-      byte[] iv,
-      long streamOffset) throws IOException {
-    super(input, cipher, bufferSize, new SecretKeySpec(key, "AES"), new 
IvParameterSpec(iv));
-
-    this.initIV = iv.clone();
-    this.iv = iv.clone();
-
-    Utils.checkStreamCipher(cipher);
-
-    resetStreamOffset(streamOffset);
-  }
-
-  /**
-   * Overrides the {@link CryptoInputStream#skip(long)}.
-   * Skips over and discards <code>n</code> bytes of data from this input
-   * stream.
-   *
-   * @param n the number of bytes to be skipped.
-   * @return the actual number of bytes skipped.
-   * @throws IOException if an I/O error occurs.
-   */
-  @Override
-  public long skip(long n) throws IOException {
-    Utils.checkArgument(n >= 0, "Negative skip length.");
-    checkStream();
-
-    if (n == 0) {
-      return 0;
-    } else if (n <= outBuffer.remaining()) {
-      int pos = outBuffer.position() + (int) n;
-      outBuffer.position(pos);
-      return n;
-    } else {
-      /*
-       * Subtract outBuffer.remaining() to see how many bytes we need to
-       * skip in the underlying stream. Add outBuffer.remaining() to the
-       * actual number of skipped bytes in the underlying stream to get the
-       * number of skipped bytes from the user's point of view.
-       */
-      n -= outBuffer.remaining();
-      long skipped = input.skip(n);
-      if (skipped < 0) {
-        skipped = 0;
-      }
-      long pos = streamOffset + skipped;
-      skipped += outBuffer.remaining();
-      resetStreamOffset(pos);
-      return skipped;
+    /**
+     * Underlying stream offset
+     */
+    long streamOffset = 0;
+
+    /**
+     * The initial IV.
+     */
+    protected final byte[] initIV;
+
+    /**
+     * Initialization vector for the cipher.
+     */
+    protected byte[] iv;
+
+    /**
+     * Padding = pos%(algorithm blocksize); Padding is put into
+     * {@link #inBuffer} before any other data goes in. The purpose of padding
+     * is to put the input data at proper position.
+     */
+    private byte padding;
+
+    /**
+     * Flag to mark whether the cipher has been reset
+     */
+    private boolean cipherReset = false;
+
+    /**
+     * Constructs a {@link CTRCryptoInputStream}.
+     *
+     * @param props The <code>Properties</code> class represents a set of
+     *        properties.
+     * @param in the input stream.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoInputStream(Properties props, InputStream in, byte[] key,
+            byte[] iv) throws IOException {
+        this(props, in, key, iv, 0);
     }
-  }
-
-  /**
-   * Overrides the {@link CTRCryptoInputStream#read(ByteBuffer)}.
-   * Reads a sequence of bytes from this channel into the given buffer.
-   *
-   * @param buf The buffer into which bytes are to be transferred.
-   * @return The number of bytes read, possibly zero, or <tt>-1</tt> if the
-   *          channel has reached end-of-stream.
-   * @throws IOException if an I/O error occurs.
-   */
-  @Override
-  public int read(ByteBuffer buf) throws IOException {
-    checkStream();
-    int unread = outBuffer.remaining();
-    if (unread <= 0) { // Fill the unread decrypted data buffer firstly
-      final int n = input.read(inBuffer);
-      if (n <= 0) {
-        return n;
-      }
-
-      streamOffset += n; // Read n bytes
-      if (buf.isDirect() && buf.remaining() >= inBuffer.position() && padding 
== 0) {
-        // Use buf as the output buffer directly
-        decryptInPlace(buf);
-        padding = postDecryption(streamOffset);
-        return n;
-      } else {
-        // Use outBuffer as the output buffer
+
+    /**
+     * Constructs a {@link CTRCryptoInputStream}.
+     *
+     * @param props The <code>Properties</code> class represents a set of
+     *        properties.
+     * @param in the ReadableByteChannel instance.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoInputStream(Properties props, ReadableByteChannel in,
+            byte[] key, byte[] iv) throws IOException {
+        this(props, in, key, iv, 0);
+    }
+
+    /**
+     * Constructs a {@link CTRCryptoInputStream}.
+     *
+     * @param in the input stream.
+     * @param cipher the CryptoCipher instance.
+     * @param bufferSize the bufferSize.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoInputStream(InputStream in, CryptoCipher cipher,
+            int bufferSize, byte[] key, byte[] iv) throws IOException {
+        this(in, cipher, bufferSize, key, iv, 0);
+    }
+
+    /**
+     * Constructs a {@link CTRCryptoInputStream}.
+     *
+     * @param in the ReadableByteChannel instance.
+     * @param cipher the cipher instance.
+     * @param bufferSize the bufferSize.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoInputStream(ReadableByteChannel in, CryptoCipher cipher,
+            int bufferSize, byte[] key, byte[] iv) throws IOException {
+        this(in, cipher, bufferSize, key, iv, 0);
+    }
+
+    /**
+     * Constructs a {@link CTRCryptoInputStream}.
+     *
+     * @param input the input data.
+     * @param cipher the CryptoCipher instance.
+     * @param bufferSize the bufferSize.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoInputStream(Input input, CryptoCipher cipher,
+            int bufferSize, byte[] key, byte[] iv) throws IOException {
+        this(input, cipher, bufferSize, key, iv, 0);
+    }
+
+    /**
+     * Constructs a {@link CTRCryptoInputStream}.
+     *
+     * @param props The <code>Properties</code> class represents a set of
+     *        properties.
+     * @param in the InputStream instance.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @param streamOffset the start offset in the stream.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoInputStream(Properties props, InputStream in, byte[] key,
+            byte[] iv, long streamOffset) throws IOException {
+        this(in, Utils.getCipherInstance(
+                CipherTransformation.AES_CTR_NOPADDING, props), Utils
+                .getBufferSize(props), key, iv, streamOffset);
+    }
+
+    /**
+     * Constructs a {@link CTRCryptoInputStream}.
+     *
+     * @param props The <code>Properties</code> class represents a set of
+     *        properties.
+     * @param in the ReadableByteChannel instance.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @param streamOffset the start offset in the stream.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoInputStream(Properties props, ReadableByteChannel in,
+            byte[] key, byte[] iv, long streamOffset) throws IOException {
+        this(in, Utils.getCipherInstance(
+                CipherTransformation.AES_CTR_NOPADDING, props), Utils
+                .getBufferSize(props), key, iv, streamOffset);
+    }
+
+    /**
+     * Constructs a {@link CTRCryptoInputStream}.
+     *
+     * @param in the InputStream instance.
+     * @param cipher the CryptoCipher instance.
+     * @param bufferSize the bufferSize.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @param streamOffset the start offset in the stream.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoInputStream(InputStream in, CryptoCipher cipher,
+            int bufferSize, byte[] key, byte[] iv, long streamOffset)
+            throws IOException {
+        this(new StreamInput(in, bufferSize), cipher, bufferSize, key, iv,
+                streamOffset);
+    }
+
+    /**
+     * Constructs a {@link CTRCryptoInputStream}.
+     *
+     * @param in the ReadableByteChannel instance.
+     * @param cipher the CryptoCipher instance.
+     * @param bufferSize the bufferSize.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @param streamOffset the start offset in the stream.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoInputStream(ReadableByteChannel in, CryptoCipher cipher,
+            int bufferSize, byte[] key, byte[] iv, long streamOffset)
+            throws IOException {
+        this(new ChannelInput(in), cipher, bufferSize, key, iv, streamOffset);
+    }
+
+    /**
+     * Constructs a {@link CTRCryptoInputStream}.
+     *
+     * @param input the input data.
+     * @param cipher the CryptoCipher instance.
+     * @param bufferSize the bufferSize.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @param streamOffset the start offset in the stream.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoInputStream(Input input, CryptoCipher cipher,
+            int bufferSize, byte[] key, byte[] iv, long streamOffset)
+            throws IOException {
+        super(input, cipher, bufferSize, new SecretKeySpec(key, "AES"),
+                new IvParameterSpec(iv));
+
+        this.initIV = iv.clone();
+        this.iv = iv.clone();
+
+        Utils.checkStreamCipher(cipher);
+
+        resetStreamOffset(streamOffset);
+    }
+
+    /**
+     * Overrides the {@link CryptoInputStream#skip(long)}. Skips over and
+     * discards <code>n</code> bytes of data from this input stream.
+     *
+     * @param n the number of bytes to be skipped.
+     * @return the actual number of bytes skipped.
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    public long skip(long n) throws IOException {
+        Utils.checkArgument(n >= 0, "Negative skip length.");
+        checkStream();
+
+        if (n == 0) {
+            return 0;
+        } else if (n <= outBuffer.remaining()) {
+            int pos = outBuffer.position() + (int) n;
+            outBuffer.position(pos);
+            return n;
+        } else {
+            /*
+             * Subtract outBuffer.remaining() to see how many bytes we need to
+             * skip in the underlying stream. Add outBuffer.remaining() to the
+             * actual number of skipped bytes in the underlying stream to get
+             * the number of skipped bytes from the user's point of view.
+             */
+            n -= outBuffer.remaining();
+            long skipped = input.skip(n);
+            if (skipped < 0) {
+                skipped = 0;
+            }
+            long pos = streamOffset + skipped;
+            skipped += outBuffer.remaining();
+            resetStreamOffset(pos);
+            return skipped;
+        }
+    }
+
+    /**
+     * Overrides the {@link CTRCryptoInputStream#read(ByteBuffer)}. Reads a
+     * sequence of bytes from this channel into the given buffer.
+     *
+     * @param buf The buffer into which bytes are to be transferred.
+     * @return The number of bytes read, possibly zero, or <tt>-1</tt> if the
+     *         channel has reached end-of-stream.
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    public int read(ByteBuffer buf) throws IOException {
+        checkStream();
+        int unread = outBuffer.remaining();
+        if (unread <= 0) { // Fill the unread decrypted data buffer firstly
+            final int n = input.read(inBuffer);
+            if (n <= 0) {
+                return n;
+            }
+
+            streamOffset += n; // Read n bytes
+            if (buf.isDirect() && buf.remaining() >= inBuffer.position()
+                    && padding == 0) {
+                // Use buf as the output buffer directly
+                decryptInPlace(buf);
+                padding = postDecryption(streamOffset);
+                return n;
+            } else {
+                // Use outBuffer as the output buffer
+                decrypt();
+                padding = postDecryption(streamOffset);
+            }
+        }
+
+        // Copy decrypted data from outBuffer to buf
+        unread = outBuffer.remaining();
+        final int toRead = buf.remaining();
+        if (toRead <= unread) {
+            final int limit = outBuffer.limit();
+            outBuffer.limit(outBuffer.position() + toRead);
+            buf.put(outBuffer);
+            outBuffer.limit(limit);
+            return toRead;
+        } else {
+            buf.put(outBuffer);
+            return unread;
+        }
+    }
+
+    /**
+     * Seeks the stream to a specific position relative to start of the under
+     * layer stream.
+     *
+     * @param position the given position in the data.
+     * @throws IOException if an I/O error occurs.
+     */
+    public void seek(long position) throws IOException {
+        Utils.checkArgument(position >= 0, "Cannot seek to negative offset.");
+        checkStream();
+        /*
+         * If data of target pos in the underlying stream has already been read
+         * and decrypted in outBuffer, we just need to re-position outBuffer.
+         */
+        if (position >= getStreamPosition() && position <= getStreamOffset()) {
+            int forward = (int) (position - getStreamPosition());
+            if (forward > 0) {
+                outBuffer.position(outBuffer.position() + forward);
+            }
+        } else {
+            input.seek(position);
+            resetStreamOffset(position);
+        }
+    }
+
+    /**
+     * Gets the offset of the stream.
+     *
+     * @return the stream offset.
+     */
+    protected long getStreamOffset() {
+        return streamOffset;
+    }
+
+    protected void setStreamOffset(long streamOffset) {
+        this.streamOffset = streamOffset;
+    }
+
+    /**
+     * Gets the position of the stream.
+     *
+     * @return the position of the stream.
+     */
+    protected long getStreamPosition() {
+        return streamOffset - outBuffer.remaining();
+    }
+
+    /**
+     * Decrypts more data by reading the under layer stream. The decrypted data
+     * will be put in the output buffer.
+     *
+     * @return The number of decrypted data. -1 if end of the decrypted stream.
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    protected int decryptMore() throws IOException {
+        int n = input.read(inBuffer);
+        if (n <= 0) {
+            return n;
+        }
+
+        streamOffset += n; // Read n bytes
         decrypt();
         padding = postDecryption(streamOffset);
-      }
+        return outBuffer.remaining();
     }
 
-    // Copy decrypted data from outBuffer to buf
-    unread = outBuffer.remaining();
-    final int toRead = buf.remaining();
-    if (toRead <= unread) {
-      final int limit = outBuffer.limit();
-      outBuffer.limit(outBuffer.position() + toRead);
-      buf.put(outBuffer);
-      outBuffer.limit(limit);
-      return toRead;
-    } else {
-      buf.put(outBuffer);
-      return unread;
+    /**
+     * Does the decryption using inBuffer as input and outBuffer as output. 
Upon
+     * return, inBuffer is cleared; the decrypted data starts at
+     * outBuffer.position() and ends at outBuffer.limit().
+     *
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    protected void decrypt() throws IOException {
+        Utils.checkState(inBuffer.position() >= padding);
+        if (inBuffer.position() == padding) {
+            // There is no real data in inBuffer.
+            return;
+        }
+
+        inBuffer.flip();
+        outBuffer.clear();
+        decryptBuffer(outBuffer);
+        inBuffer.clear();
+        outBuffer.flip();
+
+        if (padding > 0) {
+            /*
+             * The plain text and cipher text have a 1:1 mapping, they start at
+             * the same position.
+             */
+            outBuffer.position(padding);
+        }
     }
-  }
-
-  /**
-   * Seeks the stream to a specific position relative to start of the under 
layer stream.
-   *
-   * @param position the given position in the data.
-   * @throws IOException if an I/O error occurs.
-   */
-  public void seek(long position) throws IOException {
-    Utils.checkArgument(position >= 0, "Cannot seek to negative offset.");
-    checkStream();
-    /*
-     * If data of target pos in the underlying stream has already been read
-     * and decrypted in outBuffer, we just need to re-position outBuffer.
-     */
-    if (position >= getStreamPosition() && position <= getStreamOffset()) {
-      int forward = (int) (position - getStreamPosition());
-      if (forward > 0) {
-        outBuffer.position(outBuffer.position() + forward);
-      }
-    } else {
-      input.seek(position);
-      resetStreamOffset(position);
+
+    /**
+     * Does the decryption using inBuffer as input and buf as output. Upon
+     * return, inBuffer is cleared; the buf's position will be equal to
+     * <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i> where <i>p</i> is the position
+     * before decryption, <i>n</i> is the number of bytes decrypted. The buf's
+     * limit will not have changed.
+     *
+     * @param buf The buffer into which bytes are to be transferred.
+     * @throws IOException if an I/O error occurs.
+     */
+    protected void decryptInPlace(ByteBuffer buf) throws IOException {
+        Utils.checkState(inBuffer.position() >= padding);
+        Utils.checkState(buf.isDirect());
+        Utils.checkState(buf.remaining() >= inBuffer.position());
+        Utils.checkState(padding == 0);
+
+        if (inBuffer.position() == padding) {
+            // There is no real data in inBuffer.
+            return;
+        }
+        inBuffer.flip();
+        decryptBuffer(buf);
+        inBuffer.clear();
     }
-  }
-
-  /**
-   * Gets the offset of the stream.
-   *
-   * @return the stream offset.
-   */
-  protected long getStreamOffset() {
-    return streamOffset;
-  }
-
-  protected void setStreamOffset(long streamOffset) {
-    this.streamOffset = streamOffset;
-  }
-
-  /**
-   * Gets the position of the stream.
-   *
-   * @return the position of the stream.
-   */
-  protected long getStreamPosition() {
-    return streamOffset - outBuffer.remaining();
-  }
-
-  /**
-   * Decrypts more data by reading the under layer stream. The decrypted data 
will
-   * be put in the output buffer.
-   *
-   * @return The number of decrypted data. -1 if end of the decrypted stream.
-   * @throws IOException if an I/O error occurs.
-   */
-  @Override
-  protected int decryptMore() throws IOException {
-    int n = input.read(inBuffer);
-    if (n <= 0) {
-      return n;
+
+    /**
+     * Decrypts all data in buf: total n bytes from given start position. 
Output
+     * is also buf and same start position. buf.position() and buf.limit()
+     * should be unchanged after decryption.
+     *
+     * @param buf The buffer into which bytes are to be transferred.
+     * @param offset the start offset in the data.
+     * @param len the the maximum number of decrypted data bytes to read.
+     * @throws IOException if an I/O error occurs.
+     */
+    protected void decrypt(ByteBuffer buf, int offset, int len)
+            throws IOException {
+        final int pos = buf.position();
+        final int limit = buf.limit();
+        int n = 0;
+        while (n < len) {
+            buf.position(offset + n);
+            buf.limit(offset + n + Math.min(len - n, inBuffer.remaining()));
+            inBuffer.put(buf);
+            // Do decryption
+            try {
+                decrypt();
+                buf.position(offset + n);
+                buf.limit(limit);
+                n += outBuffer.remaining();
+                buf.put(outBuffer);
+            } finally {
+                padding = postDecryption(streamOffset - (len - n));
+            }
+        }
+        buf.position(pos);
     }
 
-    streamOffset += n; // Read n bytes
-    decrypt();
-    padding = postDecryption(streamOffset);
-    return outBuffer.remaining();
-  }
-
-  /**
-   * Does the decryption using inBuffer as input and outBuffer as output.
-   * Upon return, inBuffer is cleared; the decrypted data starts at
-   * outBuffer.position() and ends at outBuffer.limit().
-   *
-   * @throws IOException if an I/O error occurs.
-   */
-  @Override
-  protected void decrypt() throws IOException {
-    Utils.checkState(inBuffer.position() >= padding);
-    if(inBuffer.position() == padding) {
-      // There is no real data in inBuffer.
-      return;
+    /**
+     * This method is executed immediately after decryption. Checks whether
+     * cipher should be updated and recalculate padding if needed.
+     *
+     * @param position the given position in the data..
+     * @return the byte.
+     * @throws IOException if an I/O error occurs.
+     */
+    protected byte postDecryption(long position) throws IOException {
+        byte padding = 0;
+        if (cipherReset) {
+            /*
+             * This code is generally not executed since the cipher usually
+             * maintains cipher context (e.g. the counter) internally. However,
+             * some implementations can't maintain context so a re-init is
+             * necessary after each decryption call.
+             */
+            resetCipher(position);
+            padding = getPadding(position);
+            inBuffer.position(padding);
+        }
+        return padding;
     }
 
-    inBuffer.flip();
-    outBuffer.clear();
-    decryptBuffer(outBuffer);
-    inBuffer.clear();
-    outBuffer.flip();
-
-    if (padding > 0) {
-      /*
-       * The plain text and cipher text have a 1:1 mapping, they start at the
-       * same position.
-       */
-      outBuffer.position(padding);
+    /**
+     * Gets the initialization vector.
+     *
+     * @return the initIV.
+     */
+    protected byte[] getInitIV() {
+        return initIV;
     }
-  }
-
-  /**
-   * Does the decryption using inBuffer as input and buf as output.
-   * Upon return, inBuffer is cleared; the buf's position will be equal to
-   * <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i> where <i>p</i> is the position 
before
-   * decryption, <i>n</i> is the number of bytes decrypted.
-   * The buf's limit will not have changed.
-   *
-   * @param buf The buffer into which bytes are to be transferred.
-   * @throws IOException if an I/O error occurs.
-   */
-  protected void decryptInPlace(ByteBuffer buf) throws IOException {
-    Utils.checkState(inBuffer.position() >= padding);
-    Utils.checkState(buf.isDirect());
-    Utils.checkState(buf.remaining() >= inBuffer.position());
-    Utils.checkState(padding == 0);
-
-    if(inBuffer.position() == padding) {
-      // There is no real data in inBuffer.
-      return;
+
+    /**
+     * Gets the counter for input stream position.
+     *
+     * @param position the given position in the data.
+     * @return the counter for input stream position.
+     */
+    protected long getCounter(long position) {
+        return position / cipher.getTransformation().getAlgorithmBlockSize();
     }
-    inBuffer.flip();
-    decryptBuffer(buf);
-    inBuffer.clear();
-  }
-
-  /**
-   * Decrypts all data in buf: total n bytes from given start position.
-   * Output is also buf and same start position.
-   * buf.position() and buf.limit() should be unchanged after decryption.
-   *
-   * @param buf The buffer into which bytes are to be transferred.
-   * @param offset the start offset in the data.
-   * @param len the the maximum number of decrypted data bytes to read.
-   * @throws IOException if an I/O error occurs.
-   */
-  protected void decrypt(ByteBuffer buf, int offset, int len)
-      throws IOException {
-    final int pos = buf.position();
-    final int limit = buf.limit();
-    int n = 0;
-    while (n < len) {
-      buf.position(offset + n);
-      buf.limit(offset + n + Math.min(len - n, inBuffer.remaining()));
-      inBuffer.put(buf);
-      // Do decryption
-      try {
-        decrypt();
-        buf.position(offset + n);
-        buf.limit(limit);
-        n += outBuffer.remaining();
-        buf.put(outBuffer);
-      } finally {
-        padding = postDecryption(streamOffset - (len - n));
-      }
+
+    /**
+     * Gets the padding for input stream position.
+     *
+     * @param position the given position in the data.
+     * @return the padding for input stream position.
+     */
+    protected byte getPadding(long position) {
+        return (byte) (position % cipher.getTransformation()
+                .getAlgorithmBlockSize());
     }
-    buf.position(pos);
-  }
-
-  /**
-   * This method is executed immediately after decryption. Checks whether
-   * cipher should be updated and recalculate padding if needed.
-   *
-   * @param position the given position in the data..
-   * @return the byte.
-   * @throws IOException if an I/O error occurs.
-   */
-  protected byte postDecryption(long position) throws IOException {
-    byte padding = 0;
-    if (cipherReset) {
-      /*
-       * This code is generally not executed since the cipher usually
-       * maintains cipher context (e.g. the counter) internally. However,
-       * some implementations can't maintain context so a re-init is necessary
-       * after each decryption call.
-       */
-      resetCipher(position);
-      padding = getPadding(position);
-      inBuffer.position(padding);
+
+    /**
+     * Overrides the {@link CTRCryptoInputStream#initCipher()}. Initializes the
+     * cipher.
+     */
+    @Override
+    protected void initCipher() {
+        // Do nothing for initCipher
+        // Will reset the cipher when reset the stream offset
     }
-    return padding;
-  }
-
-  /**
-   * Gets the initialization vector.
-   *
-   * @return the initIV.
-   */
-  protected byte[] getInitIV() {
-    return initIV;
-  }
-
-  /**
-   * Gets the counter for input stream position.
-   *
-   * @param position the given position in the data.
-   * @return the counter for input stream position.
-   */
-  protected long getCounter(long position) {
-    return position / cipher.getTransformation().getAlgorithmBlockSize();
-  }
-
-  /**
-   * Gets the padding for input stream position.
-   *
-   * @param position the given position in the data.
-   * @return the padding for input stream position.
-   */
-  protected byte getPadding(long position) {
-    return (byte)(position % 
cipher.getTransformation().getAlgorithmBlockSize());
-  }
-
-  /**
-   * Overrides the {@link CTRCryptoInputStream#initCipher()}.
-   * Initializes the cipher.
-   */
-  @Override
-  protected void initCipher() {
-    // Do nothing for initCipher
-    // Will reset the cipher when reset the stream offset
-  }
-
-  /**
-   * Calculates the counter and iv, resets the cipher.
-   *
-   * @param position the given position in the data.
-   * @throws IOException if an I/O error occurs.
-   */
-  protected void resetCipher(long position)
-      throws IOException {
-    final long counter = getCounter(position);
-    Utils.calculateIV(initIV, counter, iv);
-    try {
-      cipher.init(CryptoCipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
-    } catch (InvalidKeyException e) {
-      throw new IOException(e);
-    } catch (InvalidAlgorithmParameterException e) {
-      throw new IOException(e);
+
+    /**
+     * Calculates the counter and iv, resets the cipher.
+     *
+     * @param position the given position in the data.
+     * @throws IOException if an I/O error occurs.
+     */
+    protected void resetCipher(long position) throws IOException {
+        final long counter = getCounter(position);
+        Utils.calculateIV(initIV, counter, iv);
+        try {
+            cipher.init(CryptoCipher.DECRYPT_MODE, key, new 
IvParameterSpec(iv));
+        } catch (InvalidKeyException e) {
+            throw new IOException(e);
+        } catch (InvalidAlgorithmParameterException e) {
+            throw new IOException(e);
+        }
+        cipherReset = false;
     }
-    cipherReset = false;
-  }
-
-  /**
-   * Resets the underlying stream offset; clear {@link #inBuffer} and
-   * {@link #outBuffer}. This Typically happens during {@link #skip(long)}.
-   *
-   * @param offset the offset of the stream.
-   * @throws IOException if an I/O error occurs.
-   */
-  protected void resetStreamOffset(long offset) throws IOException {
-    streamOffset = offset;
-    inBuffer.clear();
-    outBuffer.clear();
-    outBuffer.limit(0);
-    resetCipher(offset);
-    padding = getPadding(offset);
-    inBuffer.position(padding); // Set proper position for input data.
-  }
-
-  /**
-   * Does the decryption using out as output.
-   *
-   * @param out the output ByteBuffer.
-   * @throws IOException if an I/O error occurs.
-   */
-  protected void decryptBuffer(ByteBuffer out)
-      throws IOException {
-    int inputSize = inBuffer.remaining();
-    try {
-      int n = cipher.update(inBuffer, out);
-      if (n < inputSize) {
-        /**
-         * Typically code will not get here. CryptoCipher#update will consume 
all
-         * input data and put result in outBuffer.
-         * CryptoCipher#doFinal will reset the cipher context.
-         */
-        cipher.doFinal(inBuffer, out);
-        cipherReset = true;
-      }
-    } catch (ShortBufferException e) {
-      throw new IOException(e);
-    } catch (IllegalBlockSizeException e) {
-      throw new IOException(e);
-    } catch (BadPaddingException e) {
-      throw new IOException(e);
+
+    /**
+     * Resets the underlying stream offset; clear {@link #inBuffer} and
+     * {@link #outBuffer}. This Typically happens during {@link #skip(long)}.
+     *
+     * @param offset the offset of the stream.
+     * @throws IOException if an I/O error occurs.
+     */
+    protected void resetStreamOffset(long offset) throws IOException {
+        streamOffset = offset;
+        inBuffer.clear();
+        outBuffer.clear();
+        outBuffer.limit(0);
+        resetCipher(offset);
+        padding = getPadding(offset);
+        inBuffer.position(padding); // Set proper position for input data.
+    }
+
+    /**
+     * Does the decryption using out as output.
+     *
+     * @param out the output ByteBuffer.
+     * @throws IOException if an I/O error occurs.
+     */
+    protected void decryptBuffer(ByteBuffer out) throws IOException {
+        int inputSize = inBuffer.remaining();
+        try {
+            int n = cipher.update(inBuffer, out);
+            if (n < inputSize) {
+                /**
+                 * Typically code will not get here. CryptoCipher#update will
+                 * consume all input data and put result in outBuffer.
+                 * CryptoCipher#doFinal will reset the cipher context.
+                 */
+                cipher.doFinal(inBuffer, out);
+                cipherReset = true;
+            }
+        } catch (ShortBufferException e) {
+            throw new IOException(e);
+        } catch (IllegalBlockSizeException e) {
+            throw new IOException(e);
+        } catch (BadPaddingException e) {
+            throw new IOException(e);
+        }
     }
-  }
 }

Reply via email to