Initial Horde 4 import of Horde_Secret.
authorMichael M Slusarz <slusarz@curecanti.org>
Thu, 11 Dec 2008 22:13:33 +0000 (15:13 -0700)
committerMichael M Slusarz <slusarz@curecanti.org>
Thu, 11 Dec 2008 22:13:33 +0000 (15:13 -0700)
framework/Secret/lib/Horde/Secret.php [new file with mode: 0644]
framework/Secret/package.xml [new file with mode: 0644]

diff --git a/framework/Secret/lib/Horde/Secret.php b/framework/Secret/lib/Horde/Secret.php
new file mode 100644 (file)
index 0000000..ebcb674
--- /dev/null
@@ -0,0 +1,203 @@
+<?php
+/**
+ * The Secret:: class provides an API for encrypting and decrypting
+ * small pieces of data with the use of a shared key.
+ *
+ * The Secret:: functions use the Horde Cipher:: class if mcrypt is not
+ * available.
+ *
+ * Copyright 1999-2008 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Chuck Hagenbuch <chuck@horde.org>
+ * @package Horde_Secret
+ */
+class Horde_Secret
+{
+    /**
+     * Cipher cache.
+     *
+     * @var array
+     */
+    static protected $_cipherCache = array();
+
+    /**
+     * Key cache.
+     *
+     * @var array
+     */
+    static protected $_keyCache = array();
+
+    /**
+     * Take a small piece of data and encrypt it with a key.
+     *
+     * @param string $key      The key to use for encryption.
+     * @param string $message  The plaintext message.
+     *
+     * @return string  The ciphertext message.
+     */
+    static public function write($key, $message)
+    {
+        if (!strlen($key)) {
+            return false;
+        }
+
+        $ret = Secret::_getMcryptData($key, $message, 'encrypt');
+        if ($ret !== false) {
+            return $ret;
+        }
+
+        $ptr = Secret::_getCipherOb($key);
+        return $ptr->encrypt($message);
+    }
+
+    /**
+     * Decrypt a message encrypted with Secret::write().
+     *
+     * @param string $key      The key to use for decryption.
+     * @param string $message  The ciphertext message.
+     *
+     * @return string  The plaintext message.
+     */
+    static public function read($key, $ciphertext)
+    {
+        $ret = Secret::_getMcryptData($key, $ciphertext, 'decrypt');
+        if ($ret !== false) {
+            return rtrim($ret, "\0");
+        }
+
+        $ptr = Secret::_getCipherOb($key);
+        return $ptr->decrypt($ciphertext);
+    }
+
+    /**
+     * TODO
+     */
+    static protected function _getMcryptData($key, $text, $type)
+    {
+        $ret = false;
+
+        require_once 'Horde/Util.php';
+        if (Util::extensionExists('mcrypt')) {
+            $old_error = error_reporting(0);
+            $td = mcrypt_module_open(MCRYPT_GOST, '', MCRYPT_MODE_ECB, '');
+            if ($td) {
+                $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
+                mcrypt_generic_init($td, $key, $iv);
+                $ret = ($type == 'encrypt') ? mcrypt_generic($td, $text) : mdecrypt_generic($td, $text);
+                mcrypt_generic_deinit($td);
+            }
+            error_reporting($old_error);
+        }
+
+        return $ret;
+    }
+
+    /**
+     * TODO
+     */
+    static protected function _getCipherOb($key)
+    {
+        $idx = md5($key);
+
+        if (!isset(self::$_cipherCache[$idx])) {
+            self::$_cipherCache[$idx] = &Horde_Cipher::factory('blowfish');
+            self::$_cipherCache[$idx]->setBlockMode('ofb64');
+            self::$_cipherCache[$idx]->setKey($key);
+        }
+
+        return self::$_cipherCache[$idx];
+    }
+
+    /**
+     * Generate a secret key (for encryption), either using a random
+     * md5 string and storing it in a cookie if the user has cookies
+     * enabled, or munging some known values if they don't.
+     *
+     * @param string $keyname  The name of the key to set.
+     *
+     * @return string  The secret key that has been generated.
+     */
+    static public function setKey($keyname = 'generic')
+    {
+        if (isset($_COOKIE[$GLOBALS['conf']['session']['name']])) {
+            if (isset($_COOKIE[$keyname . '_key'])) {
+                $key = $_COOKIE[$keyname . '_key'];
+            } else {
+                $key = md5(mt_rand());
+                $_COOKIE[$keyname . '_key'] = $key;
+                Secret::_setCookie($keyname, $key);
+            }
+        } else {
+            $key = session_id();
+            Secret::_setCookie($keyname, $key);
+        }
+
+        return $key;
+    }
+
+    /**
+     * Return a secret key, either from a cookie, or if the cookie
+     * isn't there, assume we are using a munged version of a known
+     * base value.
+     *
+     * @param string $keyname  The name of the key to get.
+     *
+     * @return string  The secret key.
+     */
+    static public function getKey($keyname = 'generic')
+    {
+        if (!isset(self::$_keyCache[$keyname])) {
+            if (isset($_COOKIE[$keyname . '_key'])) {
+                self::$_keyCache[$keyname] = $_COOKIE[$keyname . '_key'];
+            } else {
+                self::$_keyCache[$keyname] = session_id();
+                Secret::_setCookie($keyname, self::$_keyCache[$keyname]);
+            }
+        }
+
+        return self::$_keyCache[$keyname];
+    }
+
+    /**
+     * TODO
+     */
+    static protected function _setCookie($keyname, $key)
+    {
+        global $conf;
+
+        $old_error = error_reporting(0);
+        setcookie(
+            $keyname . '_key',
+            $key,
+            $conf['session']['timeout'] ? time() + $conf['session']['timeout'] : 0,
+            $conf['cookie']['path'],
+            $conf['cookie']['domain'],
+            $conf['use_ssl'] == 1 ? 1 : 0
+        );
+        error_reporting($old_error);
+    }
+
+    /**
+     * Clears a secret key entry from the current cookie.
+     *
+     * @param string $keyname  The name of the key to clear.
+     *
+     * @return boolean  True if key existed, false if not.
+     */
+    static public function clearKey($keyname = 'generic')
+    {
+        if (isset($_COOKIE[$GLOBALS['conf']['session']['name']]) &&
+            isset($_COOKIE[$keyname . '_key'])) {
+            unset($_COOKIE[$keyname . '_key']);
+            return true;
+        }
+        return false;
+    }
+
+}
+
+// TODO - Remove once apps are transitioned to Horde 4
+class Secret extends Horde_Secret {}
diff --git a/framework/Secret/package.xml b/framework/Secret/package.xml
new file mode 100644 (file)
index 0000000..04fe3ef
--- /dev/null
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package packagerversion="1.4.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
+http://pear.php.net/dtd/tasks-1.0.xsd
+http://pear.php.net/dtd/package-2.0
+http://pear.php.net/dtd/package-2.0.xsd">
+ <name>Horde_Secret</name>
+ <channel>pear.horde.org</channel>
+ <summary>Secret Encryption API</summary>
+ <description>The Horde_Secret:: class provides an API for encrypting and decrypting small pieces of data with the use of a shared key.
+ </description>
+ <lead>
+  <name>Chuck Hagenbuch</name>
+  <user>chuck</user>
+  <email>chuck@horde.org</email>
+  <active>yes</active>
+ </lead>
+ <date>2008-12-11</date>
+ <version>
+  <release>0.0.3</release>
+  <api>0.0.2</api>
+ </version>
+ <stability>
+  <release>alpha</release>
+  <api>alpha</api>
+ </stability>
+ <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+ <notes>* Initial Horde 4 package.</notes>
+ <contents>
+  <dir name="/">
+   <dir name="lib">
+    <dir name="Horde">
+     <file name="Secret.php" role="php" />
+    </dir> <!-- /lib/Horde -->
+   </dir> <!-- /lib -->
+  </dir> <!-- / -->
+ </contents>
+ <dependencies>
+  <required>
+   <php>
+    <min>5.2.0</min>
+   </php>
+   <pearinstaller>
+    <min>1.5.0</min>
+   </pearinstaller>
+   <package>
+    <name>Horde_Cipher</name>
+    <channel>pear.horde.org</channel>
+   </package>
+   <package>
+    <name>Util</name>
+    <channel>pear.horde.org</channel>
+   </package>
+  </required>
+  <optional>
+   <extension>
+    <name>mcrypt</name>
+   </extension>
+  </optional>
+ </dependencies>
+ <phprelease>
+  <filelist>
+   <install name="lib/Horde/Secret.php" as="Horde/Secret.php" />
+  </filelist>
+ </phprelease>
+ <changelog>
+  <release>
+   <date>2006-05-08</date>
+   <time>23:10:28</time>
+   <version>
+    <release>0.0.2</release>
+    <api>0.0.2</api>
+   </version>
+   <stability>
+    <release>alpha</release>
+    <api>alpha</api>
+   </stability>
+   <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+   <notes>- Converted to package.xml 2.0 for pear.horde.org
+- Return false instead of generating encryption errors if $key is empty (Bug #5925).
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>0.0.1</release>
+    <api>0.0.1</api>
+   </version>
+   <stability>
+    <release>alpha</release>
+    <api>alpha</api>
+   </stability>
+   <date>2003-07-05</date>
+   <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+   <notes>Initial release as a PEAR package
+   </notes>
+  </release>
+ </changelog>
+</package>