/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.shiro.crypto;

import org.apache.shiro.util.ByteSource;
import org.apache.shiro.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.CipherInputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;

/**
 * Abstract {@code CipherService} implementation utilizing Java's JCA APIs.
 * <h2>Auto-generated Initialization Vectors</h2>
 * Shiro does something by default for all of its {@code CipherService} implementations that the JCA
 * {@link javax.crypto.Cipher Cipher} does not do:  by default,
 * <a href="http://en.wikipedia.org/wiki/Initialization_vector">initialization vector</a>s are automatically randomly
 * generated and prepended to encrypted data before returning from the {@code encrypt} methods.  That is, the returned
 * byte array or {@code OutputStream} is actually a concatenation of an initialization vector byte array plus the actual
 * encrypted data byte array.  The {@code decrypt} methods in turn know to read this prepended initialization vector
 * before decrypting the real data that follows.
 * <p/>
 * This is highly desirable because initialization vectors guarantee that, for a key and any plaintext, the encrypted
 * output will always be different <em>even if you call {@code encrypt} multiple times with the exact same arguments</em>.
 * This is essential in cryptography to ensure that data patterns cannot be identified across multiple input sources
 * that are the same or similar.
 * <p/>
 * You can turn off this behavior by setting the
 * {@link #setGenerateInitializationVectors(boolean) generateInitializationVectors} property to {@code false}, but it
 * is highly recommended that you do not do this unless you have a very good reason to do so, since you would be losing
 * a critical security feature.
 * <h3>Initialization Vector Size</h3>
 * This implementation defaults the {@link #setInitializationVectorSize(int) initializationVectorSize} attribute to
 * {@code 128} bits, a fairly common size.  Initialization vector sizes are very algorithm specific however, so subclass
 * implementations will often override this value in their constructor if necessary.
 * <p/>
 * Also note that {@code initializationVectorSize} values are specified in the number of
 * bits (not bytes!) to match common references in most cryptography documentation.  In practice though, initialization
 * vectors are always specified as a byte array, so ensure that if you set this property, that the value is a multiple
 * of {@code 8} to ensure that the IV can be correctly represented as a byte array (the
 * {@link #setInitializationVectorSize(int) setInitializationVectorSize} mutator method enforces this).
 *
 * @since 1.0
 */
public abstract class JcaCipherService implements CipherService {

    /**
     * Internal private log instance.
     */
    private static final Logger log = LoggerFactory.getLogger(JcaCipherService.class);

    /**
     * Default key size (in bits) for generated keys.
     */
    private static final int DEFAULT_KEY_SIZE = 128;

    /**
     * Default size of the internal buffer (in bytes) used to transfer data between streams during stream operations
     */
    private static final int DEFAULT_STREAMING_BUFFER_SIZE = 512;

    private static final int BITS_PER_BYTE = 8;

    /**
     * Default SecureRandom algorithm name to use when acquiring the SecureRandom instance.
     */
    private static final String RANDOM_NUM_GENERATOR_ALGORITHM_NAME = "SHA1PRNG";

    /**
     * The name of the cipher algorithm to use for all encryption, decryption, and key operations
     */
    private String algorithmName;

    /**
     * The size in bits (not bytes) of generated cipher keys
     */
    private int keySize;

    /**
     * The size of the internal buffer (in bytes) used to transfer data from one stream to another during stream operations
     */
    private int streamingBufferSize;

    private boolean generateInitializationVectors;
    private int initializationVectorSize;


    private SecureRandom secureRandom;

    /**
     * Creates a new {@code JcaCipherService} instance which will use the specified cipher {@code algorithmName}
     * for all encryption, decryption, and key operations.  Also, the following defaults are set:
     * <ul>
     * <li>{@link #setKeySize keySize} = 128 bits</li>
     * <li>{@link #setInitializationVectorSize(int) initializationVectorSize} = 128 bits</li>
     * <li>{@link #setStreamingBufferSize(int) streamingBufferSize} = 512 bytes</li>
     * </ul>
     *
     * @param algorithmName the name of the cipher algorithm to use for all encryption, decryption, and key operations
     */
    protected JcaCipherService(String algorithmName) {
        if (!StringUtils.hasText(algorithmName)) {
            throw new IllegalArgumentException("algorithmName argument cannot be null or empty.");
        }
        this.algorithmName = algorithmName;
        this.keySize = DEFAULT_KEY_SIZE;
        this.initializationVectorSize = DEFAULT_KEY_SIZE; //default to same size as the key size (a common algorithm practice)
        this.streamingBufferSize = DEFAULT_STREAMING_BUFFER_SIZE;
        this.generateInitializationVectors = true;
    }

