/*
 *
 * 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.qpid.client.message;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.jms.JMSException;
import javax.security.auth.x500.X500Principal;

import org.apache.qpid.client.AMQSession;
import org.apache.qpid.transport.ConnectionSettings;

public class MessageEncryptionHelper
{
    public static final String ENCRYPTION_ALGORITHM_PROPERTY = "x-qpid-encryption-algorithm";
    public static final String KEY_INIT_VECTOR_PROPERTY = "x-qpid-key-init-vector";
    public static final String ENCRYPTED_KEYS_PROPERTY = "x-qpid-encrypted-keys";
    public static final String ENCRYPT_HEADER = "x-qpid-encrypt";
    public static final String ENCRYPT_RECIPIENTS_HEADER = "x-qpid-encrypt-recipients";
    public static final String UNENCRYPTED_PROPERTIES_HEADER = "x-qpid-unencrypted-properties";
    static final int AES_KEY_SIZE_BITS = 256;
    public static final int AES_KEY_SIZE_BYTES = AES_KEY_SIZE_BITS / 8;
    public static final String AES_ALGORITHM = "AES";
    public static final String DEFAULT_MESSAGE_ENCRYPTION_CIPHER_NAME = "AES/CBC/PKCS5Padding";
    public static final int AES_INITIALIZATION_VECTOR_LENGTH = 16;
    private final AMQSession<?, ?> _session;

    private static final int KEY_TRANSPORT_RECIPIENT_INFO_TYPE = 1;
    public static final String DEFAULT_KEY_ENCRYPTION_ALGORITHM = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";


    private final Map<String, X509Certificate> _signingCertificateCache =
            Collections.synchronizedMap(new LinkedHashMap<String, X509Certificate>(16,0.75f,true)
                                        {
                                            @Override
                                            protected boolean removeEldestEntry(final Map.Entry<String, X509Certificate> eldest)
                                            {
                                                return size() > 128;
                                            }
                                        });

    private String _keyEncryptionAlgorithm = DEFAULT_KEY_ENCRYPTION_ALGORITHM;
    private String _messageEncryptionCipherName = DEFAULT_MESSAGE_ENCRYPTION_CIPHER_NAME;

    public MessageEncryptionHelper(final AMQSession<?, ?> session)
    {
        _session = session;
    }

    public String getKeyEncryptionAlgorithm()
    {
        return _keyEncryptionAlgorithm;
    }

    public void setKeyEncryptionAlgorithm(final String keyEncryptionAlgorithm)
    {
        _keyEncryptionAlgorithm = keyEncryptionAlgorithm;
    }

    public String getMessageEncryptionCipherName()
    {
        return _messageEncryptionCipherName;
    }

    public void setMessageEncryptionCipherName(final String messageEncryptionCipherName)
    {
        _messageEncryptionCipherName = messageEncryptionCipherName;
    }

    public KeyStore getSigningCertificateStore() throws GeneralSecurityException, IOException
    {
        return _session.getAMQConnection().getConnectionSettings().getEncryptionTrustStore(new ConnectionSettings.RemoteStoreFinder()
        {
            @Override
            public KeyStore getKeyStore(final String name) throws GeneralSecurityException, IOException
            {
                try
                {
                    return _session.getAMQConnection().getBrokerSuppliedTrustStore(name);
                }
                catch (JMSException e)
                {
                    throw new CertificateException("Could not load remote certificate store: '" + name  + "'", e);
                }
            }
        });

    }

    public interface KeyTransportRecipientInfo
    {
        int getType();
        String getKeyEncryptionAlgorithm();
        String getCertIssuerPrincipal();
        String getCertSerialNumber();
        byte[] getEncryptedKey();

        List<Object> asList();
    }

    public List<KeyTransportRecipientInfo> getKeyTransportRecipientInfo(List<String> recipients, SecretKeySpec secretKey)
        throws GeneralSecurityException, IOException
    {
        List<KeyTransportRecipientInfo> result = new ArrayList<>();
        final String keyEncryptionAlgorithm = getKeyEncryptionAlgorithm();
        for(String recipient : recipients)
        {
            X509Certificate cert = getSigningCertificate(recipient.trim());
            if(cert != null)
            {

                Cipher cipher = Cipher.getInstance(keyEncryptionAlgorithm);
                cipher.init(Cipher.ENCRYPT_MODE, cert.getPublicKey());
                final byte[] encryptedKey = cipher.doFinal(secretKey.getEncoded());

                final String issuePrincipal = cert.getIssuerX500Principal().getName(X500Principal.CANONICAL);
                final String serialNumber = cert.getSerialNumber().toString();

                result.add(new KeyTransportRecipientInfoImpl(keyEncryptionAlgorithm,
                                                             issuePrincipal,
                                                             serialNumber,
                                                             encryptedKey));

            }
            else
            {
                throw new CertificateException("Unable to find certificate for recipient '" + recipient +"'");
            }
        }
        return result;
    }

    public X509Certificate getSigningCertificate(final String name)
            throws GeneralSecurityException, IOException
    {
        X509Certificate returnVal = _signingCertificateCache.get(name);
        if(returnVal == null)
        {
            KeyStore certStore = getSigningCertificateStore();
            X500Principal requestedPrincipal;
            List<X509Certificate> potentialCerts = new ArrayList<>();
            try
            {
                requestedPrincipal = new X500Principal(name);
            }
            catch (IllegalArgumentException e)
            {
                requestedPrincipal = null;
            }

            for (String alias : Collections.list(certStore.aliases()))
            {
                Certificate cert = certStore.getCertificate(alias);
                if (cert instanceof X509Certificate)
                {
                    X509Certificate x509Cert = (X509Certificate) cert;
                    if (requestedPrincipal != null
                        && requestedPrincipal.equals(x509Cert.getSubjectX500Principal()))
                    {
                        potentialCerts.add(x509Cert);
                    }
                    else if (x509Cert.getSubjectAlternativeNames() != null)
                    {
                        for (List<?> entry : x509Cert.getSubjectAlternativeNames())
                        {
                            final int type = (Integer) entry.get(0);
                            if ((type == 1 || type == 2) && (entry.get(1).toString().trim().equals(name)))
                            {
                                potentialCerts.add(x509Cert);
                                break;
                            }
                        }
                    }


                }
            }

            for (X509Certificate cert : potentialCerts)
            {
                try
                {
                    cert.checkValidity();
                    if (returnVal == null || returnVal.getNotAfter().getTime() > cert.getNotAfter().getTime())
                    {
                        returnVal = cert;
                    }
                }
                catch (CertificateExpiredException | CertificateNotYetValidException e)
                {
                    // ignore the invalid cert
                }
            }
            if(returnVal != null)
            {
                _signingCertificateCache.put(name, returnVal);
            }
        }
        return returnVal;
    }

    public PrivateKey getEncryptionPrivateKey(final X500Principal issuer,
                                              final BigInteger serialNumber)
            throws GeneralSecurityException, IOException
    {

        final ConnectionSettings connectionSettings = _session.getAMQConnection().getConnectionSettings();
        KeyStore keyStore = connectionSettings.getEncryptionKeyStore();
        if(keyStore != null)
        {
            for (String alias : Collections.list(keyStore.aliases()))
            {
                try
                {

                    final KeyStore.Entry entry = keyStore.getEntry(alias,
                                                                   new KeyStore.PasswordProtection(connectionSettings.getEncryptionKeyStorePassword()
                                                                                                           .toCharArray()));
                    if (entry instanceof KeyStore.PrivateKeyEntry)
                    {
                        KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) entry;
                        if (pkEntry.getCertificate() instanceof X509Certificate)
                        {
                            X509Certificate cert = (X509Certificate) pkEntry.getCertificate();
                            if (cert.getIssuerX500Principal().equals(issuer) && cert.getSerialNumber()
                                    .equals(serialNumber))
                            {
                                return pkEntry.getPrivateKey();
                            }
                        }
                    }
                }
                catch (UnsupportedOperationException e)
                {
                    // ignore
                }
            }
        }
        return null;
    }

    private SecureRandom _random;

    public SecretKeySpec createSecretKey()
    {
        byte[] key = new byte[AES_KEY_SIZE_BYTES];
        getRandomBytes(key);
        return new SecretKeySpec(key, AES_ALGORITHM);
    }

    private void getRandomBytes(final byte[] key)
    {
        synchronized (this)
        {

            if(_random == null)
            {
                _random = new SecureRandom();
            }
            _random.nextBytes(key);
        }
    }

    public byte[] getInitialisationVector()
    {
        byte[] ivbytes = new byte[AES_INITIALIZATION_VECTOR_LENGTH];
        getRandomBytes(ivbytes);
        return ivbytes;
    }

    public byte[] readFromCipherStream(final byte[] unencryptedBytes, int offset, int length, final Cipher cipher)
            throws IOException
    {
        final byte[] encryptedBytes;
        try (CipherInputStream cipherInputStream = new CipherInputStream(new ByteArrayInputStream(unencryptedBytes,
                                                                                                  offset,
                                                                                                  length), cipher))
        {
            byte[] buf = new byte[512];
            int pos = 0;
            int read;
            while ((read = cipherInputStream.read(buf, pos, buf.length - pos)) != -1)
            {
                pos += read;
                if (pos == buf.length)
                {
                    byte[] tmp = buf;
                    buf = new byte[buf.length + 512];
                    System.arraycopy(tmp, 0, buf, 0, tmp.length);
                }
            }
            encryptedBytes = new byte[pos];
            System.arraycopy(buf, 0, encryptedBytes, 0, pos);
        }
        return encryptedBytes;
    }

    public byte[] readFromCipherStream(final byte[] unencryptedBytes, final Cipher cipher, final AMQSession amqSession) throws IOException
    {
        return readFromCipherStream(unencryptedBytes, 0, unencryptedBytes.length, cipher);
    }

    public byte[] encrypt(SecretKeySpec secretKey,
                          final byte[] unencryptedBytes,
                          byte[] ivbytes)
    {
        try
        {
            Cipher cipher = Cipher.getInstance(getMessageEncryptionCipherName());
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(ivbytes));
            return readFromCipherStream(unencryptedBytes, cipher, _session);
        }
        catch (IOException | InvalidAlgorithmParameterException | InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException e)
        {
            throw new IllegalArgumentException("Unable to encrypt secret with secret key. Cipher: "
                                               + getMessageEncryptionCipherName()
                                               + " . Key of type " + secretKey.getAlgorithm()
                                               + " size " + secretKey.getEncoded().length, e);
        }
    }

    private static class KeyTransportRecipientInfoImpl implements KeyTransportRecipientInfo
    {
        private final String _keyEncryptionAlgorithm;
        private final String _issuePrincipal;
        private final String _serialNumber;
        private final byte[] _encryptedKey;

        public KeyTransportRecipientInfoImpl(final String keyEncryptionAlgorithm,
                                             final String issuePrincipal,
                                             final String serialNumber,
                                             final byte[] encryptedKey)
        {
            _keyEncryptionAlgorithm = keyEncryptionAlgorithm;
            _issuePrincipal = issuePrincipal;
            _serialNumber = serialNumber;
            _encryptedKey = encryptedKey;
        }

        @Override
        public int getType()
        {
            return KEY_TRANSPORT_RECIPIENT_INFO_TYPE;
        }

        @Override
        public String getKeyEncryptionAlgorithm()
        {
            return _keyEncryptionAlgorithm;
        }

        @Override
        public String getCertIssuerPrincipal()
        {
            return _issuePrincipal;
        }

        @Override
        public String getCertSerialNumber()
        {
            return _serialNumber;
        }

        @Override
        public byte[] getEncryptedKey()
        {
            return _encryptedKey;
        }

        @Override
        public List<Object> asList()
        {
            List<Object> result = new ArrayList<>();

            result.add(KEY_TRANSPORT_RECIPIENT_INFO_TYPE);
            result.add(_keyEncryptionAlgorithm);
            result.add(_issuePrincipal);
            result.add(_serialNumber);
            result.add(_encryptedKey);
            return result;
        }
    }
}
