diff --git a/CHANGELOG b/CHANGELOG index 6a14ab87e..f97f1fdf0 100644 --- a/CHANGELOG +++ b/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) diff --git a/config/defaults.inc.php b/config/defaults.inc.php index a3b7b5380..45d2c7ba3 100644 --- a/config/defaults.inc.php +++ b/config/defaults.inc.php @@ -446,11 +446,16 @@ $config['referer_check'] = false; // 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 diff --git a/installer/config.php b/installer/config.php index 4882c1d93..588e14d1f 100644 --- a/installer/config.php +++ b/installer/config.php @@ -128,8 +128,7 @@ echo $input_deskey->show($RCI->getprop('des_key')); ?>
This key is used to encrypt the users imap password before storing in the session record
-

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.

+

It's a random generated string to ensure that every installation has its own key.

ip_check
diff --git a/program/lib/Roundcube/rcube.php b/program/lib/Roundcube/rcube.php index 4d80dc0a0..37b5a3af0 100644 --- a/program/lib/Roundcube/rcube.php +++ b/program/lib/Roundcube/rcube.php @@ -810,26 +810,22 @@ class rcube } /** - * 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 @@ class rcube } /** - * 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 @@ class rcube 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); @@ -868,10 +863,6 @@ class rcube $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; } diff --git a/program/lib/Roundcube/rcube_config.php b/program/lib/Roundcube/rcube_config.php index 3dd54e307..799552fdf 100644 --- a/program/lib/Roundcube/rcube_config.php +++ b/program/lib/Roundcube/rcube_config.php @@ -505,7 +505,7 @@ class rcube_config 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 @@ class rcube_config ), 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; } /**