<?php

/**
 * Lifestyle Webconsulting GmbH
 *
 * LICENSE: This Software is the property of Lifestyle Webconsulting GmbH (Aschaffenburg, Germany)
 * and is private by copyright law - it is NOT Freeware.
 *
 * Any unauthorized use of this software without a valid license
 * is a violation of the license agreement and will be prosecuted by
 * civil and criminal law.
 *
 * @copyright  2019 Lifestyle Webconsulting GmbH
 * @link       https://www.life-style.de
 */

namespace SimpleSAML\Module\lifestyle\Webservice\Api\Configuration;

use SimpleSAML\Configuration;

/**
 * Class Cyphering
 *
 * @copyright  2019 Lifestyle Webconsulting GmbH
 * @link       https://www.life-style.de
 * @package SimpleSAML\Module\lifestyle\Webservice\Api\Configuration
 */
class Cyphering
{
    /**
     * loaded from configuration
     * @var string
     */
    private $openSslCipherName;

    /**
     * random generated string
     * @var string
     */
    private $openSslInitializationVector;

    /**
     * loaded from configuration
     * @var string
     */
    private $mcryptCipherName;

    /**
     * loaded from configuration
     * @var string
     */
    private $mcryptModeName;

    /**
     * random generated string
     * @var string
     */
    private $mcryptitializationVector;

    /**
     * @var string
     */
    private $mcryptAdditionalKey;

    /**
     * \SimpleSAML\Module\lifestyle\Webservice\Api\Configuration\Cyphering constructor.
     * @param Configuration $configuration
     * @throws Exception
     */
    public function __construct(Configuration $configuration)
    {
        $config = $configuration->getArray('webservice.cyphering', array());

        /* Make sure that all required configuration params are present. */
        foreach (array('openSslCipherName', 'mcryptCipherName', 'mcryptModeName', 'mcryptAdditionalKey') as $param) {
            if (!array_key_exists($param, $config)) {
                throw new Exception(sprintf('Missing required configuration webservice.cyphering[%s] for webservice encryption.', $param));
            }

            if (!is_string($config[$param])) {
                throw new Exception(sprintf('Expected configuration paramter webservice.cyphering[%s] for webservice encryption is not a string. Instead it was: %s', $param, var_export($config[$param], true)));
            }

            $this->$param = $config[$param];
        }
    }

    /**
     * @return string
     */
    public function getMcryptCipherName()
    {
        return $this->mcryptCipherName;
    }

    /**
     * @return string
     */
    public function getOpenSslCipherName()
    {
        return $this->openSslCipherName;
    }

    /**
     * @return string
     */
    public function getOpenSslInitializationVector()
    {
        return null !== $this->openSslInitializationVector ? $this->openSslInitializationVector : ($this->openSslInitializationVector = openssl_random_pseudo_bytes(openssl_cipher_iv_length($this->openSslCipherName)));
    }

    /**
     * @return string
     */
    public function getMcryptModeName()
    {
        return $this->mcryptModeName;
    }

    /**
     * @return string
     */
    public function getMcryptitializationVector()
    {
        return null !== $this->mcryptitializationVector ? $this->mcryptitializationVector : ($this->mcryptitializationVector = mcrypt_create_iv(mcrypt_get_iv_size(constant($this->mcryptCipherName), constant($this->mcryptModeName)), MCRYPT_DEV_URANDOM));
    }

    /**
     * @return string
     */
    public function getMcryptAdditionalKey()
    {
        return $this->mcryptAdditionalKey;
    }

    /**
     * @param $flexKey
     * @param bool|false $addKey
     * @return string
     */
    public function keyMixer($flexKey, $addKey = false)
    {
        $tempKeyFixedArray = str_split(false !== $addKey ? $addKey : $this->mcryptAdditionalKey);
        $tempKeyStaticArray = str_split($flexKey);
        $mixedKey = "";
        $i = 0;
        foreach ($tempKeyFixedArray as $char) {

            if (isset($tempKeyStaticArray[$i])) {
                $charAdd = $tempKeyStaticArray[$i] . $char;
            } else {
                $charAdd = $char;
            }

            if ($i % 2 != 0) {
                $mixedKey = $mixedKey . $charAdd;
            }

            // Some code additions
            if (($i * 2) == 42) {
                $mixedKey = $mixedKey . "o&s";
            }
            $i++;
        }
        return $mixedKey;
    }
}