    /**
     * Returns the cipher algorithm name that will be used for all encryption, decryption, and key operations (for
     * example, 'AES', 'Blowfish', 'RSA', 'DSA', 'TripleDES', etc).
     *
     * @return the cipher algorithm name that will be used for all encryption, decryption, and key operations
     */
    public String getAlgorithmName() {
        return algorithmName;
    }

    /**
     * Returns the size in bits (not bytes) of generated cipher keys.
     *
     * @return the size in bits (not bytes) of generated cipher keys.
     */
    public int getKeySize() {
        return keySize;
    }

    /**
     * Sets the size in bits (not bytes) of generated cipher keys.
     *
     * @param keySize the size in bits (not bytes) of generated cipher keys.
     */
    public void setKeySize(int keySize) {
        this.keySize = keySize;
    }

    public boolean isGenerateInitializationVectors() {
        return generateInitializationVectors;
    }

    public void setGenerateInitializationVectors(boolean generateInitializationVectors) {
        this.generateInitializationVectors = generateInitializationVectors;
    }

    /**
     * Returns the algorithm-specific size in bits of generated initialization vectors.
     *
     * @return the algorithm-specific size in bits of generated initialization vectors.
     */
    public int getInitializationVectorSize() {
        return initializationVectorSize;
    }

    /**
     * Sets the algorithm-specific initialization vector size in bits (not bytes!) to be used when generating
     * initialization vectors.  The  value must be a multiple of {@code 8} to ensure that the IV can be represented
     * as a byte array.
     *
     * @param initializationVectorSize the size in bits (not bytes) of generated initialization vectors.
     * @throws IllegalArgumentException if the size is not a multiple of {@code 8}.
     */
    public void setInitializationVectorSize(int initializationVectorSize) throws IllegalArgumentException {
        if (initializationVectorSize % BITS_PER_BYTE != 0) {
            String msg = "Initialization vector sizes are specified in bits, but must be a multiple of 8 so they " +
                    "can be easily represented as a byte array.";
            throw new IllegalArgumentException(msg);
        }
        this.initializationVectorSize = initializationVectorSize;
    }

    protected boolean isGenerateInitializationVectors(boolean streaming) {
        return isGenerateInitializationVectors();
    }

    /**
     * Returns the size in bytes of the internal buffer used to transfer data from one stream to another during stream
     * operations ({@link #encrypt(java.io.InputStream, java.io.OutputStream, byte[])} and
     * {@link #decrypt(java.io.InputStream, java.io.OutputStream, byte[])}).
     * <p/>
     * Default size is {@code 512} bytes.
     *
     * @return the size of the internal buffer used to transfer data from one stream to another during stream
     *         operations
     */
    public int getStreamingBufferSize() {
        return streamingBufferSize;
    }

    /**
     * Sets the size in bytes of the internal buffer used to transfer data from one stream to another during stream
     * operations ({@link #encrypt(java.io.InputStream, java.io.OutputStream, byte[])} and
     * {@link #decrypt(java.io.InputStream, java.io.OutputStream, byte[])}).
     * <p/>
     * Default size is {@code 512} bytes.
     *
     * @param streamingBufferSize the size of the internal buffer used to transfer data from one stream to another
     *                            during stream operations
     */
    public void setStreamingBufferSize(int streamingBufferSize) {
        this.streamingBufferSize = streamingBufferSize;
    }

    /**
     * Returns a source of randomness for encryption operations.  If one is not configured, and the underlying
     * algorithm needs one, the JDK {@code SHA1PRNG} instance will be used by default.
     *
     * @return a source of randomness for encryption operations.  If one is not configured, and the underlying
     *         algorithm needs one, the JDK {@code SHA1PRNG} instance will be used by default.
     */
    public SecureRandom getSecureRandom() {
        return secureRandom;
    }

