You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2022/12/11 17:26:36 UTC

[commons-crypto] branch master updated: Reuse own API and use ternary expressions

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-crypto.git


The following commit(s) were added to refs/heads/master by this push:
     new d669943  Reuse own API and use ternary expressions
d669943 is described below

commit d669943573a9ef2df1f684e32f81ffe1e09b08fd
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sun Dec 11 12:26:32 2022 -0500

    Reuse own API and use ternary expressions
---
 .../crypto/stream/PositionedCryptoInputStream.java | 352 ++++++++++-----------
 .../org/apache/commons/crypto/utils/Utils.java     |   4 +-
 2 files changed, 170 insertions(+), 186 deletions(-)

diff --git a/src/main/java/org/apache/commons/crypto/stream/PositionedCryptoInputStream.java b/src/main/java/org/apache/commons/crypto/stream/PositionedCryptoInputStream.java
index a0e7b04..632a552 100644
--- a/src/main/java/org/apache/commons/crypto/stream/PositionedCryptoInputStream.java
+++ b/src/main/java/org/apache/commons/crypto/stream/PositionedCryptoInputStream.java
@@ -28,7 +28,6 @@ import javax.crypto.Cipher;
 import javax.crypto.spec.IvParameterSpec;
 
 import org.apache.commons.crypto.cipher.CryptoCipher;
-import org.apache.commons.crypto.cipher.CryptoCipherFactory;
 import org.apache.commons.crypto.stream.input.Input;
 import org.apache.commons.crypto.utils.AES;
 import org.apache.commons.crypto.utils.IoUtils;
