Aleksander Machniak
2015-09-07 e4c66080a8d7e3a329258498b35e8fc55eea5130
Improved encrypt/decrypt methods with option to choose the cipher_method (#1489719)
5 files modified
67 ■■■■ changed files
CHANGELOG 1 ●●●● patch | view | raw | blame | history
config/defaults.inc.php 11 ●●●● patch | view | raw | blame | history
installer/config.php 3 ●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube.php 27 ●●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_config.php 25 ●●●●● patch | view | raw | blame | history
CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
- Improved encrypt/decrypt methods with option to choose the cipher_method (#1489719)
- Make optional adding of standard signature separator - sig_separator (#1487768)
- Optimize folder_size() on Cyrus IMAP by using special folder annotation (#1490514)
- Make optional hidding of folders with name starting with a dot - imap_skip_hidden_folders (#1490468)
config/defaults.inc.php
@@ -446,11 +446,16 @@
// Possible values: sameorigin|deny. Set to false in order to disable sending them
$config['x_frame_options'] = 'sameorigin';
// this key is used to encrypt the users imap password which is stored
// in the session record (and the client cookie if remember password is enabled).
// please provide a string of exactly 24 chars.
// This key is used for encrypting purposes, like storing of imap password
// in the session. For historical reasons it's called DES_key, but it's used
// with any configured cipher_method (see below).
$config['des_key'] = 'rcmail-!24ByteDESkey*Str';
// Encryption algorithm. You can use any method supported by openssl.
// Default is set for backward compatibility to DES-EDE3-CBC,
// but you can choose e.g. AES-256-CBC which we consider a better choice.
$config['cipher_method'] = 'DES-EDE3-CBC';
// Automatically add this domain to user names for login
// Only for IMAP servers that require full e-mail addresses for login
// Specify an array with 'host' => 'domain' values to support multiple hosts
installer/config.php
@@ -128,8 +128,7 @@
?>
<div>This key is used to encrypt the users imap password before storing in the session record</div>
<p class="hint">It's a random generated string to ensure that every installation has its own key.
If you enter it manually please provide a string of exactly 24 chars.</p>
<p class="hint">It's a random generated string to ensure that every installation has its own key.</p>
</dd>
<dt class="propname">ip_check</dt>
program/lib/Roundcube/rcube.php
@@ -810,26 +810,22 @@
    }
    /**
     * Encrypt using 3DES
     * Encrypt a string
     *
     * @param string  $clear  Clear text input
     * @param string  $key    Encryption key to retrieve from the configuration, defaults to 'des_key'
     * @param boolean $base64 Whether or not to base64_encode() the result before returning
     *
     * @return string encrypted text
     * @return string Encrypted text
     */
    public function encrypt($clear, $key = 'des_key', $base64 = true)
    {
        if (!$clear) {
        if (!is_string($clear) || !strlen($clear)) {
            return '';
        }
        // Add a single canary byte to the end of the clear text, which
        // will help find out how much of padding will need to be removed
        // upon decryption; see http://php.net/mcrypt_generic#68082.
        $clear  = pack("a*H2", $clear, "80");
        $ckey   = $this->config->get_crypto_key($key);
        $method = 'DES-EDE3-CBC';
        $method = $this->config->get_crypto_method();
        $opts   = defined('OPENSSL_RAW_DATA') ? OPENSSL_RAW_DATA : true;
        $iv     = rcube_utils::random_bytes(openssl_cipher_iv_length($method), true);
        $cipher = $iv . openssl_encrypt($clear, $method, $ckey, $opts, $iv);
@@ -838,13 +834,13 @@
    }
    /**
     * Decrypt 3DES-encrypted string
     * Decrypt a string
     *
     * @param string  $cipher Encrypted text
     * @param string  $key    Encryption key to retrieve from the configuration, defaults to 'des_key'
     * @param boolean $base64 Whether or not input is base64-encoded
     *
     * @return string decrypted text
     * @return string Decrypted text
     */
    public function decrypt($cipher, $key = 'des_key', $base64 = true)
    {
@@ -852,10 +848,9 @@
            return '';
        }
        $cipher = $base64 ? base64_decode($cipher) : $cipher;
        $ckey   = $this->config->get_crypto_key($key);
        $method  = 'DES-EDE3-CBC';
        $cipher  = $base64 ? base64_decode($cipher) : $cipher;
        $ckey    = $this->config->get_crypto_key($key);
        $method  = $this->config->get_crypto_method();
        $opts    = defined('OPENSSL_RAW_DATA') ? OPENSSL_RAW_DATA : true;
        $iv_size = openssl_cipher_iv_length($method);
        $iv      = substr($cipher, 0, $iv_size);
@@ -867,10 +862,6 @@
        $cipher = substr($cipher, $iv_size);
        $clear  = openssl_decrypt($cipher, $method, $ckey, $opts, $iv);
        // Trim PHP's padding and the canary byte; see note in
        // rcube::encrypt() and http://php.net/mcrypt_generic#68082
        $clear = substr(rtrim($clear, "\0"), 0, -1);
        return $clear;
    }
program/lib/Roundcube/rcube_config.php
@@ -505,7 +505,7 @@
    public function get_crypto_key($key)
    {
        // Bomb out if the requested key does not exist
        if (!array_key_exists($key, $this->prop)) {
        if (!array_key_exists($key, $this->prop) || empty($this->prop[$key])) {
            rcube::raise_error(array(
                'code' => 500, 'type' => 'php',
                'file' => __FILE__, 'line' => __LINE__,
@@ -513,18 +513,23 @@
            ), true, true);
        }
        $key = $this->prop[$key];
        return $this->prop[$key];
    }
        // Bomb out if the configured key is not exactly 24 bytes long
        if (strlen($key) != 24) {
            rcube::raise_error(array(
                'code' => 500, 'type' => 'php',
                'file' => __FILE__, 'line' => __LINE__,
                'message' => "Configured crypto key '$key' is not exactly 24 bytes long"
            ), true, true);
    /**
     * Return configured crypto method.
     *
     * @return string Crypto method
     */
    public function get_crypto_method()
    {
        $method = $this->get('cipher_method');
        if (empty($method)) {
            $method = 'DES-EDE3-CBC';
        }
        return $key;
        return $method;
    }
    /**