From e4c66080a8d7e3a329258498b35e8fc55eea5130 Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Mon, 07 Sep 2015 03:47:16 -0400
Subject: [PATCH] Improved encrypt/decrypt methods with option to choose the cipher_method (#1489719)
---
program/lib/Roundcube/rcube.php | 27 ++++---------
CHANGELOG | 1
installer/config.php | 3 -
program/lib/Roundcube/rcube_config.php | 25 +++++++-----
config/defaults.inc.php | 11 ++++-
5 files changed, 34 insertions(+), 33 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 6a14ab8..f97f1fd 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 a3b7b53..45d2c7b 100644
--- a/config/defaults.inc.php
+++ b/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
diff --git a/installer/config.php b/installer/config.php
index 4882c1d..588e14d 100644
--- a/installer/config.php
+++ b/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>
diff --git a/program/lib/Roundcube/rcube.php b/program/lib/Roundcube/rcube.php
index 4d80dc0..37b5a3a 100644
--- a/program/lib/Roundcube/rcube.php
+++ b/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;
}
diff --git a/program/lib/Roundcube/rcube_config.php b/program/lib/Roundcube/rcube_config.php
index 3dd54e3..799552f 100644
--- a/program/lib/Roundcube/rcube_config.php
+++ b/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;
}
/**
--
Gitblit v1.9.1