    /**
     * Sets a source of randomness for encryption operations.  If one is not configured, and the underlying
     * algorithm needs one, the JDK {@code SHA1PRNG} instance will be used by default.
     *
     * @param secureRandom a source of randomness for encryption operations.  If one is not configured, and the
     *                     underlying algorithm needs one, the JDK {@code SHA1PRNG} instance will be used by default.
     */
    public void setSecureRandom(SecureRandom secureRandom) {
        this.secureRandom = secureRandom;
    }

    protected static SecureRandom getDefaultSecureRandom() {
        try {
            return java.security.SecureRandom.getInstance(RANDOM_NUM_GENERATOR_ALGORITHM_NAME);
        } catch (java.security.NoSuchAlgorithmException e) {
            log.debug("The SecureRandom SHA1PRNG algorithm is not available on the current platform.  Using the " +
                    "platform's default SecureRandom algorithm.", e);
            return new java.security.SecureRandom();
        }
    }

    protected SecureRandom ensureSecureRandom() {
        SecureRandom random = getSecureRandom();
        if (random == null) {
            random = getDefaultSecureRandom();
        }
        return random;
    }

    /**
     * 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.
     */
    protected String getTransformationString(boolean streaming) {
        return getAlgorithmName();
    }

    protected byte[] generateInitializationVector(boolean streaming) {
        int size = getInitializationVectorSize();
        if (size <= 0) {
            String msg = "initializationVectorSize property must be greater than zero.  This number is " +
                    "typically set in the " + CipherService.class.getSimpleName() + " subclass constructor.  " +
                    "Also check your configuration to ensure that if you are setting a value, it is positive.";
            throw new IllegalStateException(msg);
        }
        if (size % BITS_PER_BYTE != 0) {
            String msg = "initializationVectorSize property must be a multiple of 8 to represent as a byte array.";
            throw new IllegalStateException(msg);
        }
        int sizeInBytes = size / BITS_PER_BYTE;
        byte[] ivBytes = new byte[sizeInBytes];
        SecureRandom random = ensureSecureRandom();
        random.nextBytes(ivBytes);
        return ivBytes;
    }