@@ -41,15 +40,58 @@ import org.apache.commons.crypto.utils.Utils;
  */
 public class PositionedCryptoInputStream extends CtrCryptoInputStream {
 
+    private static class CipherState {
+
+        private final CryptoCipher cryptoCipher;
+        private boolean reset;
+
+        /**
+         * Constructs a new instance.
+         *
+         * @param cryptoCipher the CryptoCipher instance.
+         */
+        public CipherState(final CryptoCipher cryptoCipher) {
+            this.cryptoCipher = cryptoCipher;
+            this.reset = false;
+        }
+
+        /**
+         * Gets the CryptoCipher instance.
+         *
+         * @return the cipher.
+         */
+        public CryptoCipher getCryptoCipher() {
+            return cryptoCipher;
+        }
+
+        /**
+         * Gets the reset.
+         *
+         * @return the value of reset.
+         */
+        public boolean isReset() {
+            return reset;
+        }
+
+        /**
+         * Sets the value of reset.
+         *
+         * @param reset the reset.
+         */
+        public void reset(final boolean reset) {
+            this.reset = reset;
+        }
+    }
+
     /**
      * DirectBuffer pool
      */
-    private final Queue<ByteBuffer> bufferPool = new ConcurrentLinkedQueue<>();
+    private final Queue<ByteBuffer> byteBufferPool = new ConcurrentLinkedQueue<>();
 
     /**
      * CryptoCipher pool
      */
-    private final Queue<CipherState> cipherPool = new ConcurrentLinkedQueue<>();
+    private final Queue<CipherState> cipherStatePool = new ConcurrentLinkedQueue<>();
 
     /**
      * properties for constructing a CryptoCipher
@@ -93,62 +135,60 @@ public class PositionedCryptoInputStream extends CtrCryptoInputStream {
         this.properties = properties;
     }
 
-    /**
-     * Reads up to the specified number of bytes from a given position within a
-     * stream and return the number of bytes read. This does not change the
-     * current offset of the stream, and is thread-safe.
-     *
-     * @param buffer the buffer into which the data is read.
-     * @param length the maximum number of bytes to read.
-     * @param offset the start offset in the data.
-     * @param position the offset from the start of the stream.
-     * @throws IOException if an I/O error occurs.
-     * @return int the total number of decrypted data bytes read into the
-     *         buffer.
-     */
-    public int read(final long position, final byte[] buffer, final int offset, final int length)
-            throws IOException {
-        checkStream();
-        final int n = input.read(position, buffer, offset, length);
-        if (n > 0) {
-            // This operation does not change the current offset of the file
-            decrypt(position, buffer, offset, n);
+    /** Cleans direct buffer pool */
+    private void cleanBufferPool() {
+        ByteBuffer buf;
+        while ((buf = byteBufferPool.poll()) != null) {
+            CryptoInputStream.freeDirectBuffer(buf);
         }
-        return n;
     }
 
     /**
-     * Reads the specified number of bytes from a given position within a
-     * stream. This does not change the current offset of the stream and is
-     * thread-safe.
+     * Overrides the {@link CryptoInputStream#close()}. Closes this input stream
+     * and releases any system resources associated with the stream.
      *
-     * @param buffer the buffer into which the data is read.
-     * @param length the maximum number of bytes to read.
-     * @param offset the start offset in the data.
-     * @param position the offset from the start of the stream.
      * @throws IOException if an I/O error occurs.
      */
-    public void readFully(final long position, final byte[] buffer, final int offset, final int length)
-            throws IOException {
-        checkStream();
-        IoUtils.readFully(input, position, buffer, offset, length);
-        if (length > 0) {
-            // This operation does not change the current offset of the file
-            decrypt(position, buffer, offset, length);
+    @Override
+    public void close() throws IOException {
+        if (!isOpen()) {
+            return;
         }
+
+        cleanBufferPool();
+        super.close();
     }
 
     /**
-     * Reads the specified number of bytes from a given position within a
-     * stream. This does not change the current offset of the stream and is
-     * thread-safe.
+     * 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().
      *
-     * @param position the offset from the start of the stream.
-     * @param buffer the buffer into which the data is read.
+     * @param state the CipherState instance.
+     * @param inByteBuffer the input buffer.
+     * @param outByteBuffer the output buffer.
+     * @param padding the padding.
      * @throws IOException if an I/O error occurs.
      */
-    public void readFully(final long position, final byte[] buffer) throws IOException {
-        readFully(position, buffer, 0, buffer.length);
+    private void decrypt(final CipherState state, final ByteBuffer inByteBuffer,
+            final ByteBuffer outByteBuffer, final byte padding) throws IOException {
+        Utils.checkState(inByteBuffer.position() >= padding);
+        if (inByteBuffer.position() == padding) {
+            // There is no real data in inBuffer.
+            return;
+        }
+        inByteBuffer.flip();
+        outByteBuffer.clear();
+        decryptBuffer(state, inByteBuffer, outByteBuffer);
+        inByteBuffer.clear();
+        outByteBuffer.flip();
+        if (padding > 0) {
+            /*
+             * The plain text and cipher text have a 1:1 mapping, they start at
+             * the same position.
+             */
+            outByteBuffer.position(padding);
+        }
     }
 
     /**
@@ -186,41 +226,9 @@ public class PositionedCryptoInputStream extends CtrCryptoInputStream {
                 padding = postDecryption(state, inByteBuffer, position + n, iv);
             }
         } finally {
-            returnBuffer(inByteBuffer);
-            returnBuffer(outByteBuffer);
-            returnCipherState(state);
-        }
-    }
-
-    /**
-     * 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().
-     *
-     * @param state the CipherState instance.
-     * @param inByteBuffer the input buffer.
-     * @param outByteBuffer the output buffer.
-     * @param padding the padding.
-     * @throws IOException if an I/O error occurs.
-     */
-    private void decrypt(final CipherState state, final ByteBuffer inByteBuffer,
-            final ByteBuffer outByteBuffer, final byte padding) throws IOException {
-        Utils.checkState(inByteBuffer.position() >= padding);
-        if (inByteBuffer.position() == padding) {
-            // There is no real data in inBuffer.
-            return;
-        }
-        inByteBuffer.flip();
-        outByteBuffer.clear();
-        decryptBuffer(state, inByteBuffer, outByteBuffer);
-        inByteBuffer.clear();
-        outByteBuffer.flip();
-        if (padding > 0) {
-            /*
-             * The plain text and cipher text have a 1:1 mapping, they start at
-             * the same position.
-             */
-            outByteBuffer.position(padding);
+            returnToPool(inByteBuffer);
+            returnToPool(outByteBuffer);
+            returnToPool(state);
         }
     }
 
@@ -252,6 +260,28 @@ public class PositionedCryptoInputStream extends CtrCryptoInputStream {
         }
     }
 
+    /**
+     * Gets direct buffer from pool. Caller MUST also call {@link #returnToPool(ByteBuffer)}.
+     *
+     * @return the buffer.
+     * @see #returnToPool(ByteBuffer)
+     */
+    private ByteBuffer getBuffer() {
+        ByteBuffer buffer = byteBufferPool.poll();
+        return buffer != null ? buffer : ByteBuffer.allocateDirect(getBufferSize());
+    }
+
+    /**
+     * Gets CryptoCipher from pool. Caller MUST also call {@link #returnToPool(CipherState)}.
+     *
+     * @return the CipherState instance.
+     * @throws IOException if an I/O error occurs.
+     */
+    private CipherState getCipherState() throws IOException {
+        CipherState state = cipherStatePool.poll();
+        return state != null ? state : new CipherState(Utils.getCipherInstance(AES.CTR_NO_PADDING, properties));
+    }
+
     /**
      * This method is executed immediately after decryption. Check whether
      * cipher should be updated and recalculate padding if needed.
@@ -280,68 +310,80 @@ public class PositionedCryptoInputStream extends CtrCryptoInputStream {
     }
 
     /**
-     * Calculates the counter and iv, reset the cipher.
+     * Reads up to the specified number of bytes from a given position within a
+     * stream and return the number of bytes read. This does not change the
+     * current offset of the stream, and is thread-safe.
      *
-     * @param state the CipherState instance.
+     * @param buffer the buffer into which the data is read.
+     * @param length the maximum number of bytes to read.
+     * @param offset the start offset in the data.
      * @param position the offset from the start of the stream.
-     * @param iv the iv.
+     * @throws IOException if an I/O error occurs.
+     * @return int the total number of decrypted data bytes read into the
+     *         buffer.
      */
-    @SuppressWarnings("resource") // getCryptoCipher does not allocate
-    private void resetCipher(final CipherState state, final long position, final byte[] iv) {
-        final long counter = getCounter(position);
-        CtrCryptoInputStream.calculateIV(getInitIV(), counter, iv);
-        try {
-            state.getCryptoCipher().init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
-        } catch (final GeneralSecurityException e) {
-            // Ignore
+    public int read(final long position, final byte[] buffer, final int offset, final int length)
+            throws IOException {
+        checkStream();
+        final int n = input.read(position, buffer, offset, length);
+        if (n > 0) {
+            // This operation does not change the current offset of the file
+            decrypt(position, buffer, offset, n);
         }
-        state.reset(false);
+        return n;
     }
 
     /**
-     * Gets CryptoCipher from pool.
+     * Reads the specified number of bytes from a given position within a
+     * stream. This does not change the current offset of the stream and is
+     * thread-safe.
      *
-     * @return the CipherState instance.
+     * @param position the offset from the start of the stream.
+     * @param buffer the buffer into which the data is read.
      * @throws IOException if an I/O error occurs.
      */
-    private CipherState getCipherState() throws IOException {
-        CipherState state = cipherPool.poll();
-        if (state == null) {
-            final CryptoCipher cryptoCipher;
-            try {
-                cryptoCipher = CryptoCipherFactory.getCryptoCipher(AES.CTR_NO_PADDING, properties);
-            } catch (final GeneralSecurityException e) {
-                throw new IOException(e);
-            }
-            state = new CipherState(cryptoCipher);
-        }
-
-        return state;
+    public void readFully(final long position, final byte[] buffer) throws IOException {
+        readFully(position, buffer, 0, buffer.length);
     }
 
     /**
-     * Returns CryptoCipher to pool.
+     * Reads the specified number of bytes from a given position within a
+     * stream. This does not change the current offset of the stream and is
+     * thread-safe.
      *
-     * @param state the CipherState instance.
+     * @param buffer the buffer into which the data is read.
+     * @param length the maximum number of bytes to read.
+     * @param offset the start offset in the data.
+     * @param position the offset from the start of the stream.
+     * @throws IOException if an I/O error occurs.
      */
-    private void returnCipherState(final CipherState state) {
-        if (state != null) {
-            cipherPool.add(state);
+    public void readFully(final long position, final byte[] buffer, final int offset, final int length)
+            throws IOException {
+        checkStream();
+        IoUtils.readFully(input, position, buffer, offset, length);
+        if (length > 0) {
+            // This operation does not change the current offset of the file
+            decrypt(position, buffer, offset, length);
         }
     }
 
     /**
-     * Gets direct buffer from pool.
+     * Calculates the counter and iv, reset the cipher.
      *
-     * @return the buffer.
+     * @param state the CipherState instance.
+     * @param position the offset from the start of the stream.
+     * @param iv the iv.
      */
-    private ByteBuffer getBuffer() {
-        ByteBuffer buffer = bufferPool.poll();
-        if (buffer == null) {
-            buffer = ByteBuffer.allocateDirect(getBufferSize());
+    @SuppressWarnings("resource") // getCryptoCipher does not allocate
+    private void resetCipher(final CipherState state, final long position, final byte[] iv) {
+        final long counter = getCounter(position);
+        CtrCryptoInputStream.calculateIV(getInitIV(), counter, iv);
+        try {
+            state.getCryptoCipher().init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
+        } catch (final GeneralSecurityException e) {
+            // Ignore
         }
-
-        return buffer;
+        state.reset(false);
     }
 
     /**
@@ -349,77 +391,21 @@ public class PositionedCryptoInputStream extends CtrCryptoInputStream {
      *
      * @param buf the buffer.
      */
-    private void returnBuffer(final ByteBuffer buf) {
+    private void returnToPool(final ByteBuffer buf) {
         if (buf != null) {
             buf.clear();
-            bufferPool.add(buf);
+            byteBufferPool.add(buf);
         }
     }
 
     /**
-     * Overrides the {@link CryptoInputStream#close()}. Closes this input stream
-     * and releases any system resources associated with the stream.
+     * Returns CryptoCipher to pool.
      *
-     * @throws IOException if an I/O error occurs.
+     * @param state the CipherState instance.
      */
-    @Override
-    public void close() throws IOException {
-        if (!isOpen()) {
-            return;
-        }
-
-        cleanBufferPool();
-        super.close();
-    }
-
-    /** Cleans direct buffer pool */
-    private void cleanBufferPool() {
-        ByteBuffer buf;
-        while ((buf = bufferPool.poll()) != null) {
-            CryptoInputStream.freeDirectBuffer(buf);
-        }
-    }
-
-    private static class CipherState {
-
-        private final CryptoCipher cryptoCipher;
-        private boolean reset;
-
-        /**
-         * Constructs a new instance.
-         *
-         * @param cryptoCipher the CryptoCipher instance.
-         */
-        public CipherState(final CryptoCipher cryptoCipher) {
-            this.cryptoCipher = cryptoCipher;
-            this.reset = false;
-        }
-
-        /**
-         * Gets the CryptoCipher instance.
-         *
-         * @return the cipher.
-         */
-        public CryptoCipher getCryptoCipher() {
-            return cryptoCipher;
-        }
-
-        /**
-         * Gets the reset.
-         *
-         * @return the value of reset.
-         */
-        public boolean isReset() {
-            return reset;
-        }
-
-        /**
-         * Sets the value of reset.
-         *
-         * @param reset the reset.
-         */
-        public void reset(final boolean reset) {
-            this.reset = reset;
+    private void returnToPool(final CipherState state) {
+        if (state != null) {
+            cipherStatePool.add(state);
         }
     }
 }
diff --git a/src/main/java/org/apache/commons/crypto/utils/Utils.java b/src/main/java/org/apache/commons/crypto/utils/Utils.java
index 15e7c91..c0d9ec1 100644
--- a/src/main/java/org/apache/commons/crypto/utils/Utils.java
+++ b/src/main/java/org/apache/commons/crypto/utils/Utils.java
@@ -120,9 +120,7 @@ public final class Utils {
      * @return the CryptoCipher instance.
      * @throws IOException if an I/O error occurs.
      */
-    public static CryptoCipher getCipherInstance(
-            final String transformation, final Properties properties)
-            throws IOException {
+    public static CryptoCipher getCipherInstance(final String transformation, final Properties properties) throws IOException {
         try {
             return CryptoCipherFactory.getCryptoCipher(transformation, properties);
         } catch (final GeneralSecurityException e) {