private void crypt(InputStream in, OutputStream out, byte[] keyBytes, byte[] iv, int cryptMode) throws CryptoException {
        if (in == null) {
            throw new NullPointerException("InputStream argument cannot be null.");
        }
        if (out == null) {
            throw new NullPointerException("OutputStream argument cannot be null.");
        }

        javax.crypto.Cipher cipher = initNewCipher(cryptMode, keyBytes, iv, true);

        CipherInputStream cis = new CipherInputStream(in, cipher);

        int bufSize = getStreamingBufferSize();
        byte[] buffer = new byte[bufSize];

        int bytesRead;
        try {
            while ((bytesRead = cis.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            throw new CryptoException(e);
        }
    }
Initializes the JDK Cipher with the specified mode and key.  This is primarily a utility method to catch any
potential {@link java.security.InvalidKeyException InvalidKeyException} that might arise.

@param cipher the JDK Cipher to {@link javax.crypto.Cipher#init(int, java.security.Key) init}.
@param mode   the Cipher mode
@param key    the Cipher's Key
@param spec   the JDK AlgorithmParameterSpec for cipher initialization (optional, may be null).
@param random the SecureRandom to use for cipher initialization (optional, may be null).
@throws CryptoException if the key is invalid
crypto/cipher/src/main/java/org/apache/shiro/crypto/cipher/JcaCipherService.java