From 50569114acdc64e7c7cae1498635d3f821517c30 Mon Sep 17 00:00:00 2001 From: Daniel Lange Date: Mon, 7 Mar 2016 15:53:16 +0100 Subject: Initial commit of the Faster IT roundcube_calendar plugin distribution This includes: * Kolab plugins 3.2.9 (calendar and libcalendaring) * CalDAV driver 3.2.8 * .htaccess files for at least some security * SabreDAV updated to 1.8.12 (Jan 2015 release) * Support for CURLOPT_SSL_* settings to allow self-signed certificates * Small fixes & improved documentation --- calendar/lib/encryption.php | 166 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 calendar/lib/encryption.php (limited to 'calendar/lib/encryption.php') diff --git a/calendar/lib/encryption.php b/calendar/lib/encryption.php new file mode 100644 index 0000000..c503109 --- /dev/null +++ b/calendar/lib/encryption.php @@ -0,0 +1,166 @@ +cipher = $cipher; + $this->mode = $mode; + $this->rounds = (int) $rounds; + } + + /** + * Decrypt the data with the provided key + * + * @param string $data The encrypted datat to decrypt + * @param string $key The key to use for decryption + * + * @returns string|false The returned string if decryption is successful + * false if it is not + */ + public function decrypt($data, $key) { + $salt = substr($data, 0, 128); + $enc = substr($data, 128, -64); + $mac = substr($data, -64); + + list ($cipherKey, $macKey, $iv) = $this->getKeys($salt, $key); + + if ($mac !== hash_hmac('sha512', $enc, $macKey, true)) { + return false; + } + + $dec = mcrypt_decrypt($this->cipher, $cipherKey, $enc, $this->mode, $iv); + + $data = $this->unpad($dec); + + return $data; + } + + /** + * Encrypt the supplied data using the supplied key + * + * @param string $data The data to encrypt + * @param string $key The key to encrypt with + * + * @returns string The encrypted data + */ + public function encrypt($data, $key) { + $salt = mcrypt_create_iv(128, MCRYPT_DEV_URANDOM); + list ($cipherKey, $macKey, $iv) = $this->getKeys($salt, $key); + + $data = $this->pad($data); + + $enc = mcrypt_encrypt($this->cipher, $cipherKey, $data, $this->mode, $iv); + + $mac = hash_hmac('sha512', $enc, $macKey, true); + return $salt . $enc . $mac; + } + + /** + * Generates a set of keys given a random salt and a master key + * + * @param string $salt A random string to change the keys each encryption + * @param string $key The supplied key to encrypt with + * + * @returns array An array of keys (a cipher key, a mac key, and a IV) + */ + protected function getKeys($salt, $key) { + $ivSize = mcrypt_get_iv_size($this->cipher, $this->mode); + $keySize = mcrypt_get_key_size($this->cipher, $this->mode); + $length = 2 * $keySize + $ivSize; + + $key = $this->pbkdf2('sha512', $key, $salt, $this->rounds, $length); + + $cipherKey = substr($key, 0, $keySize); + $macKey = substr($key, $keySize, $keySize); + $iv = substr($key, 2 * $keySize); + return array($cipherKey, $macKey, $iv); + } + + /** + * Stretch the key using the PBKDF2 algorithm + * + * @see http://en.wikipedia.org/wiki/PBKDF2 + * + * @param string $algo The algorithm to use + * @param string $key The key to stretch + * @param string $salt A random salt + * @param int $rounds The number of rounds to derive + * @param int $length The length of the output key + * + * @returns string The derived key. + */ + protected function pbkdf2($algo, $key, $salt, $rounds, $length) { + $size = strlen(hash($algo, '', true)); + $len = ceil($length / $size); + $result = ''; + for ($i = 1; $i <= $len; $i++) { + $tmp = hash_hmac($algo, $salt . pack('N', $i), $key, true); + $res = $tmp; + for ($j = 1; $j < $rounds; $j++) { + $tmp = hash_hmac($algo, $tmp, $key, true); + $res ^= $tmp; + } + $result .= $res; + } + return substr($result, 0, $length); + } + + protected function pad($data) { + $length = mcrypt_get_block_size($this->cipher, $this->mode); + $padAmount = $length - strlen($data) % $length; + if ($padAmount == 0) { + $padAmount = $length; + } + return $data . str_repeat(chr($padAmount), $padAmount); + } + + protected function unpad($data) { + $length = mcrypt_get_block_size($this->cipher, $this->mode); + $last = ord($data[strlen($data) - 1]); + if ($last > $length) return false; + if (substr($data, -1 * $last) !== str_repeat(chr($last), $last)) { + return false; + } + return substr($data, 0, -1 * $last); + } +} +?> -- cgit v1.2.3