private ByteSource encrypt(byte[] plaintext, byte[] key, byte[] iv, boolean prependIv) throws CryptoException {

        final int MODE = javax.crypto.Cipher.ENCRYPT_MODE;

        byte[] output;

        if (prependIv && iv != null && iv.length > 0) {

            byte[] encrypted = crypt(plaintext, key, iv, MODE);

            output = new byte[iv.length + encrypted.length];

            //now copy the iv bytes + encrypted bytes into one output array:

            // iv bytes:
            System.arraycopy(iv, 0, output, 0, iv.length);

            // + encrypted bytes:
            System.arraycopy(encrypted, 0, output, iv.length, encrypted.length);
        } else {
            output = crypt(plaintext, key, iv, MODE);
        }

        if (log.isTraceEnabled()) {
            log.trace("Incoming plaintext of size " + (plaintext != null ? plaintext.length : 0) + ".  Ciphertext " +
                    "byte array is size " + (output != null ? output.length : 0));
        }

        return ByteSource.Util.bytes(output);
    }
Returns the transformation string to use with the {@link javax.crypto.Cipher#getInstance} invocation when
creating a new {@code Cipher} instance.  This default implementation always returns
{@link #getAlgorithmName() getAlgorithmName()}.  Block cipher implementations will want to override this method
to support appending cipher operation modes and padding schemes.

@param streaming if the transformation string is going to be used for a Cipher for stream-based encryption or not.
@return the transformation string to use with the {@link javax.crypto.Cipher#getInstance} invocation when
        creating a new {@code Cipher} instance.
src/main/java/org/apache/shiro/crypto/cipher/JcaCipherService.java