    public ByteSource encrypt(byte[] plaintext, byte[] key) {
        byte[] ivBytes = null;
        boolean generate = isGenerateInitializationVectors(false);
        if (generate) {
            ivBytes = generateInitializationVector(false);
            if (ivBytes == null || ivBytes.length == 0) {
                throw new IllegalStateException("Initialization vector generation is enabled - generated vector" +
                        "cannot be null or empty.");
            }
        }
        return encrypt(plaintext, key, ivBytes, generate);
    }

    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);
    }

    public ByteSource decrypt(byte[] ciphertext, byte[] key) throws CryptoException {

        byte[] encrypted = ciphertext;

        //No IV, check if we need to read the IV from the stream:
        byte[] iv = null;

        if (isGenerateInitializationVectors(false)) {
            try {
                //We are generating IVs, so the ciphertext argument array is not actually 100% cipher text.  Instead, it
                //is:
                // - the first N bytes is the initialization vector, where N equals the value of the
                // 'initializationVectorSize' attribute.
                // - the remaining bytes in the method argument (arg.length - N) is the real cipher text.

                //So we need to chunk the method argument into its constituent parts to find the IV and then use
                //the IV to decrypt the real ciphertext:

                int ivSize = getInitializationVectorSize();
                int ivByteSize = ivSize / BITS_PER_BYTE;

                //now we know how large the iv is, so extract the iv bytes:
                iv = new byte[ivByteSize];
                System.arraycopy(ciphertext, 0, iv, 0, ivByteSize);

                //remaining data is the actual encrypted ciphertext.  Isolate it:
                int encryptedSize = ciphertext.length - ivByteSize;
                encrypted = new byte[encryptedSize];
                System.arraycopy(ciphertext, ivByteSize, encrypted, 0, encryptedSize);
            } catch (Exception e) {
                String msg = "Unable to correctly extract the Initialization Vector or ciphertext.";
                throw new CryptoException(msg, e);
            }
        }

        return decrypt(encrypted, key, iv);
    }

    private ByteSource decrypt(byte[] ciphertext, byte[] key, byte[] iv) throws CryptoException {
        if (log.isTraceEnabled()) {
            log.trace("Attempting to decrypt incoming byte array of length " +
                    (ciphertext != null ? ciphertext.length : 0));
        }
        byte[] decrypted = crypt(ciphertext, key, iv, javax.crypto.Cipher.DECRYPT_MODE);
        return decrypted == null ? null : ByteSource.Util.bytes(decrypted);
    }

    /**
     * Returns a new {@link javax.crypto.Cipher Cipher} instance to use for encryption/decryption operations.  The
     * Cipher's {@code transformationString} for the {@code Cipher}.{@link javax.crypto.Cipher#getInstance getInstance}
     * call is obtaind via the {@link #getTransformationString(boolean) getTransformationString} method.
     *
     * @param streaming {@code true} if the cipher instance will be used as a stream cipher, {@code false} if it will be
     *                  used as a block cipher.
     * @return a new JDK {@code Cipher} instance.
     * @throws CryptoException if a new Cipher instance cannot be constructed based on the
     *                         {@link #getTransformationString(boolean) getTransformationString} value.
     */
    private javax.crypto.Cipher newCipherInstance(boolean streaming) throws CryptoException {
        String transformationString = getTransformationString(streaming);
        try {
            return javax.crypto.Cipher.getInstance(transformationString);
        } catch (Exception e) {
            String msg = "Unable to acquire a Java JCA Cipher instance using " +
                    javax.crypto.Cipher.class.getName() + ".getInstance( \"" + transformationString + "\" ). " +
                    getAlgorithmName() + " under this configuration is required for the " +
                    getClass().getName() + " instance to function.";
            throw new CryptoException(msg, e);
        }
    }

    /**
     * Functions as follows:
     * <ol>
     * <li>Creates a {@link #newCipherInstance(boolean) new JDK cipher instance}</li>
     * <li>Converts the specified key bytes into an {@link #getAlgorithmName() algorithm}-compatible JDK
     * {@link Key key} instance</li>
     * <li>{@link #init(javax.crypto.Cipher, int, java.security.Key, AlgorithmParameterSpec, SecureRandom) Initializes}
     * the JDK cipher instance with the JDK key</li>
     * <li>Calls the {@link #crypt(javax.crypto.Cipher, byte[]) crypt(cipher,bytes)} method to either encrypt or
     * decrypt the data based on the specified Cipher behavior mode
     * ({@link javax.crypto.Cipher#ENCRYPT_MODE Cipher.ENCRYPT_MODE} or
     * {@link javax.crypto.Cipher#DECRYPT_MODE Cipher.DECRYPT_MODE})</li>
     * </ol>
     *
     * @param bytes the bytes to crypt
     * @param key   the key to use to perform the encryption or decryption.
     * @param iv    the initialization vector to use for the crypt operation (optional, may be {@code null}).
     * @param mode  the JDK Cipher behavior mode (Cipher.ENCRYPT_MODE or Cipher.DECRYPT_MODE).
     * @return the resulting crypted byte array
     * @throws IllegalArgumentException if {@code bytes} are null or empty.
     * @throws CryptoException          if Cipher initialization or the crypt operation fails
     */
    private byte[] crypt(byte[] bytes, byte[] key, byte[] iv, int mode) throws IllegalArgumentException, CryptoException {
        if (key == null || key.length == 0) {
            throw new IllegalArgumentException("key argument cannot be null or empty.");
        }
        javax.crypto.Cipher cipher = initNewCipher(mode, key, iv, false);
        return crypt(cipher, bytes);
    }

    /**
     * Calls the {@link javax.crypto.Cipher#doFinal(byte[]) doFinal(bytes)} method, propagating any exception that
     * might arise in an {@link CryptoException}
     *
     * @param cipher the JDK Cipher to finalize (perform the actual cryption)
     * @param bytes  the bytes to crypt
     * @return the resulting crypted byte array.
     * @throws CryptoException if there is an illegal block size or bad padding
     */
    private byte[] crypt(javax.crypto.Cipher cipher, byte[] bytes) throws CryptoException {
        try {
            return cipher.doFinal(bytes);
        } catch (Exception e) {
            String msg = "Unable to execute 'doFinal' with cipher instance [" + cipher + "].";
            throw new CryptoException(msg, 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
     */
    private void init(javax.crypto.Cipher cipher, int mode, java.security.Key key,
                      AlgorithmParameterSpec spec, SecureRandom random) throws CryptoException {
        try {
            if (random != null) {
                if (spec != null) {
                    cipher.init(mode, key, spec, random);
                } else {
                    cipher.init(mode, key, random);
                }
            } else {
                if (spec != null) {
                    cipher.init(mode, key, spec);
                } else {
                    cipher.init(mode, key);
                }
            }
        } catch (Exception e) {
            String msg = "Unable to init cipher instance.";
            throw new CryptoException(msg, e);
        }
    }


    public void encrypt(InputStream in, OutputStream out, byte[] key) throws CryptoException {
        byte[] iv = null;
        boolean generate = isGenerateInitializationVectors(true);
        if (generate) {
            iv = generateInitializationVector(true);
            if (iv == null || iv.length == 0) {
                throw new IllegalStateException("Initialization vector generation is enabled - generated vector" +
                        "cannot be null or empty.");
            }
        }
        encrypt(in, out, key, iv, generate);
    }

    private void encrypt(InputStream in, OutputStream out, byte[] key, byte[] iv, boolean prependIv) throws CryptoException {
        if (prependIv && iv != null && iv.length > 0) {
            try {
                //first write the IV:
                out.write(iv);
            } catch (IOException e) {
                throw new CryptoException(e);
            }
        }

        crypt(in, out, key, iv, javax.crypto.Cipher.ENCRYPT_MODE);
    }

    public void decrypt(InputStream in, OutputStream out, byte[] key) throws CryptoException {
        decrypt(in, out, key, isGenerateInitializationVectors(true));
    }

    private void decrypt(InputStream in, OutputStream out, byte[] key, boolean ivPrepended) throws CryptoException {

        byte[] iv = null;
        //No Initialization Vector provided as a method argument - check if we need to read the IV from the stream:
        if (ivPrepended) {
            //we are generating IVs, so we need to read the previously-generated IV from the stream before
            //we decrypt the rest of the stream (we need the IV to decrypt):
            int ivSize = getInitializationVectorSize();
            int ivByteSize = ivSize / BITS_PER_BYTE;
            iv = new byte[ivByteSize];
            int read;

            try {
                read = in.read(iv);
            } catch (IOException e) {
                String msg = "Unable to correctly read the Initialization Vector from the input stream.";
                throw new CryptoException(msg, e);
            }

            if (read != ivByteSize) {
                throw new CryptoException("Unable to read initialization vector bytes from the InputStream.  " +
                        "This is required when initialization vectors are autogenerated during an encryption " +
                        "operation.");
            }
        }

        decrypt(in, out, key, iv);
    }

    private void decrypt(InputStream in, OutputStream out, byte[] decryptionKey, byte[] iv) throws CryptoException {
        crypt(in, out, decryptionKey, iv, javax.crypto.Cipher.DECRYPT_MODE);
    }

    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);
        }
    }

    private javax.crypto.Cipher initNewCipher(int jcaCipherMode, byte[] key, byte[] iv, boolean streaming)
            throws CryptoException {

        javax.crypto.Cipher cipher = newCipherInstance(streaming);
        java.security.Key jdkKey = new SecretKeySpec(key, getAlgorithmName());
        AlgorithmParameterSpec ivSpec = null;

        if (iv != null && iv.length > 0) {
            ivSpec = createParameterSpec(iv, streaming);
        }

        init(cipher, jcaCipherMode, jdkKey, ivSpec, getSecureRandom());

        return cipher;
    }

    protected AlgorithmParameterSpec createParameterSpec(byte[] iv, boolean streaming) {
        return new IvParameterSpec(iv);
    }
}
