Merge branch 'testing' of git@gitorious.org:statusnet/mainline into testing
This commit is contained in:
commit
c88507fe11
|
@ -285,6 +285,10 @@ class ProfilesettingsAction extends AccountSettingsAction
|
|||
} else {
|
||||
// Re-initialize language environment if it changed
|
||||
common_init_language();
|
||||
// Clear the site owner, in case nickname changed
|
||||
if ($user->hasRole(Profile_role::OWNER)) {
|
||||
User::blow('user:site_owner');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -792,9 +792,11 @@ class Profile extends Memcached_DataObject
|
|||
* Returns an XML string fragment with profile information as an
|
||||
* Activity Streams noun object with the given element type.
|
||||
*
|
||||
* Assumes that 'activity' namespace has been previously defined.
|
||||
* Assumes that 'activity', 'georss', and 'poco' namespace has been
|
||||
* previously defined.
|
||||
*
|
||||
* @param string $element one of 'actor', 'subject', 'object', 'target'
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function asActivityNoun($element)
|
||||
|
@ -811,9 +813,52 @@ class Profile extends Memcached_DataObject
|
|||
'id',
|
||||
null,
|
||||
$this->getUri()
|
||||
);
|
||||
);
|
||||
|
||||
// title should contain fullname
|
||||
$xs->element('title', null, $this->getBestName());
|
||||
|
||||
$xs->element('link', array('rel' => 'alternate',
|
||||
'type' => 'text/html'),
|
||||
$this->profileurl);
|
||||
|
||||
$xs->element('poco:preferredUsername', null, $this->nickname);
|
||||
|
||||
// Portable Contacts stuff
|
||||
|
||||
if (isset($this->bio)) {
|
||||
|
||||
// XXX: Possible to use OpenSocial's aboutMe?
|
||||
|
||||
$xs->element('poco:note', null, $this->bio);
|
||||
}
|
||||
|
||||
if (isset($this->homepage)) {
|
||||
|
||||
$xs->elementStart('poco:urls');
|
||||
$xs->element('poco:value', null, $this->homepage);
|
||||
$xs->element('poco:type', null, 'homepage');
|
||||
$xs->element('poco:primary', null, 'true');
|
||||
$xs->elementEnd('poco:urls');
|
||||
}
|
||||
|
||||
if (isset($this->location)) {
|
||||
$xs->elementStart('poco:address');
|
||||
$xs->element('poco:formatted', null, $this->location);
|
||||
$xs->elementEnd('poco:address');
|
||||
}
|
||||
|
||||
if (isset($this->lat) && isset($this->lon)) {
|
||||
$this->element(
|
||||
'georss:point',
|
||||
null,
|
||||
(float)$this->lat . ' ' . (float)$this->lon
|
||||
);
|
||||
}
|
||||
|
||||
// XXX: Should we send all avatar sizes we have? I think
|
||||
// cliqset does -Z
|
||||
|
||||
$avatar = $this->getAvatar(AVATAR_PROFILE_SIZE);
|
||||
|
||||
$xs->element(
|
||||
|
@ -829,6 +874,8 @@ class Profile extends Memcached_DataObject
|
|||
|
||||
$xs->elementEnd('activity:' . $element);
|
||||
|
||||
// XXX: Add people tags with <poco:tags> plural?
|
||||
|
||||
return $xs->getString();
|
||||
}
|
||||
|
||||
|
|
|
@ -109,11 +109,11 @@ class Atom10Feed extends XMLStringer
|
|||
);
|
||||
}
|
||||
|
||||
if (!is_null($uri)) {
|
||||
if (isset($uri)) {
|
||||
$xs->element('uri', null, $uri);
|
||||
}
|
||||
|
||||
if (!is_null(email)) {
|
||||
if (isset($email)) {
|
||||
$xs->element('email', null, $email);
|
||||
}
|
||||
|
||||
|
|
|
@ -60,8 +60,7 @@ class AtomUserNoticeFeed extends AtomNoticeFeed
|
|||
$this->user = $user;
|
||||
if (!empty($user)) {
|
||||
$profile = $user->getProfile();
|
||||
$this->addAuthor($profile->getBestName(),
|
||||
$user->uri);
|
||||
$this->addAuthor($profile->nickname, $user->uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
|
||||
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . '/extlib/');
|
||||
|
||||
class FeedSubException extends Exception
|
||||
{
|
||||
}
|
||||
|
|
|
@ -832,7 +832,9 @@ class Ostatus_profile extends Memcached_DataObject
|
|||
|
||||
protected static function getActivityObjectNickname($object, $hints=array())
|
||||
{
|
||||
// XXX: check whatever PoCo calls a nickname first
|
||||
if (!empty($object->nickname)) {
|
||||
return common_nicknamize($object->nickname);
|
||||
}
|
||||
|
||||
// Try the definitive ID
|
||||
|
||||
|
|
524
plugins/OStatus/extlib/Crypt/RSA.php
Normal file
524
plugins/OStatus/extlib/Crypt/RSA.php
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
234
plugins/OStatus/extlib/Crypt/RSA/ErrorHandler.php
Normal file
234
plugins/OStatus/extlib/Crypt/RSA/ErrorHandler.php
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
315
plugins/OStatus/extlib/Crypt/RSA/Key.php
Normal file
315
plugins/OStatus/extlib/Crypt/RSA/Key.php
Normal file
|
@ -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__));
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
804
plugins/OStatus/extlib/Crypt/RSA/KeyPair.php
Normal file
804
plugins/OStatus/extlib/Crypt/RSA/KeyPair.php
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
482
plugins/OStatus/extlib/Crypt/RSA/Math/BCMath.php
Normal file
482
plugins/OStatus/extlib/Crypt/RSA/Math/BCMath.php
Normal file
|
@ -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';
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
313
plugins/OStatus/extlib/Crypt/RSA/Math/BigInt.php
Normal file
313
plugins/OStatus/extlib/Crypt/RSA/Math/BigInt.php
Normal file
|
@ -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';
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
361
plugins/OStatus/extlib/Crypt/RSA/Math/GMP.php
Normal file
361
plugins/OStatus/extlib/Crypt/RSA/Math/GMP.php
Normal file
|
@ -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';
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
135
plugins/OStatus/extlib/Crypt/RSA/MathLoader.php
Normal file
135
plugins/OStatus/extlib/Crypt/RSA/MathLoader.php
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -31,6 +31,12 @@ if (!defined('STATUSNET')) {
|
|||
exit(1);
|
||||
}
|
||||
|
||||
class PoCo
|
||||
{
|
||||
const NS = 'http://portablecontacts.net/spec/1.0';
|
||||
const USERNAME = 'preferredUsername';
|
||||
}
|
||||
|
||||
/**
|
||||
* Utilities for turning DOMish things into Activityish things
|
||||
*
|
||||
|
@ -319,7 +325,8 @@ class ActivityObject
|
|||
$this->displayName = $this->title;
|
||||
|
||||
// @fixme we may have multiple avatars with different resolutions specified
|
||||
$this->avatar = ActivityUtils::getLink($element, 'avatar');
|
||||
$this->avatar = ActivityUtils::getLink($element, 'avatar');
|
||||
$this->nickname = ActivityUtils::childContent($element, PoCo::USERNAME, PoCo::NS);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
174
plugins/OStatus/lib/magicenvelope.php
Normal file
174
plugins/OStatus/lib/magicenvelope.php
Normal file
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
159
plugins/OStatus/lib/magicsig.php
Normal file
159
plugins/OStatus/lib/magicsig.php
Normal file
|
@ -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, '-_', '+/'));
|
||||
}
|
|
@ -34,6 +34,8 @@ class Salmon
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
$xml = $this->createMagicEnv($xml);
|
||||
|
||||
$headers = array('Content-type: application/atom+xml');
|
||||
|
||||
try {
|
||||
|
@ -52,16 +54,25 @@ class Salmon
|
|||
|
||||
}
|
||||
|
||||
public function createMagicEnv($text, $userid)
|
||||
public function createMagicEnv($text)
|
||||
{
|
||||
$magic_env = new MagicEnvelope();
|
||||
|
||||
// TODO: Should probably be getting the signer uri as an argument?
|
||||
$signer_uri = $magic_env->getAuthor($text);
|
||||
|
||||
$env = $magic_env->signMessage($text, 'application/atom+xml', $signer_uri);
|
||||
|
||||
return $magic_env->unfold($env);
|
||||
}
|
||||
|
||||
|
||||
public function verifyMagicEnv($env)
|
||||
public function verifyMagicEnv($dom)
|
||||
{
|
||||
$magic_env = new MagicEnvelope();
|
||||
|
||||
$env = $magic_env->fromDom($dom);
|
||||
|
||||
|
||||
return $magic_env->verify($env);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,8 +54,14 @@ class SalmonAction extends Action
|
|||
common_log(LOG_DEBUG, "Got invalid Salmon post: $xml");
|
||||
$this->clientError(_m('Salmon post must be an Atom entry.'));
|
||||
}
|
||||
// XXX: check the signature
|
||||
|
||||
// Check the signature
|
||||
$salmon = new Salmon;
|
||||
if (!$salmon->verifyMagicEnv($dom)) {
|
||||
common_log(LOG_DEBUG, "Salmon signature verification failed.");
|
||||
$this->clientError(_m('Salmon signature verification failed.'));
|
||||
}
|
||||
|
||||
$this->act = new Activity($dom->documentElement);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
If you already have an account on %%site.name%%, you can [login](%%action.login%%) with your username and password as usual.
|
||||
To use OpenID in the future, you can [add an OpenID to your account](%%action.openidsettings%%) after you have logged in normally.
|
||||
|
||||
There are many [Public OpenID providers](http://wiki.openid.net/Public_OpenID_providers), and you may already have an OpenID-enabled account on another service.
|
||||
There are many [Public OpenID providers](http://wiki.openid.net/OpenID-Providers), and you may already have an OpenID-enabled account on another service.
|
||||
|
||||
* On wikis: If you have an account on an OpenID-enabled wiki, like [Wikitravel](http://wikitravel.org/), [wikiHow](http://www.wikihow.com/), [Vinismo](http://vinismo.com/), [AboutUs](http://aboutus.org/) or [Keiki](http://kei.ki/), you can log in to %%site.name%% by entering the **full URL** of your user page on that other wiki in the box above. For example, *http://kei.ki/en/User:Evan*.
|
||||
* [Yahoo!](http://openid.yahoo.com/) : If you have an account with Yahoo!, you can log in to this site by entering your Yahoo!-provided OpenID in the box above. Yahoo! OpenID URLs have the form *https://me.yahoo.com/yourusername*.
|
||||
|
|
Loading…
Reference in New Issue
Block a user