]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
adding magic sig stuff
authorJames Walker <walkah@walkah.net>
Mon, 22 Feb 2010 14:05:32 +0000 (09:05 -0500)
committerJames Walker <walkah@walkah.net>
Mon, 22 Feb 2010 14:05:32 +0000 (09:05 -0500)
plugins/OStatus/extlib/Crypt/RSA.php [new file with mode: 0644]
plugins/OStatus/extlib/Crypt/RSA/ErrorHandler.php [new file with mode: 0644]
plugins/OStatus/extlib/Crypt/RSA/Key.php [new file with mode: 0644]
plugins/OStatus/extlib/Crypt/RSA/KeyPair.php [new file with mode: 0644]
plugins/OStatus/extlib/Crypt/RSA/Math/BCMath.php [new file with mode: 0644]
plugins/OStatus/extlib/Crypt/RSA/Math/BigInt.php [new file with mode: 0644]
plugins/OStatus/extlib/Crypt/RSA/Math/GMP.php [new file with mode: 0644]
plugins/OStatus/extlib/Crypt/RSA/MathLoader.php [new file with mode: 0644]
plugins/OStatus/lib/magicenvelope.php [new file with mode: 0644]
plugins/OStatus/lib/magicsig.php [new file with mode: 0644]

diff --git a/plugins/OStatus/extlib/Crypt/RSA.php b/plugins/OStatus/extlib/Crypt/RSA.php
new file mode 100644 (file)
index 0000000..16dfa54
--- /dev/null
@@ -0,0 +1,524 @@
+<?php
+/**
+ * Crypt_RSA allows to do following operations:
+ *     - key pair generation
+ *     - encryption and decryption
+ *     - signing and sign validation
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.0 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license@php.net so we can mail you a copy immediately.
+ *
+ * @category   Encryption
+ * @package    Crypt_RSA
+ * @author     Alexander Valyalkin <valyala@gmail.com>
+ * @copyright  2005, 2006 Alexander Valyalkin
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    1.2.0b
+ * @link       http://pear.php.net/package/Crypt_RSA
+ */
+
+/**
+ * RSA error handling facilities
+ */
+require_once 'Crypt/RSA/ErrorHandler.php';
+
+/**
+ * loader for math wrappers
+ */
+require_once 'Crypt/RSA/MathLoader.php';
+
+/**
+ * helper class for mange single key
+ */
+require_once 'Crypt/RSA/Key.php';
+
+/**
+ * helper class for manage key pair
+ */
+require_once 'Crypt/RSA/KeyPair.php';
+
+/**
+ * Crypt_RSA class, derived from Crypt_RSA_ErrorHandler
+ *
+ * Provides the following functions:
+ *  - setParams($params) - sets parameters of current object
+ *  - encrypt($plain_data, $key = null) - encrypts data
+ *  - decrypt($enc_data, $key = null) - decrypts data
+ *  - createSign($doc, $private_key = null) - signs document by private key
+ *  - validateSign($doc, $signature, $public_key = null) - validates signature of document
+ *
+ * Example usage:
+ *     // creating an error handler
+ *     $error_handler = create_function('$obj', 'echo "error: ", $obj->getMessage(), "\n"');
+ *
+ *     // 1024-bit key pair generation
+ *     $key_pair = new Crypt_RSA_KeyPair(1024);
+ *
+ *     // check consistence of Crypt_RSA_KeyPair object
+ *     $error_handler($key_pair);
+ *
+ *     // creating Crypt_RSA object
+ *     $rsa_obj = new Crypt_RSA;
+ *
+ *     // check consistence of Crypt_RSA object
+ *     $error_handler($rsa_obj);
+ *
+ *     // set error handler on Crypt_RSA object ( see Crypt/RSA/ErrorHandler.php for details )
+ *     $rsa_obj->setErrorHandler($error_handler);
+ *
+ *     // encryption (usually using public key)
+ *     $enc_data = $rsa_obj->encrypt($plain_data, $key_pair->getPublicKey());
+ *
+ *     // decryption (usually using private key)
+ *     $plain_data = $rsa_obj->decrypt($enc_data, $key_pair->getPrivateKey());
+ *
+ *     // signing
+ *     $signature = $rsa_obj->createSign($document, $key_pair->getPrivateKey());
+ *
+ *     // signature checking
+ *     $is_valid = $rsa_obj->validateSign($document, $signature, $key_pair->getPublicKey());
+ *
+ *     // signing many documents by one private key
+ *     $rsa_obj = new Crypt_RSA(array('private_key' => $key_pair->getPrivateKey()));
+ *     // check consistence of Crypt_RSA object
+ *     $error_handler($rsa_obj);
+ *     // set error handler ( see Crypt/RSA/ErrorHandler.php for details )
+ *     $rsa_obj->setErrorHandler($error_handler);
+ *     // sign many documents
+ *     $sign_1 = $rsa_obj->sign($doc_1);
+ *     $sign_2 = $rsa_obj->sign($doc_2);
+ *     //...
+ *     $sign_n = $rsa_obj->sign($doc_n);
+ *
+ *     // changing default hash function, which is used for sign
+ *     // creating/validation
+ *     $rsa_obj->setParams(array('hash_func' => 'md5'));
+ *
+ *     // using factory() method instead of constructor (it returns PEAR_Error object on failure)
+ *     $rsa_obj = &Crypt_RSA::factory();
+ *     if (PEAR::isError($rsa_obj)) {
+ *         echo "error: ", $rsa_obj->getMessage(), "\n";
+ *     }
+ *
+ * @category   Encryption
+ * @package    Crypt_RSA
+ * @author     Alexander Valyalkin <valyala@gmail.com>
+ * @copyright  2005, 2006 Alexander Valyalkin
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @link       http://pear.php.net/package/Crypt_RSA
+ * @version    @package_version@
+ * @access     public
+ */
+class Crypt_RSA extends Crypt_RSA_ErrorHandler
+{
+    /**
+     * Reference to math wrapper, which is used to
+     * manipulate large integers in RSA algorithm.
+     *
+     * @var object of Crypt_RSA_Math_* class
+     * @access private
+     */
+    var $_math_obj;
+
+    /**
+     * key for encryption, which is used by encrypt() method
+     *
+     * @var object of Crypt_RSA_KEY class
+     * @access private
+     */
+    var $_enc_key;
+
+    /**
+     * key for decryption, which is used by decrypt() method
+     *
+     * @var object of Crypt_RSA_KEY class
+     * @access private
+     */
+    var $_dec_key;
+
+    /**
+     * public key, which is used by validateSign() method
+     *
+     * @var object of Crypt_RSA_KEY class
+     * @access private
+     */
+    var $_public_key;
+
+    /**
+     * private key, which is used by createSign() method
+     *
+     * @var object of Crypt_RSA_KEY class
+     * @access private
+     */
+    var $_private_key;
+
+    /**
+     * name of hash function, which is used by validateSign()
+     * and createSign() methods. Default hash function is SHA-1
+     *
+     * @var string
+     * @access private
+     */
+    var $_hash_func = 'sha1';
+
+    /**
+     * Crypt_RSA constructor.
+     *
+     * @param array $params
+     *        Optional associative array of parameters, such as:
+     *        enc_key, dec_key, private_key, public_key, hash_func.
+     *        See setParams() method for more detailed description of
+     *        these parameters.
+     * @param string $wrapper_name
+     *        Name of math wrapper, which will be used to
+     *        perform different operations with big integers.
+     *        See contents of Crypt/RSA/Math folder for examples of wrappers.
+     *        Read docs/Crypt_RSA/docs/math_wrappers.txt for details.
+     * @param string $error_handler   name of error handler function
+     *
+     * @access public
+     */
+    function Crypt_RSA($params = null, $wrapper_name = 'default', $error_handler = '')
+    {
+        // set error handler
+        $this->setErrorHandler($error_handler);
+        // try to load math wrapper
+        $obj = &Crypt_RSA_MathLoader::loadWrapper($wrapper_name);
+        if ($this->isError($obj)) {
+            // error during loading of math wrapper
+            // Crypt_RSA object is partially constructed.
+            $this->pushError($obj);
+            return;
+        }
+        $this->_math_obj = &$obj;
+
+        if (!is_null($params)) {
+            if (!$this->setParams($params)) {
+                // error in Crypt_RSA::setParams() function
+                return;
+            }
+        }
+    }
+
+    /**
+     * Crypt_RSA factory.
+     *
+     * @param array $params
+     *        Optional associative array of parameters, such as:
+     *        enc_key, dec_key, private_key, public_key, hash_func.
+     *        See setParams() method for more detailed description of
+     *        these parameters.
+     * @param string $wrapper_name
+     *        Name of math wrapper, which will be used to
+     *        perform different operations with big integers.
+     *        See contents of Crypt/RSA/Math folder for examples of wrappers.
+     *        Read docs/Crypt_RSA/docs/math_wrappers.txt for details.
+     * @param string $error_handler   name of error handler function
+     *
+     * @return object  new Crypt_RSA object on success or PEAR_Error object on failure
+     * @access public
+     */
+    function &factory($params = null, $wrapper_name = 'default', $error_handler = '')
+    {
+        $obj = &new Crypt_RSA($params, $wrapper_name, $error_handler);
+        if ($obj->isError()) {
+            // error during creating a new object. Retrurn PEAR_Error object
+            return $obj->getLastError();
+        }
+        // object created successfully. Return it
+        return $obj;
+    }
+
+    /**
+     * Accepts any combination of available parameters as associative array:
+     *     enc_key - encryption key for encrypt() method
+     *     dec_key - decryption key for decrypt() method
+     *     public_key - key for validateSign() method
+     *     private_key - key for createSign() method
+     *     hash_func - name of hash function, which will be used to create and validate sign
+     *
+     * @param array $params
+     *        associative array of permitted parameters (see above)
+     *
+     * @return bool   true on success or false on error
+     * @access public
+     */
+    function setParams($params)
+    {
+        if (!is_array($params)) {
+            $this->pushError('parameters must be passed to function as associative array', CRYPT_RSA_ERROR_WRONG_PARAMS);
+            return false;
+        }
+
+        if (isset($params['enc_key'])) {
+            if (Crypt_RSA_Key::isValid($params['enc_key'])) {
+                $this->_enc_key = $params['enc_key'];
+            }
+            else {
+                $this->pushError('wrong encryption key. It must be an object of Crypt_RSA_Key class', CRYPT_RSA_ERROR_WRONG_KEY);
+                return false;
+            }
+        }
+        if (isset($params['dec_key'])) {
+            if (Crypt_RSA_Key::isValid($params['dec_key'])) {
+                $this->_dec_key = $params['dec_key'];
+            }
+            else {
+                $this->pushError('wrong decryption key. It must be an object of Crypt_RSA_Key class', CRYPT_RSA_ERROR_WRONG_KEY);
+                return false;
+            }
+        }
+        if (isset($params['private_key'])) {
+            if (Crypt_RSA_Key::isValid($params['private_key'])) {
+                if ($params['private_key']->getKeyType() != 'private') {
+                    $this->pushError('private key must have "private" attribute', CRYPT_RSA_ERROR_WRONG_KEY_TYPE);
+                    return false;
+                }
+                $this->_private_key = $params['private_key'];
+            }
+            else {
+                $this->pushError('wrong private key. It must be an object of Crypt_RSA_Key class', CRYPT_RSA_ERROR_WRONG_KEY);
+                return false;
+            }
+        }
+        if (isset($params['public_key'])) {
+            if (Crypt_RSA_Key::isValid($params['public_key'])) {
+                if ($params['public_key']->getKeyType() != 'public') {
+                    $this->pushError('public key must have "public" attribute', CRYPT_RSA_ERROR_WRONG_KEY_TYPE);
+                    return false;
+                }
+                $this->_public_key = $params['public_key'];
+            }
+            else {
+                $this->pushError('wrong public key. It must be an object of Crypt_RSA_Key class', CRYPT_RSA_ERROR_WRONG_KEY);
+                return false;
+            }
+        }
+        if (isset($params['hash_func'])) {
+            if (!function_exists($params['hash_func'])) {
+                $this->pushError('cannot find hash function with name [' . $params['hash_func'] . ']', CRYPT_RSA_ERROR_WRONG_HASH_FUNC);
+                return false;
+            }
+            $this->_hash_func = $params['hash_func'];
+        }
+        return true; // all ok
+    }
+
+    /**
+     * Ecnrypts $plain_data by the key $this->_enc_key or $key.
+     *
+     * @param string $plain_data  data, which must be encrypted
+     * @param object $key         encryption key (object of Crypt_RSA_Key class)
+     * @return mixed
+     *         encrypted data as string on success or false on error
+     *
+     * @access public
+     */
+    function encrypt($plain_data, $key = null)
+    {
+        $enc_data = $this->encryptBinary($plain_data, $key);
+        if ($enc_data !== false) {
+            return base64_encode($enc_data);
+        }
+        // error during encripting data
+        return false;
+    }
+
+    /**
+     * Ecnrypts $plain_data by the key $this->_enc_key or $key.
+     *
+     * @param string $plain_data  data, which must be encrypted
+     * @param object $key         encryption key (object of Crypt_RSA_Key class)
+     * @return mixed
+     *         encrypted data as binary string on success or false on error
+     *
+     * @access public
+     */
+    function encryptBinary($plain_data, $key = null)
+    {
+        if (is_null($key)) {
+            // use current encryption key
+            $key = $this->_enc_key;
+        }
+        else if (!Crypt_RSA_Key::isValid($key)) {
+            $this->pushError('invalid encryption key. It must be an object of Crypt_RSA_Key class', CRYPT_RSA_ERROR_WRONG_KEY);
+            return false;
+        }
+
+        // append tail \x01 to plain data. It needs for correctly decrypting of data
+        $plain_data .= "\x01";
+
+        $plain_data = $this->_math_obj->bin2int($plain_data);
+        $exp = $this->_math_obj->bin2int($key->getExponent());
+        $modulus = $this->_math_obj->bin2int($key->getModulus());
+
+        // divide plain data into chunks
+        $data_len = $this->_math_obj->bitLen($plain_data);
+        $chunk_len = $key->getKeyLength() - 1;
+        $block_len = (int) ceil($chunk_len / 8);
+        $curr_pos = 0;
+        $enc_data = '';
+        while ($curr_pos < $data_len) {
+            $tmp = $this->_math_obj->subint($plain_data, $curr_pos, $chunk_len);
+            $enc_data .= str_pad(
+                $this->_math_obj->int2bin($this->_math_obj->powmod($tmp, $exp, $modulus)),
+                $block_len,
+                "\0"
+            );
+            $curr_pos += $chunk_len;
+        }
+        return $enc_data;
+    }
+
+    /**
+     * Decrypts $enc_data by the key $this->_dec_key or $key.
+     *
+     * @param string $enc_data  encrypted data as string
+     * @param object $key       decryption key (object of RSA_Crypt_Key class)
+     * @return mixed
+     *         decrypted data as string on success or false on error
+     *
+     * @access public
+     */
+    function decrypt($enc_data, $key = null)
+    {
+        $enc_data = base64_decode($enc_data);
+        return $this->decryptBinary($enc_data, $key);
+    }
+
+    /**
+     * Decrypts $enc_data by the key $this->_dec_key or $key.
+     *
+     * @param string $enc_data  encrypted data as binary string
+     * @param object $key       decryption key (object of RSA_Crypt_Key class)
+     * @return mixed
+     *         decrypted data as string on success or false on error
+     *
+     * @access public
+     */
+    function decryptBinary($enc_data, $key = null)
+    {
+        if (is_null($key)) {
+            // use current decryption key
+            $key = $this->_dec_key;
+        }
+        else if (!Crypt_RSA_Key::isValid($key)) {
+            $this->pushError('invalid decryption key. It must be an object of Crypt_RSA_Key class', CRYPT_RSA_ERROR_WRONG_KEY);
+            return false;
+        }
+
+        $exp = $this->_math_obj->bin2int($key->getExponent());
+        $modulus = $this->_math_obj->bin2int($key->getModulus());
+
+        $data_len = strlen($enc_data);
+        $chunk_len = $key->getKeyLength() - 1;
+        $block_len = (int) ceil($chunk_len / 8);
+        $curr_pos = 0;
+        $bit_pos = 0;
+        $plain_data = $this->_math_obj->bin2int("\0");
+        while ($curr_pos < $data_len) {
+            $tmp = $this->_math_obj->bin2int(substr($enc_data, $curr_pos, $block_len));
+            $tmp = $this->_math_obj->powmod($tmp, $exp, $modulus);
+            $plain_data = $this->_math_obj->bitOr($plain_data, $tmp, $bit_pos);
+            $bit_pos += $chunk_len;
+            $curr_pos += $block_len;
+        }
+        $result = $this->_math_obj->int2bin($plain_data);
+
+        // delete tail, containing of \x01
+        $tail = ord($result{strlen($result) - 1});
+        if ($tail != 1) {
+            $this->pushError("Error tail of decrypted text = {$tail}. Expected 1", CRYPT_RSA_ERROR_WRONG_TAIL);
+            return false;
+        }
+        return substr($result, 0, -1);
+    }
+
+    /**
+     * Creates sign for document $document, using $this->_private_key or $private_key
+     * as private key and $this->_hash_func or $hash_func as hash function.
+     *
+     * @param string $document     document, which must be signed
+     * @param object $private_key  private key (object of Crypt_RSA_Key type)
+     * @param string $hash_func    name of hash function, which will be used during signing
+     * @return mixed
+     *         signature of $document as string on success or false on error
+     *
+     * @access public
+     */
+    function createSign($document, $private_key = null, $hash_func = null)
+    {
+        // check private key
+        if (is_null($private_key)) {
+            $private_key = $this->_private_key;
+        }
+        else if (!Crypt_RSA_Key::isValid($private_key)) {
+            $this->pushError('invalid private key. It must be an object of Crypt_RSA_Key class', CRYPT_RSA_ERROR_WRONG_KEY);
+            return false;
+        }
+        if ($private_key->getKeyType() != 'private') {
+            $this->pushError('signing key must be private', CRYPT_RSA_ERROR_NEED_PRV_KEY);
+            return false;
+        }
+
+        // check hash_func
+        if (is_null($hash_func)) {
+            $hash_func = $this->_hash_func;
+        }
+        if (!function_exists($hash_func)) {
+            $this->pushError("cannot find hash function with name [$hash_func]", CRYPT_RSA_ERROR_WRONG_HASH_FUNC);
+            return false;
+        }
+
+        return $this->encrypt($hash_func($document), $private_key);
+    }
+
+    /**
+     * Validates $signature for document $document with public key $this->_public_key
+     * or $public_key and hash function $this->_hash_func or $hash_func.
+     *
+     * @param string $document    document, signature of which must be validated
+     * @param string $signature   signature, which must be validated
+     * @param object $public_key  public key (object of Crypt_RSA_Key class)
+     * @param string $hash_func   hash function, which will be used during validating signature
+     * @return mixed
+     *         true, if signature of document is valid
+     *         false, if signature of document is invalid
+     *         null on error
+     *
+     * @access public
+     */
+    function validateSign($document, $signature, $public_key = null, $hash_func = null)
+    {
+        // check public key
+        if (is_null($public_key)) {
+            $public_key = $this->_public_key;
+        }
+        else if (!Crypt_RSA_Key::isValid($public_key)) {
+            $this->pushError('invalid public key. It must be an object of Crypt_RSA_Key class', CRYPT_RSA_ERROR_WRONG_KEY);
+            return null;
+        }
+        if ($public_key->getKeyType() != 'public') {
+            $this->pushError('validating key must be public', CRYPT_RSA_ERROR_NEED_PUB_KEY);
+            return null;
+        }
+
+        // check hash_func
+        if (is_null($hash_func)) {
+            $hash_func = $this->_hash_func;
+        }
+        if (!function_exists($hash_func)) {
+            $this->pushError("cannot find hash function with name [$hash_func]", CRYPT_RSA_ERROR_WRONG_HASH_FUNC);
+            return null;
+        }
+
+        return $hash_func($document) == $this->decrypt($signature, $public_key);
+    }
+}
+
+?>
\ No newline at end of file
diff --git a/plugins/OStatus/extlib/Crypt/RSA/ErrorHandler.php b/plugins/OStatus/extlib/Crypt/RSA/ErrorHandler.php
new file mode 100644 (file)
index 0000000..8f39741
--- /dev/null
@@ -0,0 +1,234 @@
+<?php
+/**
+ * Crypt_RSA allows to do following operations:
+ *     - key pair generation
+ *     - encryption and decryption
+ *     - signing and sign validation
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.0 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license@php.net so we can mail you a copy immediately.
+ *
+ * @category  Encryption
+ * @package   Crypt_RSA
+ * @author    Alexander Valyalkin <valyala@gmail.com>
+ * @copyright 2005 Alexander Valyalkin
+ * @license   http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version   CVS: $Id: ErrorHandler.php,v 1.4 2009/01/05 08:30:29 clockwerx Exp $
+ * @link      http://pear.php.net/package/Crypt_RSA
+ */
+
+/**
+ * uses PEAR's error handling
+ */
+require_once 'PEAR.php';
+
+/**
+ * cannot load required extension for math wrapper
+ */
+define('CRYPT_RSA_ERROR_NO_EXT', 1);
+
+/**
+ * cannot load any math wrappers.
+ * Possible reasons:
+ *  - there is no any wrappers (they must exist in Crypt/RSA/Math folder )
+ *  - all available wrappers are incorrect (read docs/Crypt_RSA/docs/math_wrappers.txt )
+ *  - cannot load any extension, required by available wrappers
+ */
+define('CRYPT_RSA_ERROR_NO_WRAPPERS', 2);
+
+/**
+ * cannot find file, containing requested math wrapper
+ */
+define('CRYPT_RSA_ERROR_NO_FILE', 3);
+
+/**
+ * cannot find math wrapper class in the math wrapper file
+ */
+define('CRYPT_RSA_ERROR_NO_CLASS', 4);
+
+/**
+ * invalid key type passed to function (it must be 'public' or 'private')
+ */
+define('CRYPT_RSA_ERROR_WRONG_KEY_TYPE', 5);
+
+/**
+ * key modulus must be greater than key exponent
+ */
+define('CRYPT_RSA_ERROR_EXP_GE_MOD', 6);
+
+/**
+ * missing $key_len parameter in Crypt_RSA_KeyPair::generate($key_len) function
+ */
+define('CRYPT_RSA_ERROR_MISSING_KEY_LEN', 7);
+
+/**
+ * wrong key object passed to function (it must be an object of Crypt_RSA_Key class)
+ */
+define('CRYPT_RSA_ERROR_WRONG_KEY', 8);
+
+/**
+ * wrong name of hash function passed to Crypt_RSA::setParams() function
+ */
+define('CRYPT_RSA_ERROR_WRONG_HASH_FUNC', 9);
+
+/**
+ * key, used for signing, must be private
+ */
+define('CRYPT_RSA_ERROR_NEED_PRV_KEY', 10);
+
+/**
+ * key, used for sign validating, must be public
+ */
+define('CRYPT_RSA_ERROR_NEED_PUB_KEY', 11);
+
+/**
+ * parameters must be passed to function as associative array
+ */
+define('CRYPT_RSA_ERROR_WRONG_PARAMS', 12);
+
+/**
+ * error tail of decrypted text. Maybe, wrong decryption key?
+ */
+define('CRYPT_RSA_ERROR_WRONG_TAIL', 13);
+
+/**
+ * Crypt_RSA_ErrorHandler class.
+ *
+ * This class is used as base for Crypt_RSA, Crypt_RSA_Key
+ * and Crypt_RSA_KeyPair classes.
+ *
+ * It provides following functions:
+ *   - isError() - returns true, if list contains errors, else returns false
+ *   - getErrorList() - returns error list
+ *   - getLastError() - returns last error from error list or false, if list is empty
+ *   - pushError($errstr) - pushes $errstr into the error list
+ *   - setErrorHandler($new_error_handler) - sets error handler function
+ *   - getErrorHandler() - returns name of error handler function
+ *
+ * @category  Encryption
+ * @package   Crypt_RSA
+ * @author    Alexander Valyalkin <valyala@gmail.com>
+ * @copyright 2005 Alexander Valyalkin
+ * @license   http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version   Release: @package_version@
+ * @link      http://pear.php.net/package/Crypt_RSA
+ * @access    public
+ */
+class Crypt_RSA_ErrorHandler
+{
+    /**
+     * array of error objects, pushed by $this->pushError()
+     *
+     * @var array
+     * @access private
+     */
+    var $_errors = array();
+
+    /**
+     * name of error handler - function, which calls on $this->pushError() call
+     *
+     * @var string
+     * @access private
+     */
+    var $_error_handler = '';
+
+    /**
+     * Returns true if list of errors is not empty, else returns false
+     *
+     * @param mixed $err Check if the object is an error
+     *
+     * @return bool    true, if list of errors is not empty or $err is PEAR_Error object, else false
+     * @access public
+     */
+    function isError($err = null)
+    {
+        return is_null($err) ? (sizeof($this->_errors) > 0) : PEAR::isError($err);
+    }
+
+    /**
+     * Returns list of all errors, pushed to error list by $this->pushError()
+     *
+     * @return array    list of errors (usually it contains objects of PEAR_Error class)
+     * @access public
+     */
+    function getErrorList()
+    {
+        return $this->_errors;
+    }
+
+    /**
+     * Returns last error from errors list or false, if list is empty
+     *
+     * @return mixed
+     *         last error from errors list (usually it is PEAR_Error object)
+     *         or false, if list is empty.
+     *
+     * @access public
+     */
+    function getLastError()
+    {
+        $len = sizeof($this->_errors);
+        return $len ? $this->_errors[$len - 1] : false;
+    }
+
+    /**
+     * pushes error object $error to the error list
+     *
+     * @param string $errstr error string
+     * @param int    $errno  error number
+     *
+     * @return bool          true on success, false on error
+     * @access public
+     */
+    function pushError($errstr, $errno = 0)
+    {
+        $this->_errors[] = PEAR::raiseError($errstr, $errno);
+
+        if ($this->_error_handler != '') {
+            // call user defined error handler
+            $func = $this->_error_handler;
+            $func($this);
+        }
+        return true;
+    }
+
+    /**
+     * sets error handler to function with name $func_name.
+     * Function $func_name must accept one parameter - current
+     * object, which triggered error.
+     *
+     * @param string $func_name name of error handler function
+     *
+     * @return bool             true on success, false on error
+     * @access public
+     */
+    function setErrorHandler($func_name = '')
+    {
+        if ($func_name == '') {
+            $this->_error_handler = '';
+        }
+        if (!function_exists($func_name)) {
+            return false;
+        }
+        $this->_error_handler = $func_name;
+        return true;
+    }
+
+    /**
+     * returns name of current error handler, or null if there is no error handler
+     *
+     * @return mixed  error handler name as string or null, if there is no error handler
+     * @access public
+     */
+    function getErrorHandler()
+    {
+        return $this->_error_handler;
+    }
+}
+
+?>
diff --git a/plugins/OStatus/extlib/Crypt/RSA/Key.php b/plugins/OStatus/extlib/Crypt/RSA/Key.php
new file mode 100644 (file)
index 0000000..6595302
--- /dev/null
@@ -0,0 +1,315 @@
+<?php
+/**
+ * Crypt_RSA allows to do following operations:
+ *     - key pair generation
+ *     - encryption and decryption
+ *     - signing and sign validation
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.0 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license@php.net so we can mail you a copy immediately.
+ *
+ * @category  Encryption
+ * @package   Crypt_RSA
+ * @author    Alexander Valyalkin <valyala@gmail.com>
+ * @copyright 2005 Alexander Valyalkin
+ * @license   http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version   CVS: $Id: Key.php,v 1.6 2009/01/05 08:30:29 clockwerx Exp $
+ * @link      http://pear.php.net/package/Crypt_RSA
+ */
+
+/**
+ * RSA error handling facilities
+ */
+require_once 'Crypt/RSA/ErrorHandler.php';
+
+/**
+ * loader for RSA math wrappers
+ */
+require_once 'Crypt/RSA/MathLoader.php';
+
+/**
+ * Crypt_RSA_Key class, derived from Crypt_RSA_ErrorHandler
+ *
+ * Provides the following functions:
+ *  - getKeyLength() - returns bit key length
+ *  - getExponent() - returns key exponent as binary string
+ *  - getModulus() - returns key modulus as binary string
+ *  - getKeyType() - returns type of the key (public or private)
+ *  - toString() - returns serialized key as string
+ *  - fromString($key_str) - static function; returns key, unserialized from string
+ *  - isValid($key) - static function for validating of $key
+ *
+ * Example usage:
+ *    // create new 1024-bit key pair
+ *    $key_pair = new Crypt_RSA_KeyPair(1024);
+ * 
+ *    // get public key (its class is Crypt_RSA_Key)
+ *    $key = $key_pair->getPublicKey();
+ *
+ *    // get key length
+ *    $len = $key->getKeyLength();
+ *
+ *    // get modulus as string
+ *    $modulus = $key->getModulus();
+ *
+ *    // get exponent as string
+ *    $exponent = $key->getExponent();
+ *
+ *    // get string represenation of key (use it instead of serialization of Crypt_RSA_Key object)
+ *    $key_in_str = $key->toString();
+ *
+ *    // restore key object from string using 'BigInt' math wrapper
+ *    $key = Crypt_RSA_Key::fromString($key_in_str, 'BigInt');
+ *
+ *    // error check
+ *    if ($key->isError()) {
+ *        echo "error while unserializing key object:\n";
+ *        $erorr = $key->getLastError();
+ *        echo $error->getMessage(), "\n";
+ *    }
+ *
+ *    // validate key
+ *    if (Crypt_RSA_Key::isValid($key)) echo 'valid key';
+ *    else echo 'invalid key';
+ *
+ *    // using factory() method instead of constructor (it returns PEAR_Error object on failure)
+ *    $rsa_obj = &Crypt_RSA_Key::factory($modulus, $exp, $key_type);
+ *    if (PEAR::isError($rsa_obj)) {
+ *        echo "error: ", $rsa_obj->getMessage(), "\n";
+ *    }
+ *
+ * @category  Encryption
+ * @package   Crypt_RSA
+ * @author    Alexander Valyalkin <valyala@gmail.com>
+ * @copyright 2005 Alexander Valyalkin
+ * @license   http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version   Release: @package_version@
+ * @link      http://pear.php.net/package/Crypt_RSA
+ * @access    public
+ */
+class Crypt_RSA_Key extends Crypt_RSA_ErrorHandler
+{
+    /**
+     * Reference to math wrapper object, which is used to
+     * manipulate large integers in RSA algorithm.
+     *
+     * @var object of Crypt_RSA_Math_* class
+     * @access private
+     */
+    var $_math_obj;
+
+    /**
+     * shared modulus
+     *
+     * @var string
+     * @access private
+     */
+    var $_modulus;
+
+    /**
+     * exponent
+     *
+     * @var string
+     * @access private
+     */
+    var $_exp;
+
+    /**
+     * key type (private or public)
+     *
+     * @var string
+     * @access private
+     */
+    var $_key_type;
+
+    /**
+     * key length in bits
+     *
+     * @var int
+     * @access private
+     */
+    var $_key_len;
+
+    /**
+     * Crypt_RSA_Key constructor.
+     *
+     * You should pass in the name of math wrapper, which will be used to
+     *        perform different operations with big integers.
+     *        See contents of Crypt/RSA/Math folder for examples of wrappers.
+     *        Read docs/Crypt_RSA/docs/math_wrappers.txt for details.
+     *
+     * @param string $modulus       key modulus
+     * @param string $exp           key exponent
+     * @param string $key_type      type of the key (public or private)
+     * @param string $wrapper_name  wrapper to use
+     * @param string $error_handler name of error handler function
+     *
+     * @access public
+     */
+    function Crypt_RSA_Key($modulus, $exp, $key_type, $wrapper_name = 'default', $error_handler = '')
+    {
+        // set error handler
+        $this->setErrorHandler($error_handler);
+        // try to load math wrapper $wrapper_name
+        $obj = &Crypt_RSA_MathLoader::loadWrapper($wrapper_name);
+        if ($this->isError($obj)) {
+            // error during loading of math wrapper
+            $this->pushError($obj); // push error object into error list
+            return;
+        }
+        $this->_math_obj = &$obj;
+
+        $this->_modulus = $modulus;
+        $this->_exp = $exp;
+
+        if (!in_array($key_type, array('private', 'public'))) {
+            $this->pushError('invalid key type. It must be private or public', CRYPT_RSA_ERROR_WRONG_KEY_TYPE);
+            return;
+        }
+        $this->_key_type = $key_type;
+
+        /* check length of modulus & exponent ( abs(modulus) > abs(exp) ) */
+        $mod_num = $this->_math_obj->bin2int($this->_modulus);
+        $exp_num = $this->_math_obj->bin2int($this->_exp);
+
+        if ($this->_math_obj->cmpAbs($mod_num, $exp_num) <= 0) {
+            $this->pushError('modulus must be greater than exponent', CRYPT_RSA_ERROR_EXP_GE_MOD);
+            return;
+        }
+
+        // determine key length
+        $this->_key_len = $this->_math_obj->bitLen($mod_num);
+    }
+
+    /**
+     * Crypt_RSA_Key factory.
+     *
+     * @param string $modulus       key modulus
+     * @param string $exp           key exponent
+     * @param string $key_type      type of the key (public or private)
+     * @param string $wrapper_name  wrapper to use
+     * @param string $error_handler name of error handler function
+     *
+     * @return object   new Crypt_RSA_Key object on success or PEAR_Error object on failure
+     * @access public
+     */
+    function factory($modulus, $exp, $key_type, $wrapper_name = 'default', $error_handler = '')
+    {
+        $obj = new Crypt_RSA_Key($modulus, $exp, $key_type, $wrapper_name, $error_handler);
+        if ($obj->isError()) {
+            // error during creating a new object. Retrurn PEAR_Error object
+            return $obj->getLastError();
+        }
+        // object created successfully. Return it
+        return $obj;
+    }
+
+    /**
+     * Calculates bit length of the key
+     *
+     * @return int    bit length of key
+     * @access public
+     */
+    function getKeyLength()
+    {
+        return $this->_key_len;
+    }
+
+    /**
+     * Returns modulus part of the key as binary string,
+     * which can be used to construct new Crypt_RSA_Key object.
+     *
+     * @return string  modulus as binary string
+     * @access public
+     */
+    function getModulus()
+    {
+        return $this->_modulus;
+    }
+
+    /**
+     * Returns exponent part of the key as binary string,
+     * which can be used to construct new Crypt_RSA_Key object.
+     *
+     * @return string  exponent as binary string
+     * @access public
+     */
+    function getExponent()
+    {
+        return $this->_exp;
+    }
+
+    /**
+     * Returns key type (public, private)
+     *
+     * @return string  key type (public, private)
+     * @access public
+     */
+    function getKeyType()
+    {
+        return $this->_key_type;
+    }
+
+    /**
+     * Returns string representation of key
+     *
+     * @return string  key, serialized to string
+     * @access public
+     */
+    function toString()
+    {
+        return base64_encode(
+            serialize(
+                array($this->_modulus, $this->_exp, $this->_key_type)
+            )
+        );
+    }
+
+    /**
+     * Returns Crypt_RSA_Key object, unserialized from
+     * string representation of key.
+     *
+     * optional parameter $wrapper_name - is the name of math wrapper,
+     * which will be used during unserialization of this object.
+     *
+     * This function can be called statically:
+     *     $key = Crypt_RSA_Key::fromString($key_in_string, 'BigInt');
+     *
+     * @param string $key_str      RSA key, serialized into string
+     * @param string $wrapper_name optional math wrapper name
+     *
+     * @return object        key as Crypt_RSA_Key object
+     * @access public
+     * @static
+     */
+    function fromString($key_str, $wrapper_name = 'default')
+    {
+        list($modulus, $exponent, $key_type) = unserialize(base64_decode($key_str));
+        $obj = new Crypt_RSA_Key($modulus, $exponent, $key_type, $wrapper_name);
+        return $obj;
+    }
+
+    /**
+     * Validates key
+     * This function can be called statically:
+     *    $is_valid = Crypt_RSA_Key::isValid($key)
+     *
+     * Returns true, if $key is valid Crypt_RSA key, else returns false
+     *
+     * @param object $key Crypt_RSA_Key object for validating
+     *
+     * @return bool        true if $key is valid, else false
+     * @access public
+     */
+    function isValid($key)
+    {
+        return (is_object($key) && strtolower(get_class($key)) === strtolower(__CLASS__));
+    }
+}
+
+?>
diff --git a/plugins/OStatus/extlib/Crypt/RSA/KeyPair.php b/plugins/OStatus/extlib/Crypt/RSA/KeyPair.php
new file mode 100644 (file)
index 0000000..ecc0b7d
--- /dev/null
@@ -0,0 +1,804 @@
+<?php
+/**
+ * Crypt_RSA allows to do following operations:
+ *     - key pair generation
+ *     - encryption and decryption
+ *     - signing and sign validation
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.0 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license@php.net so we can mail you a copy immediately.
+ *
+ * @category  Encryption
+ * @package   Crypt_RSA
+ * @author    Alexander Valyalkin <valyala@gmail.com>
+ * @copyright 2005 Alexander Valyalkin
+ * @license   http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version   CVS: $Id: KeyPair.php,v 1.7 2009/01/05 08:30:29 clockwerx Exp $
+ * @link      http://pear.php.net/package/Crypt_RSA
+ */
+
+/**
+ * RSA error handling facilities
+ */
+require_once 'Crypt/RSA/ErrorHandler.php';
+
+/**
+ * loader for RSA math wrappers
+ */
+require_once 'Crypt/RSA/MathLoader.php';
+
+/**
+ * helper class for single key managing
+ */
+require_once 'Crypt/RSA/Key.php';
+
+/**
+ * Crypt_RSA_KeyPair class, derived from Crypt_RSA_ErrorHandler
+ *
+ * Provides the following functions:
+ *  - generate($key) - generates new key pair
+ *  - getPublicKey() - returns public key
+ *  - getPrivateKey() - returns private key
+ *  - getKeyLength() - returns bit key length
+ *  - setRandomGenerator($func_name) - sets random generator to $func_name
+ *  - fromPEMString($str) - retrieves keypair from PEM-encoded string
+ *  - toPEMString() - stores keypair to PEM-encoded string
+ *  - isEqual($keypair2) - compares current keypair to $keypair2
+ *
+ * Example usage:
+ *    // create new 1024-bit key pair
+ *    $key_pair = new Crypt_RSA_KeyPair(1024);
+ *
+ *    // error check
+ *    if ($key_pair->isError()) {
+ *        echo "error while initializing Crypt_RSA_KeyPair object:\n";
+ *        $erorr = $key_pair->getLastError();
+ *        echo $error->getMessage(), "\n";
+ *    }
+ *
+ *    // get public key
+ *    $public_key = $key_pair->getPublicKey();
+ * 
+ *    // get private key
+ *    $private_key = $key_pair->getPrivateKey();
+ * 
+ *    // generate new 512-bit key pair
+ *    $key_pair->generate(512);
+ *
+ *    // error check
+ *    if ($key_pair->isError()) {
+ *        echo "error while generating key pair:\n";
+ *        $erorr = $key_pair->getLastError();
+ *        echo $error->getMessage(), "\n";
+ *    }
+ *
+ *    // get key pair length
+ *    $length = $key_pair->getKeyLength();
+ *
+ *    // set random generator to $func_name, where $func_name
+ *    // consists name of random generator function. See comments
+ *    // before setRandomGenerator() method for details
+ *    $key_pair->setRandomGenerator($func_name);
+ *
+ *    // error check
+ *    if ($key_pair->isError()) {
+ *        echo "error while changing random generator:\n";
+ *        $erorr = $key_pair->getLastError();
+ *        echo $error->getMessage(), "\n";
+ *    }
+ *
+ *    // using factory() method instead of constructor (it returns PEAR_Error object on failure)
+ *    $rsa_obj = &Crypt_RSA_KeyPair::factory($key_len);
+ *    if (PEAR::isError($rsa_obj)) {
+ *        echo "error: ", $rsa_obj->getMessage(), "\n";
+ *    }
+ *
+ *    // read key pair from PEM-encoded string:
+ *    $str = "-----BEGIN RSA PRIVATE KEY-----"
+ *         . "MCsCAQACBHr5LDkCAwEAAQIEBc6jbQIDAOCfAgMAjCcCAk3pAgJMawIDAL41"
+ *         . "-----END RSA PRIVATE KEY-----";
+ *    $keypair = Crypt_RSA_KeyPair::fromPEMString($str);
+ *
+ *    // read key pair from .pem file 'private.pem':
+ *    $str = file_get_contents('private.pem');
+ *    $keypair = Crypt_RSA_KeyPair::fromPEMString($str);
+ *
+ *    // generate and write 1024-bit key pair to .pem file 'private_new.pem'
+ *    $keypair = new Crypt_RSA_KeyPair(1024);
+ *    $str = $keypair->toPEMString();
+ *    file_put_contents('private_new.pem', $str);
+ *
+ *    // compare $keypair1 to $keypair2
+ *    if ($keypair1->isEqual($keypair2)) {
+ *        echo "keypair1 = keypair2\n";
+ *    }
+ *    else {
+ *        echo "keypair1 != keypair2\n";
+ *    }
+ *
+ * @category  Encryption
+ * @package   Crypt_RSA
+ * @author    Alexander Valyalkin <valyala@gmail.com>
+ * @copyright 2005 Alexander Valyalkin
+ * @license   http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version   Release: @package_version@
+ * @link      http://pear.php.net/package/Crypt_RSA
+ * @access    public
+ */
+class Crypt_RSA_KeyPair extends Crypt_RSA_ErrorHandler
+{
+    /**
+     * Reference to math wrapper object, which is used to
+     * manipulate large integers in RSA algorithm.
+     *
+     * @var object of Crypt_RSA_Math_* class
+     * @access private
+     */
+    var $_math_obj;
+
+    /**
+     * length of each key in the key pair
+     *
+     * @var int
+     * @access private
+     */
+    var $_key_len;
+
+    /**
+     * public key
+     *
+     * @var object of Crypt_RSA_KEY class
+     * @access private
+     */
+    var $_public_key;
+
+    /**
+     * private key
+     *
+     * @var object of Crypt_RSA_KEY class
+     * @access private
+     */
+    var $_private_key;
+
+    /**
+     * name of function, which is used as random generator
+     *
+     * @var string
+     * @access private
+     */
+    var $_random_generator;
+
+    /**
+     * RSA keypair attributes [version, n, e, d, p, q, dmp1, dmq1, iqmp] as associative array
+     *
+     * @var array
+     * @access private
+     */
+    var $_attrs;
+
+    /**
+     * Returns names of keypair attributes from $this->_attrs array
+     *
+     * @return array  Array of keypair attributes names
+     * @access private
+     */
+    function _get_attr_names() 
+    {
+        return array('version', 'n', 'e', 'd', 'p', 'q', 'dmp1', 'dmq1', 'iqmp');
+    }
+
+    /**
+     * Parses ASN.1 string [$str] starting form position [$pos].
+     * Returns tag and string value of parsed object.
+     *
+     * @param string                 $str
+     * @param int                    &$pos
+     * @param Crypt_RSA_ErrorHandler &$err_handler
+     *
+     * @return mixed    Array('tag' => ..., 'str' => ...) on success, false on error
+     * @access private
+     */
+    function _ASN1Parse($str, &$pos, &$err_handler)
+    {
+        $max_pos = strlen($str);
+        if ($max_pos < 2) {
+            $err_handler->pushError("ASN.1 string too short");
+            return false;
+        }
+
+        // get ASN.1 tag value
+        $tag = ord($str[$pos++]) & 0x1f;
+        if ($tag == 0x1f) {
+            $tag = 0;
+            do {
+                $n = ord($str[$pos++]);
+                $tag <<= 7;
+                $tag |= $n & 0x7f;
+            } while (($n & 0x80) && $pos < $max_pos);
+        }
+        if ($pos >= $max_pos) {
+            $err_handler->pushError("ASN.1 string too short");
+            return false;
+        }
+
+        // get ASN.1 object length
+        $len = ord($str[$pos++]);
+        if ($len & 0x80) {
+            $n = $len & 0x1f;
+            $len = 0;
+            while ($n-- && $pos < $max_pos) {
+                $len <<= 8;
+                $len |= ord($str[$pos++]);
+            }
+        }
+        if ($pos >= $max_pos || $len > $max_pos - $pos) {
+            $err_handler->pushError("ASN.1 string too short");
+            return false;
+        }
+
+        // get string value of ASN.1 object
+        $str = substr($str, $pos, $len);
+
+        return array(
+            'tag' => $tag,
+            'str' => $str,
+        );
+    }
+
+    /**
+     * Parses ASN.1 sting [$str] starting from position [$pos].
+     * Returns string representation of number, which can be passed
+     * in bin2int() function of math wrapper.
+     *
+     * @param string                 $str
+     * @param int                    &$pos
+     * @param Crypt_RSA_ErrorHandler &$err_handler
+     *
+     * @return mixed   string representation of parsed number on success, false on error
+     * @access private
+     */
+    function _ASN1ParseInt($str, &$pos, &$err_handler)
+    {
+        $tmp = Crypt_RSA_KeyPair::_ASN1Parse($str, $pos, $err_handler);
+        if ($err_handler->isError()) {
+            return false;
+        }
+        if ($tmp['tag'] != 0x02) {
+            $errstr = sprintf("wrong ASN tag value: 0x%02x. Expected 0x02 (INTEGER)", $tmp['tag']);
+            $err_handler->pushError($errstr);
+            return false;
+        }
+        $pos += strlen($tmp['str']);
+
+        return strrev($tmp['str']);
+    }
+
+    /**
+     * Constructs ASN.1 string from tag $tag and object $str
+     *
+     * @param string $str            ASN.1 object string
+     * @param int    $tag            ASN.1 tag value
+     * @param bool   $is_constructed 
+     * @param bool   $is_private 
+     *
+     * @return ASN.1-encoded string
+     * @access private
+     */
+    function _ASN1Store($str, $tag, $is_constructed = false, $is_private = false)
+    {
+        $out = '';
+
+        // encode ASN.1 tag value
+        $tag_ext = ($is_constructed ? 0x20 : 0) | ($is_private ? 0xc0 : 0);
+        if ($tag < 0x1f) {
+            $out .= chr($tag | $tag_ext);
+        } else {
+            $out .= chr($tag_ext | 0x1f);
+            $tmp = chr($tag & 0x7f);
+            $tag >>= 7;
+            while ($tag) {
+                $tmp .= chr(($tag & 0x7f) | 0x80);
+                $tag >>= 7;
+            }
+            $out .= strrev($tmp);
+        }
+
+        // encode ASN.1 object length
+        $len = strlen($str);
+        if ($len < 0x7f) {
+            $out .= chr($len);
+        } else {
+            $tmp = '';
+            $n = 0;
+            while ($len) {
+                $tmp .= chr($len & 0xff);
+                $len >>= 8;
+                $n++;
+            }
+            $out .= chr($n | 0x80);
+            $out .= strrev($tmp);
+        }
+
+        return $out . $str;
+    }
+
+    /**
+     * Constructs ASN.1 string from binary representation of big integer
+     *
+     * @param string $str binary representation of big integer
+     *
+     * @return ASN.1-encoded string
+     * @access private
+     */
+    function _ASN1StoreInt($str)
+    {
+        $str = strrev($str);
+        return Crypt_RSA_KeyPair::_ASN1Store($str, 0x02);
+    }
+
+    /**
+     * Crypt_RSA_KeyPair constructor.
+     *
+     * Wrapper: name of math wrapper, which will be used to
+     *        perform different operations with big integers.
+     *        See contents of Crypt/RSA/Math folder for examples of wrappers.
+     *        Read docs/Crypt_RSA/docs/math_wrappers.txt for details.
+     *
+     * @param int      $key_len          bit length of key pair, which will be generated in constructor
+     * @param string   $wrapper_name     wrapper name
+     * @param string   $error_handler    name of error handler function
+     * @param callback $random_generator function which will be used as random generator
+     *
+     * @access public
+     */
+    function Crypt_RSA_KeyPair($key_len, $wrapper_name = 'default', $error_handler = '', $random_generator = null)
+    {
+        // set error handler
+        $this->setErrorHandler($error_handler);
+        // try to load math wrapper
+        $obj = &Crypt_RSA_MathLoader::loadWrapper($wrapper_name);
+        if ($this->isError($obj)) {
+            // error during loading of math wrapper
+            $this->pushError($obj);
+            return;
+        }
+        $this->_math_obj = &$obj;
+
+        // set random generator
+        if (!$this->setRandomGenerator($random_generator)) {
+            // error in setRandomGenerator() function
+            return;
+        }
+
+        if (is_array($key_len)) {
+            // ugly BC hack - it is possible to pass RSA private key attributes [version, n, e, d, p, q, dmp1, dmq1, iqmp]
+            // as associative array instead of key length to Crypt_RSA_KeyPair constructor
+            $rsa_attrs = $key_len;
+
+            // convert attributes to big integers
+            $attr_names = $this->_get_attr_names();
+            foreach ($attr_names as $attr) {
+                if (!isset($rsa_attrs[$attr])) {
+                    $this->pushError("missing required RSA attribute [$attr]");
+                    return;
+                }
+                ${$attr} = $this->_math_obj->bin2int($rsa_attrs[$attr]);
+            }
+
+            // check primality of p and q
+            if (!$this->_math_obj->isPrime($p)) {
+                $this->pushError("[p] must be prime");
+                return;
+            }
+            if (!$this->_math_obj->isPrime($q)) {
+                $this->pushError("[q] must be prime");
+                return;
+            }
+
+            // check n = p * q
+            $n1 = $this->_math_obj->mul($p, $q);
+            if ($this->_math_obj->cmpAbs($n, $n1)) {
+                $this->pushError("n != p * q");
+                return;
+            }
+
+            // check e * d = 1 mod (p-1) * (q-1)
+            $p1 = $this->_math_obj->dec($p);
+            $q1 = $this->_math_obj->dec($q);
+            $p1q1 = $this->_math_obj->mul($p1, $q1);
+            $ed = $this->_math_obj->mul($e, $d);
+            $one = $this->_math_obj->mod($ed, $p1q1);
+            if (!$this->_math_obj->isOne($one)) {
+                $this->pushError("e * d != 1 mod (p-1)*(q-1)");
+                return;
+            }
+
+            // check dmp1 = d mod (p-1)
+            $dmp = $this->_math_obj->mod($d, $p1);
+            if ($this->_math_obj->cmpAbs($dmp, $dmp1)) {
+                $this->pushError("dmp1 != d mod (p-1)");
+                return;
+            }
+
+            // check dmq1 = d mod (q-1)
+            $dmq = $this->_math_obj->mod($d, $q1);
+            if ($this->_math_obj->cmpAbs($dmq, $dmq1)) {
+                $this->pushError("dmq1 != d mod (q-1)");
+                return;
+            }
+
+            // check iqmp = 1/q mod p
+            $q1 = $this->_math_obj->invmod($iqmp, $p);
+            if ($this->_math_obj->cmpAbs($q, $q1)) {
+                $this->pushError("iqmp != 1/q mod p");
+                return;
+            }
+
+            // try to create public key object
+            $public_key = &new Crypt_RSA_Key($rsa_attrs['n'], $rsa_attrs['e'], 'public', $wrapper_name, $error_handler);
+            if ($public_key->isError()) {
+                // error during creating public object
+                $this->pushError($public_key->getLastError());
+                return;
+            }
+
+            // try to create private key object
+            $private_key = &new Crypt_RSA_Key($rsa_attrs['n'], $rsa_attrs['d'], 'private', $wrapper_name, $error_handler);
+            if ($private_key->isError()) {
+                // error during creating private key object
+                $this->pushError($private_key->getLastError());
+                return;
+            }
+
+            $this->_public_key = $public_key;
+            $this->_private_key = $private_key;
+            $this->_key_len = $public_key->getKeyLength();
+            $this->_attrs = $rsa_attrs;
+        } else {
+            // generate key pair
+            if (!$this->generate($key_len)) {
+                // error during generating key pair
+                return;
+            }
+        }
+    }
+
+    /**
+     * Crypt_RSA_KeyPair factory.
+     *
+     * Wrapper - Name of math wrapper, which will be used to
+     *        perform different operations with big integers.
+     *        See contents of Crypt/RSA/Math folder for examples of wrappers.
+     *        Read docs/Crypt_RSA/docs/math_wrappers.txt for details.
+     *
+     * @param int      $key_len          bit length of key pair, which will be generated in constructor
+     * @param string   $wrapper_name     wrapper name
+     * @param string   $error_handler    name of error handler function
+     * @param callback $random_generator function which will be used as random generator
+     *
+     * @return object   new Crypt_RSA_KeyPair object on success or PEAR_Error object on failure
+     * @access public
+     */
+    function &factory($key_len, $wrapper_name = 'default', $error_handler = '', $random_generator = null)
+    {
+        $obj = &new Crypt_RSA_KeyPair($key_len, $wrapper_name, $error_handler, $random_generator);
+        if ($obj->isError()) {
+            // error during creating a new object. Return PEAR_Error object
+            return $obj->getLastError();
+        }
+        // object created successfully. Return it
+        return $obj;
+    }
+
+    /**
+     * Generates new Crypt_RSA key pair with length $key_len.
+     * If $key_len is missed, use an old key length from $this->_key_len
+     *
+     * @param int $key_len bit length of key pair, which will be generated
+     *
+     * @return bool         true on success or false on error
+     * @access public
+     */
+    function generate($key_len = null)
+    {
+        if (is_null($key_len)) {
+            // use an old key length
+            $key_len = $this->_key_len;
+            if (is_null($key_len)) {
+                $this->pushError('missing key_len parameter', CRYPT_RSA_ERROR_MISSING_KEY_LEN);
+                return false;
+            }
+        }
+
+        // minimal key length is 8 bit ;)
+        if ($key_len < 8) {
+            $key_len = 8;
+        }
+        // store key length in the _key_len property
+        $this->_key_len = $key_len;
+
+        // set [e] to 0x10001 (65537)
+        $e = $this->_math_obj->bin2int("\x01\x00\x01");
+
+        // generate [p], [q] and [n]
+        $p_len = intval(($key_len + 1) / 2);
+        $q_len = $key_len - $p_len;
+        $p1 = $q1 = 0;
+        do {
+            // generate prime number [$p] with length [$p_len] with the following condition:
+            // GCD($e, $p - 1) = 1
+            do {
+                $p = $this->_math_obj->getPrime($p_len, $this->_random_generator);
+                $p1 = $this->_math_obj->dec($p);
+                $tmp = $this->_math_obj->GCD($e, $p1);
+            } while (!$this->_math_obj->isOne($tmp));
+            // generate prime number [$q] with length [$q_len] with the following conditions:
+            // GCD($e, $q - 1) = 1
+            // $q != $p
+            do {
+                $q = $this->_math_obj->getPrime($q_len, $this->_random_generator);
+                $q1 = $this->_math_obj->dec($q);
+                $tmp = $this->_math_obj->GCD($e, $q1);
+            } while (!$this->_math_obj->isOne($tmp) && !$this->_math_obj->cmpAbs($q, $p));
+            // if (p < q), then exchange them
+            if ($this->_math_obj->cmpAbs($p, $q) < 0) {
+                $tmp = $p;
+                $p = $q;
+                $q = $tmp;
+                $tmp = $p1;
+                $p1 = $q1;
+                $q1 = $tmp;
+            }
+            // calculate n = p * q
+            $n = $this->_math_obj->mul($p, $q);
+        } while ($this->_math_obj->bitLen($n) != $key_len);
+
+        // calculate d = 1/e mod (p - 1) * (q - 1)
+        $pq = $this->_math_obj->mul($p1, $q1);
+        $d = $this->_math_obj->invmod($e, $pq);
+
+        // calculate dmp1 = d mod (p - 1)
+        $dmp1 = $this->_math_obj->mod($d, $p1);
+
+        // calculate dmq1 = d mod (q - 1)
+        $dmq1 = $this->_math_obj->mod($d, $q1);
+
+        // calculate iqmp = 1/q mod p
+        $iqmp = $this->_math_obj->invmod($q, $p);
+
+        // store RSA keypair attributes
+        $this->_attrs = array(
+            'version' => "\x00",
+            'n' => $this->_math_obj->int2bin($n),
+            'e' => $this->_math_obj->int2bin($e),
+            'd' => $this->_math_obj->int2bin($d),
+            'p' => $this->_math_obj->int2bin($p),
+            'q' => $this->_math_obj->int2bin($q),
+            'dmp1' => $this->_math_obj->int2bin($dmp1),
+            'dmq1' => $this->_math_obj->int2bin($dmq1),
+            'iqmp' => $this->_math_obj->int2bin($iqmp),
+        );
+
+        $n = $this->_attrs['n'];
+        $e = $this->_attrs['e'];
+        $d = $this->_attrs['d'];
+
+        // try to create public key object
+        $obj = &new Crypt_RSA_Key($n, $e, 'public', $this->_math_obj->getWrapperName(), $this->_error_handler);
+        if ($obj->isError()) {
+            // error during creating public object
+            $this->pushError($obj->getLastError());
+            return false;
+        }
+        $this->_public_key = &$obj;
+
+        // try to create private key object
+        $obj = &new Crypt_RSA_Key($n, $d, 'private', $this->_math_obj->getWrapperName(), $this->_error_handler);
+        if ($obj->isError()) {
+            // error during creating private key object
+            $this->pushError($obj->getLastError());
+            return false;
+        }
+        $this->_private_key = &$obj;
+
+        return true; // key pair successfully generated
+    }
+
+    /**
+     * Returns public key from the pair
+     *
+     * @return object  public key object of class Crypt_RSA_Key
+     * @access public
+     */
+    function getPublicKey()
+    {
+        return $this->_public_key;
+    }
+
+    /**
+     * Returns private key from the pair
+     *
+     * @return object   private key object of class Crypt_RSA_Key
+     * @access public
+     */
+    function getPrivateKey()
+    {
+        return $this->_private_key;
+    }
+
+    /**
+     * Sets name of random generator function for key generation.
+     * If parameter is skipped, then sets to default random generator.
+     *
+     * Random generator function must return integer with at least 8 lower
+     * significant bits, which will be used as random values.
+     *
+     * @param string $random_generator name of random generator function
+     *
+     * @return bool                     true on success or false on error
+     * @access public
+     */
+    function setRandomGenerator($random_generator = null)
+    {
+        static $default_random_generator = null;
+
+        if (is_string($random_generator)) {
+            // set user's random generator
+            if (!function_exists($random_generator)) {
+                $this->pushError("can't find random generator function with name [{$random_generator}]");
+                return false;
+            }
+            $this->_random_generator = $random_generator;
+        } else {
+            // set default random generator
+            $this->_random_generator = is_null($default_random_generator) ?
+                ($default_random_generator = create_function('', '$a=explode(" ",microtime());return(int)($a[0]*1000000);')) :
+                $default_random_generator;
+        }
+        return true;
+    }
+
+    /**
+     * Returns length of each key in the key pair
+     *
+     * @return int  bit length of each key in key pair
+     * @access public
+     */
+    function getKeyLength()
+    {
+        return $this->_key_len;
+    }
+
+    /**
+     * Retrieves RSA keypair from PEM-encoded string, containing RSA private key.
+     * Example of such string:
+     * -----BEGIN RSA PRIVATE KEY-----
+     * MCsCAQACBHtvbSECAwEAAQIEeYrk3QIDAOF3AgMAjCcCAmdnAgJMawIDALEk
+     * -----END RSA PRIVATE KEY-----
+     *
+     * Wrapper: Name of math wrapper, which will be used to
+     * perform different operations with big integers.
+     * See contents of Crypt/RSA/Math folder for examples of wrappers.
+     * Read docs/Crypt_RSA/docs/math_wrappers.txt for details.
+     *
+     * @param string $str           PEM-encoded string
+     * @param string $wrapper_name  Wrapper name
+     * @param string $error_handler name of error handler function
+     *
+     * @return Crypt_RSA_KeyPair object on success, PEAR_Error object on error
+     * @access public
+     * @static
+     */
+    function &fromPEMString($str, $wrapper_name = 'default', $error_handler = '')
+    {
+        if (isset($this)) {
+            if ($wrapper_name == 'default') {
+                $wrapper_name = $this->_math_obj->getWrapperName();
+            }
+            if ($error_handler == '') {
+                $error_handler = $this->_error_handler;
+            }
+        }
+        $err_handler = &new Crypt_RSA_ErrorHandler;
+        $err_handler->setErrorHandler($error_handler);
+
+        // search for base64-encoded private key
+        if (!preg_match('/-----BEGIN RSA PRIVATE KEY-----([^-]+)-----END RSA PRIVATE KEY-----/', $str, $matches)) {
+            $err_handler->pushError("can't find RSA private key in the string [{$str}]");
+            return $err_handler->getLastError();
+        }
+
+        // parse private key. It is ASN.1-encoded
+        $str = base64_decode($matches[1]);
+        $pos = 0;
+        $tmp = Crypt_RSA_KeyPair::_ASN1Parse($str, $pos, $err_handler);
+        if ($err_handler->isError()) {
+            return $err_handler->getLastError();
+        }
+        if ($tmp['tag'] != 0x10) {
+            $errstr = sprintf("wrong ASN tag value: 0x%02x. Expected 0x10 (SEQUENCE)", $tmp['tag']);
+            $err_handler->pushError($errstr);
+            return $err_handler->getLastError();
+        }
+
+        // parse ASN.1 SEQUENCE for RSA private key
+        $attr_names = Crypt_RSA_KeyPair::_get_attr_names();
+        $n = sizeof($attr_names);
+        $rsa_attrs = array();
+        for ($i = 0; $i < $n; $i++) {
+            $tmp = Crypt_RSA_KeyPair::_ASN1ParseInt($str, $pos, $err_handler);
+            if ($err_handler->isError()) {
+                return $err_handler->getLastError();
+            }
+            $attr = $attr_names[$i];
+            $rsa_attrs[$attr] = $tmp;
+        }
+
+        // create Crypt_RSA_KeyPair object.
+        $keypair = &new Crypt_RSA_KeyPair($rsa_attrs, $wrapper_name, $error_handler);
+        if ($keypair->isError()) {
+            return $keypair->getLastError();
+        }
+
+        return $keypair;
+    }
+
+    /**
+     * converts keypair to PEM-encoded string, which can be stroed in 
+     * .pem compatible files, contianing RSA private key.
+     *
+     * @return string PEM-encoded keypair on success, false on error
+     * @access public
+     */
+    function toPEMString()
+    {
+        // store RSA private key attributes into ASN.1 string
+        $str = '';
+        $attr_names = $this->_get_attr_names();
+        $n = sizeof($attr_names);
+        $rsa_attrs = $this->_attrs;
+        for ($i = 0; $i < $n; $i++) {
+            $attr = $attr_names[$i];
+            if (!isset($rsa_attrs[$attr])) {
+                $this->pushError("Cannot find value for ASN.1 attribute [$attr]");
+                return false;
+            }
+            $tmp = $rsa_attrs[$attr];
+            $str .= Crypt_RSA_KeyPair::_ASN1StoreInt($tmp);
+        }
+
+        // prepend $str by ASN.1 SEQUENCE (0x10) header
+        $str = Crypt_RSA_KeyPair::_ASN1Store($str, 0x10, true);
+
+        // encode and format PEM string
+        $str = base64_encode($str);
+        $str = chunk_split($str, 64, "\n");
+        return "-----BEGIN RSA PRIVATE KEY-----\n$str-----END RSA PRIVATE KEY-----\n";
+    }
+
+    /**
+     * Compares keypairs in Crypt_RSA_KeyPair objects $this and $key_pair
+     *
+     * @param Crypt_RSA_KeyPair $key_pair  keypair to compare
+     *
+     * @return bool  true, if keypair stored in $this equal to keypair stored in $key_pair
+     * @access public
+     */
+    function isEqual($key_pair)
+    {
+        $attr_names = $this->_get_attr_names();
+        foreach ($attr_names as $attr) {
+            if ($this->_attrs[$attr] != $key_pair->_attrs[$attr]) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
+
+?>
diff --git a/plugins/OStatus/extlib/Crypt/RSA/Math/BCMath.php b/plugins/OStatus/extlib/Crypt/RSA/Math/BCMath.php
new file mode 100644 (file)
index 0000000..646ff67
--- /dev/null
@@ -0,0 +1,482 @@
+<?php
+/**
+ * Crypt_RSA allows to do following operations:
+ *     - key pair generation
+ *     - encryption and decryption
+ *     - signing and sign validation
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.0 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license@php.net so we can mail you a copy immediately.
+ *
+ * @category   Encryption
+ * @package    Crypt_RSA
+ * @author     Alexander Valyalkin <valyala@gmail.com>
+ * @copyright  2006 Alexander Valyalkin
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    1.2.0b
+ * @link       http://pear.php.net/package/Crypt_RSA
+ */
+
+/**
+ * Crypt_RSA_Math_BCMath class.
+ *
+ * Provides set of math functions, which are used by Crypt_RSA package
+ * This class is a wrapper for PHP BCMath extension.
+ * See http://php.net/manual/en/ref.bc.php for details.
+ *
+ * @category   Encryption
+ * @package    Crypt_RSA
+ * @author     Alexander Valyalkin <valyala@gmail.com>
+ * @copyright  2005, 2006 Alexander Valyalkin
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @link       http://pear.php.net/package/Crypt_RSA
+ * @version    @package_version@
+ * @access     public
+ */
+class Crypt_RSA_Math_BCMath
+{
+    /**
+     * error description
+     *
+     * @var string
+     * @access public
+     */
+    var $errstr = '';
+
+    /**
+     * Performs Miller-Rabin primality test for number $num 
+     * with base $base. Returns true, if $num is strong pseudoprime
+     * by base $base. Else returns false.
+     *
+     * @param string $num
+     * @param string $base
+     * @return bool
+     * @access private
+     */
+    function _millerTest($num, $base)
+    {
+        if (!bccomp($num, '1')) {
+            // 1 is not prime ;)
+            return false;
+        }
+        $tmp = bcsub($num, '1');
+
+        $zero_bits = 0;
+        while (!bccomp(bcmod($tmp, '2'), '0')) {
+            $zero_bits++;
+            $tmp = bcdiv($tmp, '2');
+        }
+
+        $tmp = $this->powmod($base, $tmp, $num);
+        if (!bccomp($tmp, '1')) {
+            // $num is probably prime
+            return true;
+        }
+
+        while ($zero_bits--) {
+            if (!bccomp(bcadd($tmp, '1'), $num)) {
+                // $num is probably prime
+                return true;
+            }
+            $tmp = $this->powmod($tmp, '2', $num);
+        }
+        // $num is composite
+        return false;
+    }
+
+    /**
+     * Crypt_RSA_Math_BCMath constructor.
+     * Checks an existance of PHP BCMath extension.
+     * On failure saves error description in $this->errstr
+     *
+     * @access public
+     */
+    function Crypt_RSA_Math_BCMath()
+    {
+        if (!extension_loaded('bcmath')) {
+            if (!@dl('bcmath.' . PHP_SHLIB_SUFFIX) && !@dl('php_bcmath.' . PHP_SHLIB_SUFFIX)) {
+                // cannot load BCMath extension. Set error string
+                $this->errstr = 'Crypt_RSA package requires the BCMath extension. See http://php.net/manual/en/ref.bc.php for details';
+                return;
+            }
+        }
+    }
+
+    /**
+     * Transforms binary representation of large integer into its native form.
+     * 
+     * Example of transformation:
+     *    $str = "\x12\x34\x56\x78\x90";
+     *    $num = 0x9078563412;
+     *
+     * @param string $str
+     * @return string
+     * @access public
+     */
+    function bin2int($str)
+    {
+        $result = '0';
+        $n = strlen($str);
+        do {
+            $result = bcadd(bcmul($result, '256'), ord($str{--$n}));
+        } while ($n > 0);
+        return $result;
+    }
+
+    /**
+     * Transforms large integer into binary representation.
+     * 
+     * Example of transformation:
+     *    $num = 0x9078563412;
+     *    $str = "\x12\x34\x56\x78\x90";
+     *
+     * @param string $num
+     * @return string
+     * @access public
+     */
+    function int2bin($num)
+    {
+        $result = '';
+        do {
+            $result .= chr(bcmod($num, '256'));
+            $num = bcdiv($num, '256');
+        } while (bccomp($num, '0'));
+        return $result;
+    }
+
+    /**
+     * Calculates pow($num, $pow) (mod $mod)
+     *
+     * @param string $num
+     * @param string $pow
+     * @param string $mod
+     * @return string
+     * @access public
+     */
+    function powmod($num, $pow, $mod)
+    {
+        if (function_exists('bcpowmod')) {
+            // bcpowmod is only available under PHP5
+            return bcpowmod($num, $pow, $mod);
+        }
+
+        // emulate bcpowmod
+        $result = '1';
+        do {
+            if (!bccomp(bcmod($pow, '2'), '1')) {
+                $result = bcmod(bcmul($result, $num), $mod);
+            }
+            $num = bcmod(bcpow($num, '2'), $mod);
+            $pow = bcdiv($pow, '2');
+        } while (bccomp($pow, '0'));
+        return $result;
+    }
+
+    /**
+     * Calculates $num1 * $num2
+     *
+     * @param string $num1
+     * @param string $num2
+     * @return string
+     * @access public
+     */
+    function mul($num1, $num2)
+    {
+        return bcmul($num1, $num2);
+    }
+
+    /**
+     * Calculates $num1 % $num2
+     *
+     * @param string $num1
+     * @param string $num2
+     * @return string
+     * @access public
+     */
+    function mod($num1, $num2)
+    {
+        return bcmod($num1, $num2);
+    }
+
+    /**
+     * Compares abs($num1) to abs($num2).
+     * Returns:
+     *   -1, if abs($num1) < abs($num2)
+     *   0, if abs($num1) == abs($num2)
+     *   1, if abs($num1) > abs($num2)
+     *
+     * @param string $num1
+     * @param string $num2
+     * @return int
+     * @access public
+     */
+    function cmpAbs($num1, $num2)
+    {
+        return bccomp($num1, $num2);
+    }
+
+    /**
+     * Tests $num on primality. Returns true, if $num is strong pseudoprime.
+     * Else returns false.
+     *
+     * @param string $num
+     * @return bool
+     * @access private
+     */
+    function isPrime($num)
+    {
+        static $primes = null;
+        static $primes_cnt = 0;
+        if (is_null($primes)) {
+            // generate all primes up to 10000
+            $primes = array();
+            for ($i = 0; $i < 10000; $i++) {
+                $primes[] = $i;
+            }
+            $primes[0] = $primes[1] = 0;
+            for ($i = 2; $i < 100; $i++) {
+                while (!$primes[$i]) {
+                    $i++;
+                }
+                $j = $i;
+                for ($j += $i; $j < 10000; $j += $i) {
+                    $primes[$j] = 0;
+                }
+            }
+            $j = 0;
+            for ($i = 0; $i < 10000; $i++) {
+                if ($primes[$i]) {
+                    $primes[$j++] = $primes[$i];
+                }
+            }
+            $primes_cnt = $j;
+        }
+
+        // try to divide number by small primes
+        for ($i = 0; $i < $primes_cnt; $i++) {
+            if (bccomp($num, $primes[$i]) <= 0) {
+                // number is prime
+                return true;
+            }
+            if (!bccomp(bcmod($num, $primes[$i]), '0')) {
+                // number divides by $primes[$i]
+                return false;
+            }
+        }
+
+        /*
+            try Miller-Rabin's probable-primality test for first
+            7 primes as bases
+        */
+        for ($i = 0; $i < 7; $i++) {
+            if (!$this->_millerTest($num, $primes[$i])) {
+                // $num is composite
+                return false;
+            }
+        }
+        // $num is strong pseudoprime
+        return true;
+    }
+
+    /**
+     * Generates prime number with length $bits_cnt
+     * using $random_generator as random generator function.
+     *
+     * @param int $bits_cnt
+     * @param string $rnd_generator
+     * @access public
+     */
+    function getPrime($bits_cnt, $random_generator)
+    {
+        $bytes_n = intval($bits_cnt / 8);
+        $bits_n = $bits_cnt % 8;
+        do {
+            $str = '';
+            for ($i = 0; $i < $bytes_n; $i++) {
+                $str .= chr(call_user_func($random_generator) & 0xff);
+            }
+            $n = call_user_func($random_generator) & 0xff;
+            $n |= 0x80;
+            $n >>= 8 - $bits_n;
+            $str .= chr($n);
+            $num = $this->bin2int($str);
+
+            // search for the next closest prime number after [$num]
+            if (!bccomp(bcmod($num, '2'), '0')) {
+                $num = bcadd($num, '1');
+            }
+            while (!$this->isPrime($num)) {
+                $num = bcadd($num, '2');
+            }
+        } while ($this->bitLen($num) != $bits_cnt);
+        return $num;
+    }
+
+    /**
+     * Calculates $num - 1
+     *
+     * @param string $num
+     * @return string
+     * @access public
+     */
+    function dec($num)
+    {
+        return bcsub($num, '1');
+    }
+
+    /**
+     * Returns true, if $num is equal to one. Else returns false
+     *
+     * @param string $num
+     * @return bool
+     * @access public
+     */
+    function isOne($num)
+    {
+        return !bccomp($num, '1');
+    }
+
+    /**
+     * Finds greatest common divider (GCD) of $num1 and $num2
+     *
+     * @param string $num1
+     * @param string $num2
+     * @return string
+     * @access public
+     */
+    function GCD($num1, $num2)
+    {
+        do {
+            $tmp = bcmod($num1, $num2);
+            $num1 = $num2;
+            $num2 = $tmp;
+        } while (bccomp($num2, '0'));
+        return $num1;
+    }
+
+    /**
+     * Finds inverse number $inv for $num by modulus $mod, such as:
+     *     $inv * $num = 1 (mod $mod)
+     *
+     * @param string $num
+     * @param string $mod
+     * @return string
+     * @access public
+     */
+    function invmod($num, $mod)
+    {
+        $x = '1';
+        $y = '0';
+        $num1 = $mod;
+        do {
+            $tmp = bcmod($num, $num1);
+            $q = bcdiv($num, $num1);
+            $num = $num1;
+            $num1 = $tmp;
+
+            $tmp = bcsub($x, bcmul($y, $q));
+            $x = $y;
+            $y = $tmp;
+        } while (bccomp($num1, '0'));
+        if (bccomp($x, '0') < 0) {
+            $x = bcadd($x, $mod);
+        }
+        return $x;
+    }
+
+    /**
+     * Returns bit length of number $num
+     *
+     * @param string $num
+     * @return int
+     * @access public
+     */
+    function bitLen($num)
+    {
+        $tmp = $this->int2bin($num);
+        $bit_len = strlen($tmp) * 8;
+        $tmp = ord($tmp{strlen($tmp) - 1});
+        if (!$tmp) {
+            $bit_len -= 8;
+        }
+        else {
+            while (!($tmp & 0x80)) {
+                $bit_len--;
+                $tmp <<= 1;
+            }
+        }
+        return $bit_len;
+    }
+
+    /**
+     * Calculates bitwise or of $num1 and $num2,
+     * starting from bit $start_pos for number $num1
+     *
+     * @param string $num1
+     * @param string $num2
+     * @param int $start_pos
+     * @return string
+     * @access public
+     */
+    function bitOr($num1, $num2, $start_pos)
+    {
+        $start_byte = intval($start_pos / 8);
+        $start_bit = $start_pos % 8;
+        $tmp1 = $this->int2bin($num1);
+
+        $num2 = bcmul($num2, 1 << $start_bit);
+        $tmp2 = $this->int2bin($num2);
+        if ($start_byte < strlen($tmp1)) {
+            $tmp2 |= substr($tmp1, $start_byte);
+            $tmp1 = substr($tmp1, 0, $start_byte) . $tmp2;
+        }
+        else {
+            $tmp1 = str_pad($tmp1, $start_byte, "\0") . $tmp2;
+        }
+        return $this->bin2int($tmp1);
+    }
+
+    /**
+     * Returns part of number $num, starting at bit
+     * position $start with length $length
+     *
+     * @param string $num
+     * @param int start
+     * @param int length
+     * @return string
+     * @access public
+     */
+    function subint($num, $start, $length)
+    {
+        $start_byte = intval($start / 8);
+        $start_bit = $start % 8;
+        $byte_length = intval($length / 8);
+        $bit_length = $length % 8;
+        if ($bit_length) {
+            $byte_length++;
+        }
+        $num = bcdiv($num, 1 << $start_bit);
+        $tmp = substr($this->int2bin($num), $start_byte, $byte_length);
+        $tmp = str_pad($tmp, $byte_length, "\0");
+        $tmp = substr_replace($tmp, $tmp{$byte_length - 1} & chr(0xff >> (8 - $bit_length)), $byte_length - 1, 1);
+        return $this->bin2int($tmp);
+    }
+
+    /**
+     * Returns name of current wrapper
+     *
+     * @return string name of current wrapper
+     * @access public
+     */
+    function getWrapperName()
+    {
+        return 'BCMath';
+    }
+}
+
+?>
\ No newline at end of file
diff --git a/plugins/OStatus/extlib/Crypt/RSA/Math/BigInt.php b/plugins/OStatus/extlib/Crypt/RSA/Math/BigInt.php
new file mode 100644 (file)
index 0000000..b7ac24c
--- /dev/null
@@ -0,0 +1,313 @@
+<?php
+/**
+ * Crypt_RSA allows to do following operations:
+ *     - key pair generation
+ *     - encryption and decryption
+ *     - signing and sign validation
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.0 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license@php.net so we can mail you a copy immediately.
+ *
+ * @category   Encryption
+ * @package    Crypt_RSA
+ * @author     Alexander Valyalkin <valyala@gmail.com>
+ * @copyright  2005, 2006 Alexander Valyalkin
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    1.2.0b
+ * @link       http://pear.php.net/package/Crypt_RSA
+ */
+
+/**
+ * Crypt_RSA_Math_BigInt class.
+ *
+ * Provides set of math functions, which are used by Crypt_RSA package
+ * This class is a wrapper for big_int PECL extension,
+ * which could be loaded from http://pecl.php.net/packages/big_int
+ *
+ * @category   Encryption
+ * @package    Crypt_RSA
+ * @author     Alexander Valyalkin <valyala@gmail.com>
+ * @copyright  2005, 2006 Alexander Valyalkin
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @link       http://pear.php.net/package/Crypt_RSA
+ * @version    @package_version@
+ * @access     public
+ */
+class Crypt_RSA_Math_BigInt
+{
+    /**
+     * error description
+     *
+     * @var string
+     * @access public
+     */
+    var $errstr = '';
+
+    /**
+     * Crypt_RSA_Math_BigInt constructor.
+     * Checks an existance of big_int PECL math package.
+     * This package is available at http://pecl.php.net/packages/big_int
+     * On failure saves error description in $this->errstr
+     *
+     * @access public
+     */
+    function Crypt_RSA_Math_BigInt()
+    {
+        if (!extension_loaded('big_int')) {
+            if (!@dl('big_int.' . PHP_SHLIB_SUFFIX) && !@dl('php_big_int.' . PHP_SHLIB_SUFFIX)) {
+                // cannot load big_int extension
+                $this->errstr = 'Crypt_RSA package requires big_int PECL package. ' .
+                     'It is available at http://pecl.php.net/packages/big_int';
+                return;
+            }
+        }
+
+        // check version of big_int extension ( Crypt_RSA requires version 1.0.2 and higher )
+        if (!in_array('bi_info', get_extension_funcs('big_int'))) {
+            // there is no bi_info() function in versions, older than 1.0.2
+            $this->errstr = 'Crypt_RSA package requires big_int package version 1.0.2 and higher';
+        }
+    }
+
+    /**
+     * Transforms binary representation of large integer into its native form.
+     * 
+     * Example of transformation:
+     *    $str = "\x12\x34\x56\x78\x90";
+     *    $num = 0x9078563412;
+     *
+     * @param string $str
+     * @return big_int resource
+     * @access public
+     */
+    function bin2int($str)
+    {
+        return bi_unserialize($str);
+    }
+
+    /**
+     * Transforms large integer into binary representation.
+     * 
+     * Example of transformation:
+     *    $num = 0x9078563412;
+     *    $str = "\x12\x34\x56\x78\x90";
+     *
+     * @param big_int resource $num
+     * @return string
+     * @access public
+     */
+    function int2bin($num)
+    {
+        return bi_serialize($num);
+    }
+
+    /**
+     * Calculates pow($num, $pow) (mod $mod)
+     *
+     * @param big_int resource $num
+     * @param big_int resource $pow
+     * @param big_int resource $mod
+     * @return big_int resource
+     * @access public
+     */
+    function powmod($num, $pow, $mod)
+    {
+        return bi_powmod($num, $pow, $mod);
+    }
+
+    /**
+     * Calculates $num1 * $num2
+     *
+     * @param big_int resource $num1
+     * @param big_int resource $num2
+     * @return big_int resource
+     * @access public
+     */
+    function mul($num1, $num2)
+    {
+        return bi_mul($num1, $num2);
+    }
+
+    /**
+     * Calculates $num1 % $num2
+     *
+     * @param string $num1
+     * @param string $num2
+     * @return string
+     * @access public
+     */
+    function mod($num1, $num2)
+    {
+        return bi_mod($num1, $num2);
+    }
+
+    /**
+     * Compares abs($num1) to abs($num2).
+     * Returns:
+     *   -1, if abs($num1) < abs($num2)
+     *   0, if abs($num1) == abs($num2)
+     *   1, if abs($num1) > abs($num2)
+     *
+     * @param big_int resource $num1
+     * @param big_int resource $num2
+     * @return int
+     * @access public
+     */
+    function cmpAbs($num1, $num2)
+    {
+        return bi_cmp_abs($num1, $num2);
+    }
+
+    /**
+     * Tests $num on primality. Returns true, if $num is strong pseudoprime.
+     * Else returns false.
+     *
+     * @param string $num
+     * @return bool
+     * @access private
+     */
+    function isPrime($num)
+    {
+        return bi_is_prime($num) ? true : false;
+    }
+
+    /**
+     * Generates prime number with length $bits_cnt
+     * using $random_generator as random generator function.
+     *
+     * @param int $bits_cnt
+     * @param string $rnd_generator
+     * @access public
+     */
+    function getPrime($bits_cnt, $random_generator)
+    {
+        $bytes_n = intval($bits_cnt / 8);
+        $bits_n = $bits_cnt % 8;
+        do {
+            $str = '';
+            for ($i = 0; $i < $bytes_n; $i++) {
+                $str .= chr(call_user_func($random_generator) & 0xff);
+            }
+            $n = call_user_func($random_generator) & 0xff;
+            $n |= 0x80;
+            $n >>= 8 - $bits_n;
+            $str .= chr($n);
+            $num = $this->bin2int($str);
+
+            // search for the next closest prime number after [$num]
+            $num = bi_next_prime($num);
+        } while ($this->bitLen($num) != $bits_cnt);
+        return $num;
+    }
+
+    /**
+     * Calculates $num - 1
+     *
+     * @param big_int resource $num
+     * @return big_int resource
+     * @access public
+     */
+    function dec($num)
+    {
+        return bi_dec($num);
+    }
+
+    /**
+     * Returns true, if $num is equal to 1. Else returns false
+     *
+     * @param big_int resource $num
+     * @return bool
+     * @access public
+     */
+    function isOne($num)
+    {
+        return bi_is_one($num);
+    }
+
+    /**
+     * Finds greatest common divider (GCD) of $num1 and $num2
+     *
+     * @param big_int resource $num1
+     * @param big_int resource $num2
+     * @return big_int resource
+     * @access public
+     */
+    function GCD($num1, $num2)
+    {
+        return bi_gcd($num1, $num2);
+    }
+
+    /**
+     * Finds inverse number $inv for $num by modulus $mod, such as:
+     *     $inv * $num = 1 (mod $mod)
+     *
+     * @param big_int resource $num
+     * @param big_int resource $mod
+     * @return big_int resource
+     * @access public
+     */
+    function invmod($num, $mod)
+    {
+        return bi_invmod($num, $mod);
+    }
+
+    /**
+     * Returns bit length of number $num
+     *
+     * @param big_int resource $num
+     * @return int
+     * @access public
+     */
+    function bitLen($num)
+    {
+        return bi_bit_len($num);
+    }
+
+    /**
+     * Calculates bitwise or of $num1 and $num2,
+     * starting from bit $start_pos for number $num1
+     *
+     * @param big_int resource $num1
+     * @param big_int resource $num2
+     * @param int $start_pos
+     * @return big_int resource
+     * @access public
+     */
+    function bitOr($num1, $num2, $start_pos)
+    {
+        return bi_or($num1, $num2, $start_pos);
+    }
+
+    /**
+     * Returns part of number $num, starting at bit
+     * position $start with length $length
+     *
+     * @param big_int resource $num
+     * @param int start
+     * @param int length
+     * @return big_int resource
+     * @access public
+     */
+    function subint($num, $start, $length)
+    {
+        return bi_subint($num, $start, $length);
+    }
+
+    /**
+     * Returns name of current wrapper
+     *
+     * @return string name of current wrapper
+     * @access public
+     */
+    function getWrapperName()
+    {
+        return 'BigInt';
+    }
+}
+
+?>
\ No newline at end of file
diff --git a/plugins/OStatus/extlib/Crypt/RSA/Math/GMP.php b/plugins/OStatus/extlib/Crypt/RSA/Math/GMP.php
new file mode 100644 (file)
index 0000000..54e4c34
--- /dev/null
@@ -0,0 +1,361 @@
+<?php
+/**
+ * Crypt_RSA allows to do following operations:
+ *     - key pair generation
+ *     - encryption and decryption
+ *     - signing and sign validation
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.0 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license@php.net so we can mail you a copy immediately.
+ *
+ * @category   Encryption
+ * @package    Crypt_RSA
+ * @author     Alexander Valyalkin <valyala@gmail.com>
+ * @copyright  2005, 2006 Alexander Valyalkin
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    1.2.0b
+ * @link       http://pear.php.net/package/Crypt_RSA
+ */
+
+/**
+ * Crypt_RSA_Math_GMP class.
+ *
+ * Provides set of math functions, which are used by Crypt_RSA package
+ * This class is a wrapper for PHP GMP extension.
+ * See http://php.net/gmp for details.
+ *
+ * @category   Encryption
+ * @package    Crypt_RSA
+ * @author     Alexander Valyalkin <valyala@gmail.com>
+ * @copyright  2005, 2006 Alexander Valyalkin
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @link       http://pear.php.net/package/Crypt_RSA
+ * @version    @package_version@
+ * @access     public
+ */
+class Crypt_RSA_Math_GMP
+{
+    /**
+     * error description
+     *
+     * @var string
+     * @access public
+     */
+    var $errstr = '';
+
+    /**
+     * Crypt_RSA_Math_GMP constructor.
+     * Checks an existance of PHP GMP package.
+     * See http://php.net/gmp for details.
+     *
+     * On failure saves error description in $this->errstr
+     *
+     * @access public
+     */
+    function Crypt_RSA_Math_GMP()
+    {
+        if (!extension_loaded('gmp')) {
+            if (!@dl('gmp.' . PHP_SHLIB_SUFFIX) && !@dl('php_gmp.' . PHP_SHLIB_SUFFIX)) {
+                // cannot load GMP extension
+                $this->errstr = 'Crypt_RSA package requires PHP GMP package. ' .
+                     'See http://php.net/gmp for details';
+                return;
+            }
+        }
+    }
+
+    /**
+     * Transforms binary representation of large integer into its native form.
+     * 
+     * Example of transformation:
+     *    $str = "\x12\x34\x56\x78\x90";
+     *    $num = 0x9078563412;
+     *
+     * @param string $str
+     * @return gmp resource
+     * @access public
+     */
+    function bin2int($str)
+    {
+        $result = 0;
+        $n = strlen($str);
+        do {
+            // dirty hack: GMP returns FALSE, when second argument equals to int(0).
+            // so, it must be converted to string '0'
+            $result = gmp_add(gmp_mul($result, 256), strval(ord($str{--$n})));
+        } while ($n > 0);
+        return $result;
+    }
+
+    /**
+     * Transforms large integer into binary representation.
+     * 
+     * Example of transformation:
+     *    $num = 0x9078563412;
+     *    $str = "\x12\x34\x56\x78\x90";
+     *
+     * @param gmp resource $num
+     * @return string
+     * @access public
+     */
+    function int2bin($num)
+    {
+        $result = '';
+        do {
+            $result .= chr(gmp_intval(gmp_mod($num, 256)));
+            $num = gmp_div($num, 256);
+        } while (gmp_cmp($num, 0));
+        return $result;
+    }
+
+    /**
+     * Calculates pow($num, $pow) (mod $mod)
+     *
+     * @param gmp resource $num
+     * @param gmp resource $pow
+     * @param gmp resource $mod
+     * @return gmp resource
+     * @access public
+     */
+    function powmod($num, $pow, $mod)
+    {
+        return gmp_powm($num, $pow, $mod);
+    }
+
+    /**
+     * Calculates $num1 * $num2
+     *
+     * @param gmp resource $num1
+     * @param gmp resource $num2
+     * @return gmp resource
+     * @access public
+     */
+    function mul($num1, $num2)
+    {
+        return gmp_mul($num1, $num2);
+    }
+
+    /**
+     * Calculates $num1 % $num2
+     *
+     * @param string $num1
+     * @param string $num2
+     * @return string
+     * @access public
+     */
+    function mod($num1, $num2)
+    {
+        return gmp_mod($num1, $num2);
+    }
+
+    /**
+     * Compares abs($num1) to abs($num2).
+     * Returns:
+     *   -1, if abs($num1) < abs($num2)
+     *   0, if abs($num1) == abs($num2)
+     *   1, if abs($num1) > abs($num2)
+     *
+     * @param gmp resource $num1
+     * @param gmp resource $num2
+     * @return int
+     * @access public
+     */
+    function cmpAbs($num1, $num2)
+    {
+        return gmp_cmp($num1, $num2);
+    }
+
+    /**
+     * Tests $num on primality. Returns true, if $num is strong pseudoprime.
+     * Else returns false.
+     *
+     * @param string $num
+     * @return bool
+     * @access private
+     */
+    function isPrime($num)
+    {
+        return gmp_prob_prime($num) ? true : false;
+    }
+
+    /**
+     * Generates prime number with length $bits_cnt
+     * using $random_generator as random generator function.
+     *
+     * @param int $bits_cnt
+     * @param string $rnd_generator
+     * @access public
+     */
+    function getPrime($bits_cnt, $random_generator)
+    {
+        $bytes_n = intval($bits_cnt / 8);
+        $bits_n = $bits_cnt % 8;
+        do {
+            $str = '';
+            for ($i = 0; $i < $bytes_n; $i++) {
+                $str .= chr(call_user_func($random_generator) & 0xff);
+            }
+            $n = call_user_func($random_generator) & 0xff;
+            $n |= 0x80;
+            $n >>= 8 - $bits_n;
+            $str .= chr($n);
+            $num = $this->bin2int($str);
+
+            // search for the next closest prime number after [$num]
+            if (!gmp_cmp(gmp_mod($num, '2'), '0')) {
+                $num = gmp_add($num, '1');
+            }
+            while (!gmp_prob_prime($num)) {
+                $num = gmp_add($num, '2');
+            }
+        } while ($this->bitLen($num) != $bits_cnt);
+        return $num;
+    }
+
+    /**
+     * Calculates $num - 1
+     *
+     * @param gmp resource $num
+     * @return gmp resource
+     * @access public
+     */
+    function dec($num)
+    {
+        return gmp_sub($num, 1);
+    }
+
+    /**
+     * Returns true, if $num is equal to one. Else returns false
+     *
+     * @param gmp resource $num
+     * @return bool
+     * @access public
+     */
+    function isOne($num)
+    {
+        return !gmp_cmp($num, 1);
+    }
+
+    /**
+     * Finds greatest common divider (GCD) of $num1 and $num2
+     *
+     * @param gmp resource $num1
+     * @param gmp resource $num2
+     * @return gmp resource
+     * @access public
+     */
+    function GCD($num1, $num2)
+    {
+        return gmp_gcd($num1, $num2);
+    }
+
+    /**
+     * Finds inverse number $inv for $num by modulus $mod, such as:
+     *     $inv * $num = 1 (mod $mod)
+     *
+     * @param gmp resource $num
+     * @param gmp resource $mod
+     * @return gmp resource
+     * @access public
+     */
+    function invmod($num, $mod)
+    {
+        return gmp_invert($num, $mod);
+    }
+
+    /**
+     * Returns bit length of number $num
+     *
+     * @param gmp resource $num
+     * @return int
+     * @access public
+     */
+    function bitLen($num)
+    {
+        $tmp = $this->int2bin($num);
+        $bit_len = strlen($tmp) * 8;
+        $tmp = ord($tmp{strlen($tmp) - 1});
+        if (!$tmp) {
+            $bit_len -= 8;
+        }
+        else {
+            while (!($tmp & 0x80)) {
+                $bit_len--;
+                $tmp <<= 1;
+            }
+        }
+        return $bit_len;
+    }
+
+    /**
+     * Calculates bitwise or of $num1 and $num2,
+     * starting from bit $start_pos for number $num1
+     *
+     * @param gmp resource $num1
+     * @param gmp resource $num2
+     * @param int $start_pos
+     * @return gmp resource
+     * @access public
+     */
+    function bitOr($num1, $num2, $start_pos)
+    {
+        $start_byte = intval($start_pos / 8);
+        $start_bit = $start_pos % 8;
+        $tmp1 = $this->int2bin($num1);
+
+        $num2 = gmp_mul($num2, 1 << $start_bit);
+        $tmp2 = $this->int2bin($num2);
+        if ($start_byte < strlen($tmp1)) {
+            $tmp2 |= substr($tmp1, $start_byte);
+            $tmp1 = substr($tmp1, 0, $start_byte) . $tmp2;
+        }
+        else {
+            $tmp1 = str_pad($tmp1, $start_byte, "\0") . $tmp2;
+        }
+        return $this->bin2int($tmp1);
+    }
+
+    /**
+     * Returns part of number $num, starting at bit
+     * position $start with length $length
+     *
+     * @param gmp resource $num
+     * @param int start
+     * @param int length
+     * @return gmp resource
+     * @access public
+     */
+    function subint($num, $start, $length)
+    {
+        $start_byte = intval($start / 8);
+        $start_bit = $start % 8;
+        $byte_length = intval($length / 8);
+        $bit_length = $length % 8;
+        if ($bit_length) {
+            $byte_length++;
+        }
+        $num = gmp_div($num, 1 << $start_bit);
+        $tmp = substr($this->int2bin($num), $start_byte, $byte_length);
+        $tmp = str_pad($tmp, $byte_length, "\0");
+        $tmp = substr_replace($tmp, $tmp{$byte_length - 1} & chr(0xff >> (8 - $bit_length)), $byte_length - 1, 1);
+        return $this->bin2int($tmp);
+    }
+
+    /**
+     * Returns name of current wrapper
+     *
+     * @return string name of current wrapper
+     * @access public
+     */
+    function getWrapperName()
+    {
+        return 'GMP';
+    }
+}
+
+?>
\ No newline at end of file
diff --git a/plugins/OStatus/extlib/Crypt/RSA/MathLoader.php b/plugins/OStatus/extlib/Crypt/RSA/MathLoader.php
new file mode 100644 (file)
index 0000000..de6c946
--- /dev/null
@@ -0,0 +1,135 @@
+<?php
+/**
+ * Crypt_RSA allows to do following operations:
+ *     - key pair generation
+ *     - encryption and decryption
+ *     - signing and sign validation
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.0 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license@php.net so we can mail you a copy immediately.
+ *
+ * @category  Encryption
+ * @package   Crypt_RSA
+ * @author    Alexander Valyalkin <valyala@gmail.com>
+ * @copyright Alexander Valyalkin 2005
+ * @license   http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version   CVS: $Id: MathLoader.php,v 1.5 2009/01/05 08:30:29 clockwerx Exp $
+ * @link      http://pear.php.net/package/Crypt_RSA
+ */
+
+/**
+ * RSA error handling facilities
+ */
+require_once 'Crypt/RSA/ErrorHandler.php';
+
+/**
+ * Crypt_RSA_MathLoader class.
+ *
+ * Provides static function:
+ *  - loadWrapper($wrapper_name) - loads RSA math wrapper with name $wrapper_name
+ *                                 or most suitable wrapper if $wrapper_name == 'default'
+ *
+ * Example usage:
+ *    // load BigInt wrapper
+ *    $big_int_wrapper = Crypt_RSA_MathLoader::loadWrapper('BigInt');
+ * 
+ *    // load BCMath wrapper
+ *    $bcmath_wrapper = Crypt_RSA_MathLoader::loadWrapper('BCMath');
+ * 
+ *    // load the most suitable wrapper
+ *    $bcmath_wrapper = Crypt_RSA_MathLoader::loadWrapper();
+ * 
+ * @category  Encryption
+ * @package   Crypt_RSA
+ * @author    Alexander Valyalkin <valyala@gmail.com>
+ * @copyright Alexander Valyalkin 2005
+ * @license   http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version   Release: @package_version@
+ * @link      http://pear.php.net/package/Crypt_RSA
+ * @access    public
+ */
+class Crypt_RSA_MathLoader
+{
+    /**
+     * Loads RSA math wrapper with name $wrapper_name.
+     * Implemented wrappers can be found at Crypt/RSA/Math folder.
+     * Read docs/Crypt_RSA/docs/math_wrappers.txt for details
+     *
+     * This is a static function:
+     *    // load BigInt wrapper
+     *    $big_int_wrapper = &Crypt_RSA_MathLoader::loadWrapper('BigInt');
+     *
+     *    // load BCMath wrapper
+     *    $bcmath_wrapper = &Crypt_RSA_MathLoader::loadWrapper('BCMath');
+     *
+     * @param string $wrapper_name Name of wrapper
+     *
+     * @return object
+     *         Reference to object of wrapper with name $wrapper_name on success
+     *         or PEAR_Error object on error
+     *
+     * @access public
+     */
+    function loadWrapper($wrapper_name = 'default')
+    {
+        static $math_objects = array();
+        // ordered by performance. GMP is the fastest math library, BCMath - the slowest.
+        static $math_wrappers = array('GMP', 'BigInt', 'BCMath',);
+
+        if (isset($math_objects[$wrapper_name])) {
+            /*
+                wrapper with name $wrapper_name is already loaded and created.
+                Return reference to existing copy of wrapper
+            */
+            return $math_objects[$wrapper_name];
+        }
+
+        $err_handler = new Crypt_RSA_ErrorHandler();
+
+        if ($wrapper_name === 'default') {
+            // try to load the most suitable wrapper
+            $n = sizeof($math_wrappers);
+            for ($i = 0; $i < $n; $i++) {
+                $obj = Crypt_RSA_MathLoader::loadWrapper($math_wrappers[$i]);
+                if (!$err_handler->isError($obj)) {
+                    // wrapper for $math_wrappers[$i] successfully loaded
+                    // register it as default wrapper and return reference to it
+                    return $math_objects['default'] = $obj;
+                }
+            }
+            // can't load any wrapper
+            $err_handler->pushError("can't load any wrapper for existing math libraries", CRYPT_RSA_ERROR_NO_WRAPPERS);
+            return $err_handler->getLastError();
+        }
+
+        $class_name = 'Crypt_RSA_Math_' . $wrapper_name;
+        $class_filename = dirname(__FILE__) . '/Math/' . $wrapper_name . '.php';
+
+        if (!is_file($class_filename)) {
+            $err_handler->pushError("can't find file [{$class_filename}] for RSA math wrapper [{$wrapper_name}]", CRYPT_RSA_ERROR_NO_FILE);
+            return $err_handler->getLastError();
+        }
+
+        include_once $class_filename;
+        if (!class_exists($class_name)) {
+            $err_handler->pushError("can't find class [{$class_name}] in file [{$class_filename}]", CRYPT_RSA_ERROR_NO_CLASS);
+            return $err_handler->getLastError();
+        }
+
+        // create and return wrapper object on success or PEAR_Error object on error
+        $obj = new $class_name;
+        if ($obj->errstr) {
+            // cannot load required extension for math wrapper
+            $err_handler->pushError($obj->errstr, CRYPT_RSA_ERROR_NO_EXT);
+            return $err_handler->getLastError();
+        }
+        return $math_objects[$wrapper_name] = $obj;
+    }
+}
+
+?>
diff --git a/plugins/OStatus/lib/magicenvelope.php b/plugins/OStatus/lib/magicenvelope.php
new file mode 100644 (file)
index 0000000..1ae80d7
--- /dev/null
@@ -0,0 +1,174 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2010, StatusNet, Inc.
+ *
+ * A sample module to show best practices for StatusNet plugins
+ *
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @package   StatusNet
+ * @author    James Walker <james@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+require_once 'magicsig.php';
+
+class MagicEnvelope
+{
+    const ENCODING = 'base64url';
+
+    const NS = 'http://salmon-protocol.org/ns/magic-env';
+    
+    private function normalizeUser($user_id)
+    {
+        if (substr($user_id, 0, 5) == 'http:' ||
+            substr($user_id, 0, 6) == 'https:' ||
+            substr($user_id, 0, 5) == 'acct:') {
+            return $user_id;
+        }
+
+        if (strpos($user_id, '@') !== FALSE) {
+            return 'acct:' . $user_id;
+        }
+
+        return 'http://' . $user_id;
+    }
+
+    public function getKeyPair($signer_uri)
+    {
+        return 'RSA.79_L2gq-TD72Nsb5yGS0r9stLLpJZF5AHXyxzWmQmlqKl276LEJEs8CppcerLcR90MbYQUwt-SX9slx40Yq3vA==.AQAB.AR-jo5KMfSISmDAT2iMs2_vNFgWRjl5rbJVvA0SpGIEWyPdCGxlPtCbTexp8-0ZEIe8a4SyjatBECH5hxgMTpw==';
+    }
+
+
+    public function signMessage($text, $mimetype, $signer_uri)
+    {
+        $signer_uri = $this->normalizeUser($signer_uri);
+
+        if (!$this->checkAuthor($text, $signer_uri)) {
+            return false;
+        }
+
+        $signature_alg = new MagicsigRsaSha256($this->getKeyPair($signer_uri));
+        $armored_text = base64_encode($text);
+
+        return array(
+            'data' => $armored_text,
+            'encoding' => MagicEnvelope::ENCODING,
+            'data_type' => $mimetype,
+            'sig' => $signature_alg->sign($armored_text),
+            'alg' => $signature_alg->getName()
+        );
+            
+            
+    }
+
+    public function unfold($env)
+    {
+        $dom = new DOMDocument();
+        $dom->loadXML(base64_decode($env['data']));
+
+        if ($dom->documentElement->tagName != 'entry') {
+            return false;
+        }
+
+        $prov = $dom->createElementNS(MagicEnvelope::NS, 'me:provenance');
+        $prov->setAttribute('xmlns:me', MagicEnvelope::NS);
+        $data = $dom->createElementNS(MagicEnvelope::NS, 'me:data', $env['data']);
+        $data->setAttribute('type', $env['data_type']);
+        $prov->appendChild($data);
+        $enc = $dom->createElementNS(MagicEnvelope::NS, 'me:encoding', $env['encoding']);
+        $prov->appendChild($enc);
+        $alg = $dom->createElementNS(MagicEnvelope::NS, 'me:alg', $env['alg']);
+        $prov->appendChild($alg);
+        $sig = $dom->createElementNS(MagicEnvelope::NS, 'me:sig', $env['sig']);
+        $prov->appendChild($sig);
+
+        $dom->documentElement->appendChild($prov);
+
+        return $dom->saveXML();
+    }
+    
+    public function getAuthor($text) {
+        $doc = new DOMDocument();
+        if (!$doc->loadXML($text)) {
+            return FALSE;
+        }
+
+        if ($doc->documentElement->tagName == 'entry') {
+            $authors = $doc->documentElement->getElementsByTagName('author');
+            foreach ($authors as $author) {
+                $uris = $author->getElementsByTagName('uri');
+                foreach ($uris as $uri) {
+                    return $this->normalizeUser($uri->nodeValue);
+                }
+            }
+        }
+    }
+    
+    public function checkAuthor($text, $signer_uri)
+    {
+        return ($this->getAuthor($text) == $signer_uri);
+    }
+    
+    public function verify($env)
+    {
+        if ($env['alg'] != 'RSA-SHA256') {
+            return false;
+        }
+
+        if ($env['encoding'] != MagicEnvelope::ENCODING) {
+            return false;
+        }
+
+        $text = base64_decode($env['data']);
+        $signer_uri = $this->getAuthor($text);
+
+        $verifier = new MagicsigRsaSha256($this->getKeyPair($signer_uri));
+
+        return $verifier->verify($env['data'], $env['sig']);
+    }
+
+    public function parse($text)
+    {
+        $dom = DOMDocument::loadXML($text);
+        return $this->fromDom($dom);
+    }
+
+    public function fromDom($dom)
+    {
+        if ($dom->documentElement->tagName == 'entry') {
+            $env_element = $dom->getElementsByTagNameNS(MagicEnvelope::NS, 'provenance')->item(0);
+        } else if ($dom->documentElement->tagName == 'me:env') {
+            $env_element = $dom->documentElement;
+        } else {
+            return false;
+        }
+
+        $data_element = $env_element->getElementsByTagNameNS(MagicEnvelope::NS, 'data')->item(0);
+        
+        return array(
+            'data' => trim($data_element->nodeValue),
+            'data_type' => $data_element->getAttribute('type'),
+            'encoding' => $env_element->getElementsByTagNameNS(MagicEnvelope::NS, 'encoding')->item(0)->nodeValue,
+            'alg' => $env_element->getElementsByTagNameNS(MagicEnvelope::NS, 'alg')->item(0)->nodeValue,
+            'sig' => $env_element->getElementsByTagNameNS(MagicEnvelope::NS, 'sig')->item(0)->nodeValue,
+        );
+    }
+
+}
diff --git a/plugins/OStatus/lib/magicsig.php b/plugins/OStatus/lib/magicsig.php
new file mode 100644 (file)
index 0000000..af65bad
--- /dev/null
@@ -0,0 +1,159 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2010, StatusNet, Inc.
+ *
+ * A sample module to show best practices for StatusNet plugins
+ *
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @package   StatusNet
+ * @author    James Walker <james@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+require_once 'Crypt/RSA.php';
+
+interface Magicsig
+{
+
+    public function sign($bytes);
+
+    public function verify($signed, $signature_b64);
+}
+
+class MagicsigRsaSha256
+{
+
+    public $keypair;
+    
+    public function __construct($init = null)
+    {
+        if (is_null($init)) {
+            $this->generate();
+        } else {
+            $this->fromString($init);
+        }
+    }
+
+
+    public function generate($key_length = 512)
+    {
+        $keypair = new Crypt_RSA_KeyPair($key_length);
+        $params['public_key'] = $keypair->getPublicKey();
+        $params['private_key'] = $keypair->getPrivateKey();
+        
+        $this->keypair = new Crypt_RSA($params);
+    }
+
+
+    public function toString($full_pair = true)
+    {
+        $public_key = $this->keypair->_public_key;
+        $private_key = $this->keypair->_private_key;
+
+        $mod = base64_url_encode($public_key->getModulus());
+        $exp = base64_url_encode($public_key->getExponent());
+        $private_exp = '';
+        if ($full_pair && $private_key->getExponent()) {
+            $private_exp = '.' . base64_url_encode($private_key->getExponent());
+        }
+
+        return 'RSA.' . $mod . '.' . $exp . $private_exp; 
+    }
+    
+    public function fromString($text)
+    {
+        // remove whitespace
+        $text = preg_replace('/\s+/', '', $text);
+
+        // parse components
+        if (!preg_match('/RSA\.([^\.]+)\.([^\.]+)(.([^\.]+))?/', $text, $matches)) {
+            return false;
+        }
+
+        
+        $mod = base64_url_decode($matches[1]);
+        $exp = base64_url_decode($matches[2]);
+        if ($matches[4]) {
+            $private_exp = base64_url_decode($matches[4]);
+        }
+
+        $params['public_key'] = new Crypt_RSA_KEY($mod, $exp, 'public');
+        if ($params['public_key']->isError()) {
+            $error = $params['public_key']->getLastError();
+            print $error->getMessage();
+            exit;
+        }
+        if ($private_exp) {
+            $params['private_key'] = new Crypt_RSA_KEY($mod, $private_exp, 'private');
+            if ($params['private_key']->isError()) {
+                $error = $params['private_key']->getLastError();
+                print $error->getMessage();
+                exit;
+            }
+        }
+
+        $this->keypair = new Crypt_RSA($params);
+    }
+
+    public function getName()
+    {
+        return 'RSA-SHA256';
+    }
+
+    public function sign($bytes)
+    {
+        $sig = $this->keypair->createSign($bytes, null, 'sha256');
+        if ($this->keypair->isError()) {
+            $error = $this->keypair->getLastError();
+            common_log(LOG_DEBUG, 'RSA Error: '. $error->getMessage());
+        }
+
+        return $sig;
+    }
+
+    public function verify($signed_bytes, $signature)
+    {
+        $result =  $this->keypair->validateSign($signed_bytes, $signature, null, 'sha256');
+        if ($this->keypair->isError()) {
+            $error = $this->keypair->getLastError();
+            //common_log(LOG_DEBUG, 'RSA Error: '. $error->getMessage());
+            print $error->getMessage();
+        }
+        return $result;
+    }
+        
+}
+
+// Define a sha256 function for hashing
+// (Crypt_RSA should really be updated to use hash() )
+function sha256($bytes)
+{
+    return hash('sha256', $bytes);
+}
+
+function base64_url_encode($input)
+{
+    return strtr(base64_encode($input), '+/', '-_');
+}
+
+function base64_url_decode($input)
+{
+    return base64_decode(strtr($input, '-_', '+/'));
+}
\ No newline at end of file