forked from GNUsocial/gnu-social
Merge branch 'testing' of git@gitorious.org:statusnet/mainline into testing
This commit is contained in:
commit
4761c07ad8
141
actions/apimediaupload.php
Normal file
141
actions/apimediaupload.php
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Upload an image via the API
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* LICENCE: 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/>.
|
||||||
|
*
|
||||||
|
* @category API
|
||||||
|
* @author Zach Copley <zach@status.net>
|
||||||
|
* @copyright 2010 StatusNet, Inc.
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once INSTALLDIR . '/lib/apiauth.php';
|
||||||
|
require_once INSTALLDIR . '/lib/mediafile.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload an image via the API. Returns a shortened URL for the image
|
||||||
|
* to the user.
|
||||||
|
*
|
||||||
|
* @category API
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Zach Copley <zach@status.net>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ApiMediaUploadAction extends ApiAuthAction
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle the request
|
||||||
|
*
|
||||||
|
* Grab the file from the 'media' param, then store, and shorten
|
||||||
|
*
|
||||||
|
* @todo Upload throttle!
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST data (unused)
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
function handle($args)
|
||||||
|
{
|
||||||
|
parent::handle($args);
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
|
||||||
|
$this->clientError(
|
||||||
|
_('This method requires a POST.'),
|
||||||
|
400, $this->format
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Workaround for PHP returning empty $_POST and $_FILES when POST
|
||||||
|
// length > post_max_size in php.ini
|
||||||
|
|
||||||
|
if (empty($_FILES)
|
||||||
|
&& empty($_POST)
|
||||||
|
&& ($_SERVER['CONTENT_LENGTH'] > 0)
|
||||||
|
) {
|
||||||
|
$msg = _('The server was unable to handle that much POST ' .
|
||||||
|
'data (%s bytes) due to its current configuration.');
|
||||||
|
|
||||||
|
$this->clientError(sprintf($msg, $_SERVER['CONTENT_LENGTH']));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$upload = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$upload = MediaFile::fromUpload('media', $this->auth_user);
|
||||||
|
} catch (ClientException $ce) {
|
||||||
|
$this->clientError($ce->getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($upload)) {
|
||||||
|
$this->showResponse($upload);
|
||||||
|
} else {
|
||||||
|
$this->clientError('Upload failed.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a Twitpic-like response with the ID of the media file
|
||||||
|
* and a (hopefully) shortened URL for it.
|
||||||
|
*
|
||||||
|
* @param File $upload the uploaded file
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function showResponse($upload)
|
||||||
|
{
|
||||||
|
$this->initDocument();
|
||||||
|
$this->elementStart('rsp', array('stat' => 'ok'));
|
||||||
|
$this->element('mediaid', null, $upload->fileRecord->id);
|
||||||
|
$this->element('mediaurl', null, $upload->shortUrl());
|
||||||
|
$this->elementEnd('rsp');
|
||||||
|
$this->endDocument();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrided clientError to show a more Twitpic-like error
|
||||||
|
*
|
||||||
|
* @param String $msg an error message
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function clientError($msg)
|
||||||
|
{
|
||||||
|
$this->initDocument();
|
||||||
|
$this->elementStart('rsp', array('stat' => 'fail'));
|
||||||
|
|
||||||
|
// @todo add in error code
|
||||||
|
$errAttr = array('msg' => $msg);
|
||||||
|
|
||||||
|
$this->element('err', $errAttr, null);
|
||||||
|
$this->elementEnd('rsp');
|
||||||
|
$this->endDocument();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -97,8 +97,6 @@ class ApiStatusnetConfigAction extends ApiAction
|
|||||||
|
|
||||||
// XXX: check that all sections and settings are legal XML elements
|
// XXX: check that all sections and settings are legal XML elements
|
||||||
|
|
||||||
common_debug(var_export($this->keys, true));
|
|
||||||
|
|
||||||
foreach ($this->keys as $section => $settings) {
|
foreach ($this->keys as $section => $settings) {
|
||||||
$this->elementStart($section);
|
$this->elementStart($section);
|
||||||
foreach ($settings as $setting) {
|
foreach ($settings as $setting) {
|
||||||
@ -110,6 +108,14 @@ class ApiStatusnetConfigAction extends ApiAction
|
|||||||
} else if ($value === true) {
|
} else if ($value === true) {
|
||||||
$value = 'true';
|
$value = 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return theme logo if there's no site specific one
|
||||||
|
if (empty($value)) {
|
||||||
|
if ($section == 'site' && $setting == 'logo') {
|
||||||
|
$value = Theme::path('logo.png');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->element($setting, null, $value);
|
$this->element($setting, null, $value);
|
||||||
}
|
}
|
||||||
$this->elementEnd($section);
|
$this->elementEnd($section);
|
||||||
|
@ -162,7 +162,15 @@ class DeleteuserAction extends ProfileFormAction
|
|||||||
function handlePost()
|
function handlePost()
|
||||||
{
|
{
|
||||||
if (Event::handle('StartDeleteUser', array($this, $this->user))) {
|
if (Event::handle('StartDeleteUser', array($this, $this->user))) {
|
||||||
$this->user->delete();
|
// Mark the account as deleted and shove low-level deletion tasks
|
||||||
|
// to background queues. Removing a lot of posts can take a while...
|
||||||
|
if (!$this->user->hasRole(Profile_role::DELETED)) {
|
||||||
|
$this->user->grantRole(Profile_role::DELETED);
|
||||||
|
}
|
||||||
|
|
||||||
|
$qm = QueueManager::get();
|
||||||
|
$qm->enqueue($this->user, 'deluser');
|
||||||
|
|
||||||
Event::handle('EndDeleteUser', array($this, $this->user));
|
Event::handle('EndDeleteUser', array($this, $this->user));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,11 +103,6 @@ class ShownoticeAction extends OwnerDesignAction
|
|||||||
|
|
||||||
$this->user = User::staticGet('id', $this->profile->id);
|
$this->user = User::staticGet('id', $this->profile->id);
|
||||||
|
|
||||||
if ($this->notice->is_local == Notice::REMOTE_OMB) {
|
|
||||||
common_redirect($this->notice->uri);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->avatar = $this->profile->getAvatar(AVATAR_PROFILE_SIZE);
|
$this->avatar = $this->profile->getAvatar(AVATAR_PROFILE_SIZE);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -198,13 +193,20 @@ class ShownoticeAction extends OwnerDesignAction
|
|||||||
|
|
||||||
if ($this->notice->is_local == Notice::REMOTE_OMB) {
|
if ($this->notice->is_local == Notice::REMOTE_OMB) {
|
||||||
if (!empty($this->notice->url)) {
|
if (!empty($this->notice->url)) {
|
||||||
common_redirect($this->notice->url, 301);
|
$target = $this->notice->url;
|
||||||
} else if (!empty($this->notice->uri) && preg_match('/^https?:/', $this->notice->uri)) {
|
} else if (!empty($this->notice->uri) && preg_match('/^https?:/', $this->notice->uri)) {
|
||||||
common_redirect($this->notice->uri, 301);
|
// Old OMB posts saved the remote URL only into the URI field.
|
||||||
|
$target = $this->notice->uri;
|
||||||
|
} else {
|
||||||
|
// Shouldn't happen.
|
||||||
|
$target = false;
|
||||||
|
}
|
||||||
|
if ($target && $target != $this->selfUrl()) {
|
||||||
|
common_redirect($target, 301);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
$this->showPage();
|
|
||||||
}
|
}
|
||||||
|
$this->showPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -119,6 +119,9 @@ class Notice extends Memcached_DataObject
|
|||||||
// NOTE: we don't clear queue items
|
// NOTE: we don't clear queue items
|
||||||
|
|
||||||
$result = parent::delete();
|
$result = parent::delete();
|
||||||
|
|
||||||
|
$this->blowOnDelete();
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -421,6 +424,18 @@ class Notice extends Memcached_DataObject
|
|||||||
$profile->blowNoticeCount();
|
$profile->blowNoticeCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear cache entries related to this notice at delete time.
|
||||||
|
* Necessary to avoid breaking paging on public, profile timelines.
|
||||||
|
*/
|
||||||
|
function blowOnDelete()
|
||||||
|
{
|
||||||
|
$this->blowOnInsert();
|
||||||
|
|
||||||
|
self::blow('profile:notice_ids:%d;last', $this->profile_id);
|
||||||
|
self::blow('public;last');
|
||||||
|
}
|
||||||
|
|
||||||
/** save all urls in the notice to the db
|
/** save all urls in the notice to the db
|
||||||
*
|
*
|
||||||
* follow redirects and save all available file information
|
* follow redirects and save all available file information
|
||||||
@ -589,7 +604,6 @@ class Notice extends Memcached_DataObject
|
|||||||
array(),
|
array(),
|
||||||
'public',
|
'public',
|
||||||
$offset, $limit, $since_id, $max_id);
|
$offset, $limit, $since_id, $max_id);
|
||||||
|
|
||||||
return Notice::getStreamByIds($ids);
|
return Notice::getStreamByIds($ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -732,6 +732,9 @@ class Profile extends Memcached_DataObject
|
|||||||
function hasRight($right)
|
function hasRight($right)
|
||||||
{
|
{
|
||||||
$result = false;
|
$result = false;
|
||||||
|
if ($this->hasRole(Profile_role::DELETED)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (Event::handle('UserRightsCheck', array($this, $right, &$result))) {
|
if (Event::handle('UserRightsCheck', array($this, $right, &$result))) {
|
||||||
switch ($right)
|
switch ($right)
|
||||||
{
|
{
|
||||||
|
@ -53,6 +53,7 @@ class Profile_role extends Memcached_DataObject
|
|||||||
const ADMINISTRATOR = 'administrator';
|
const ADMINISTRATOR = 'administrator';
|
||||||
const SANDBOXED = 'sandboxed';
|
const SANDBOXED = 'sandboxed';
|
||||||
const SILENCED = 'silenced';
|
const SILENCED = 'silenced';
|
||||||
|
const DELETED = 'deleted'; // Pending final deletion of notices...
|
||||||
|
|
||||||
public static function isValid($role)
|
public static function isValid($role)
|
||||||
{
|
{
|
||||||
|
@ -42,6 +42,25 @@ class Safe_DataObject extends DB_DataObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Magic function called at clone() time.
|
||||||
|
*
|
||||||
|
* We use this to drop connection with some global resources.
|
||||||
|
* This supports the fairly common pattern where individual
|
||||||
|
* items being read in a loop via a single object are cloned
|
||||||
|
* for individual processing, then fall out of scope when the
|
||||||
|
* loop comes around again.
|
||||||
|
*
|
||||||
|
* As that triggers the destructor, we want to make sure that
|
||||||
|
* the original object doesn't have its database result killed.
|
||||||
|
* It will still be freed properly when the original object
|
||||||
|
* gets destroyed.
|
||||||
|
*/
|
||||||
|
function __clone()
|
||||||
|
{
|
||||||
|
$this->_DB_resultid = false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Magic function called at serialize() time.
|
* Magic function called at serialize() time.
|
||||||
*
|
*
|
||||||
|
107
index.php
107
index.php
@ -37,6 +37,8 @@ define('INSTALLDIR', dirname(__FILE__));
|
|||||||
define('STATUSNET', true);
|
define('STATUSNET', true);
|
||||||
define('LACONICA', true); // compatibility
|
define('LACONICA', true); // compatibility
|
||||||
|
|
||||||
|
require_once INSTALLDIR . '/lib/common.php';
|
||||||
|
|
||||||
$user = null;
|
$user = null;
|
||||||
$action = null;
|
$action = null;
|
||||||
|
|
||||||
@ -66,69 +68,52 @@ function getPath($req)
|
|||||||
*/
|
*/
|
||||||
function handleError($error)
|
function handleError($error)
|
||||||
{
|
{
|
||||||
try {
|
if ($error->getCode() == DB_DATAOBJECT_ERROR_NODATA) {
|
||||||
|
return;
|
||||||
if ($error->getCode() == DB_DATAOBJECT_ERROR_NODATA) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$logmsg = "PEAR error: " . $error->getMessage();
|
|
||||||
if ($error instanceof PEAR_Exception && common_config('site', 'logdebug')) {
|
|
||||||
$logmsg .= " : ". $error->toText();
|
|
||||||
}
|
|
||||||
// DB queries often end up with a lot of newlines; merge to a single line
|
|
||||||
// for easier grepability...
|
|
||||||
$logmsg = str_replace("\n", " ", $logmsg);
|
|
||||||
common_log(LOG_ERR, $logmsg);
|
|
||||||
|
|
||||||
// @fixme backtrace output should be consistent with exception handling
|
|
||||||
if (common_config('site', 'logdebug')) {
|
|
||||||
$bt = $error->getTrace();
|
|
||||||
foreach ($bt as $n => $line) {
|
|
||||||
common_log(LOG_ERR, formatBacktraceLine($n, $line));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($error instanceof DB_DataObject_Error
|
|
||||||
|| $error instanceof DB_Error
|
|
||||||
|| ($error instanceof PEAR_Exception && $error->getCode() == -24)
|
|
||||||
) {
|
|
||||||
//If we run into a DB error, assume we can't connect to the DB at all
|
|
||||||
//so set the current user to null, so we don't try to access the DB
|
|
||||||
//while rendering the error page.
|
|
||||||
global $_cur;
|
|
||||||
$_cur = null;
|
|
||||||
|
|
||||||
$msg = sprintf(
|
|
||||||
_(
|
|
||||||
'The database for %s isn\'t responding correctly, '.
|
|
||||||
'so the site won\'t work properly. '.
|
|
||||||
'The site admins probably know about the problem, '.
|
|
||||||
'but you can contact them at %s to make sure. '.
|
|
||||||
'Otherwise, wait a few minutes and try again.'
|
|
||||||
),
|
|
||||||
common_config('site', 'name'),
|
|
||||||
common_config('site', 'email')
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$msg = _(
|
|
||||||
'An important error occured, probably related to email setup. '.
|
|
||||||
'Check logfiles for more info..'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$dac = new DBErrorAction($msg, 500);
|
|
||||||
$dac->showPage();
|
|
||||||
|
|
||||||
} catch (Exception $e) {
|
|
||||||
echo _('An error occurred.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$logmsg = "PEAR error: " . $error->getMessage();
|
||||||
|
if (common_config('site', 'logdebug')) {
|
||||||
|
$logmsg .= " : ". $error->getDebugInfo();
|
||||||
|
}
|
||||||
|
// DB queries often end up with a lot of newlines; merge to a single line
|
||||||
|
// for easier grepability...
|
||||||
|
$logmsg = str_replace("\n", " ", $logmsg);
|
||||||
|
common_log(LOG_ERR, $logmsg);
|
||||||
|
|
||||||
|
// @fixme backtrace output should be consistent with exception handling
|
||||||
|
if (common_config('site', 'logdebug')) {
|
||||||
|
$bt = $error->getBacktrace();
|
||||||
|
foreach ($bt as $n => $line) {
|
||||||
|
common_log(LOG_ERR, formatBacktraceLine($n, $line));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($error instanceof DB_DataObject_Error
|
||||||
|
|| $error instanceof DB_Error
|
||||||
|
) {
|
||||||
|
$msg = sprintf(
|
||||||
|
_(
|
||||||
|
'The database for %s isn\'t responding correctly, '.
|
||||||
|
'so the site won\'t work properly. '.
|
||||||
|
'The site admins probably know about the problem, '.
|
||||||
|
'but you can contact them at %s to make sure. '.
|
||||||
|
'Otherwise, wait a few minutes and try again.'
|
||||||
|
),
|
||||||
|
common_config('site', 'name'),
|
||||||
|
common_config('site', 'email')
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$msg = _(
|
||||||
|
'An important error occured, probably related to email setup. '.
|
||||||
|
'Check logfiles for more info..'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$dac = new DBErrorAction($msg, 500);
|
||||||
|
$dac->showPage();
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_exception_handler('handleError');
|
|
||||||
|
|
||||||
require_once INSTALLDIR . '/lib/common.php';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format a backtrace line for debug output roughly like debug_print_backtrace() does.
|
* Format a backtrace line for debug output roughly like debug_print_backtrace() does.
|
||||||
* Exceptions already have this built in, but PEAR error objects just give us the array.
|
* Exceptions already have this built in, but PEAR error objects just give us the array.
|
||||||
@ -253,6 +238,10 @@ function main()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For database errors
|
||||||
|
|
||||||
|
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'handleError');
|
||||||
|
|
||||||
// Make sure RW database is setup
|
// Make sure RW database is setup
|
||||||
|
|
||||||
setupRW();
|
setupRW();
|
||||||
|
@ -457,13 +457,13 @@ class ActivityUtils
|
|||||||
|
|
||||||
// slavishly following http://atompub.org/rfc4287.html#rfc.section.4.1.3.3
|
// slavishly following http://atompub.org/rfc4287.html#rfc.section.4.1.3.3
|
||||||
|
|
||||||
if ($type == 'text') {
|
if (empty($type) || $type == 'text') {
|
||||||
return $contentEl->textContent;
|
return $contentEl->textContent;
|
||||||
} else if ($type == 'html') {
|
} else if ($type == 'html') {
|
||||||
$text = $contentEl->textContent;
|
$text = $contentEl->textContent;
|
||||||
return htmlspecialchars_decode($text, ENT_QUOTES);
|
return htmlspecialchars_decode($text, ENT_QUOTES);
|
||||||
} else if ($type == 'xhtml') {
|
} else if ($type == 'xhtml') {
|
||||||
$divEl = ActivityUtils::child($contentEl, 'div');
|
$divEl = ActivityUtils::child($contentEl, 'div', 'http://www.w3.org/1999/xhtml');
|
||||||
if (empty($divEl)) {
|
if (empty($divEl)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -476,7 +476,7 @@ class ActivityUtils
|
|||||||
$text .= $doc->saveXML($child);
|
$text .= $doc->saveXML($child);
|
||||||
}
|
}
|
||||||
return trim($text);
|
return trim($text);
|
||||||
} else if (in_array(array('text/xml', 'application/xml'), $type) ||
|
} else if (in_array($type, array('text/xml', 'application/xml')) ||
|
||||||
preg_match('#(+|/)xml$#', $type)) {
|
preg_match('#(+|/)xml$#', $type)) {
|
||||||
throw new ClientException(_("Can't handle embedded XML content yet."));
|
throw new ClientException(_("Can't handle embedded XML content yet."));
|
||||||
} else if (strncasecmp($type, 'text/', 5)) {
|
} else if (strncasecmp($type, 'text/', 5)) {
|
||||||
@ -681,9 +681,16 @@ class ActivityObject
|
|||||||
if ($this->type == self::PERSON || $this->type == self::GROUP) {
|
if ($this->type == self::PERSON || $this->type == self::GROUP) {
|
||||||
$this->displayName = $this->title;
|
$this->displayName = $this->title;
|
||||||
|
|
||||||
$avatars = ActivityUtils::getLinks($element, 'avatar');
|
$photos = ActivityUtils::getLinks($element, 'photo');
|
||||||
foreach ($avatars as $link) {
|
if (count($photos)) {
|
||||||
$this->avatarLinks[] = new AvatarLink($link);
|
foreach ($photos as $link) {
|
||||||
|
$this->avatarLinks[] = new AvatarLink($link);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$avatars = ActivityUtils::getLinks($element, 'avatar');
|
||||||
|
foreach ($avatars as $link) {
|
||||||
|
$this->avatarLinks[] = new AvatarLink($link);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->poco = new PoCo($element);
|
$this->poco = new PoCo($element);
|
||||||
@ -1076,15 +1083,11 @@ class Activity
|
|||||||
|
|
||||||
$this->entry = $entry;
|
$this->entry = $entry;
|
||||||
|
|
||||||
// @fixme Don't send in a DOMDocument
|
// Insist on a feed's root DOMElement; don't allow a DOMDocument
|
||||||
if ($feed instanceof DOMDocument) {
|
if ($feed instanceof DOMDocument) {
|
||||||
common_log(
|
throw new ClientException(
|
||||||
LOG_WARNING,
|
_("Expecting a root feed element but got a whole XML document.")
|
||||||
'Activity::__construct() - '
|
|
||||||
. 'DOMDocument passed in for feed by mistake. '
|
|
||||||
. "Expecting a 'feed' DOMElement."
|
|
||||||
);
|
);
|
||||||
$feed = $feed->getElementsByTagName('feed')->item(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->feed = $feed;
|
$this->feed = $feed;
|
||||||
|
@ -71,7 +71,6 @@ if (!function_exists('dl')) {
|
|||||||
# global configuration object
|
# global configuration object
|
||||||
|
|
||||||
require_once('PEAR.php');
|
require_once('PEAR.php');
|
||||||
require_once('PEAR/Exception.php');
|
|
||||||
require_once('DB/DataObject.php');
|
require_once('DB/DataObject.php');
|
||||||
require_once('DB/DataObject/Cast.php'); # for dates
|
require_once('DB/DataObject/Cast.php'); # for dates
|
||||||
|
|
||||||
@ -129,17 +128,6 @@ require_once INSTALLDIR.'/lib/activity.php';
|
|||||||
require_once INSTALLDIR.'/lib/clientexception.php';
|
require_once INSTALLDIR.'/lib/clientexception.php';
|
||||||
require_once INSTALLDIR.'/lib/serverexception.php';
|
require_once INSTALLDIR.'/lib/serverexception.php';
|
||||||
|
|
||||||
|
|
||||||
//set PEAR error handling to use regular PHP exceptions
|
|
||||||
function PEAR_ErrorToPEAR_Exception($err)
|
|
||||||
{
|
|
||||||
if ($err->getCode()) {
|
|
||||||
throw new PEAR_Exception($err->getMessage(), $err->getCode());
|
|
||||||
}
|
|
||||||
throw new PEAR_Exception($err->getMessage());
|
|
||||||
}
|
|
||||||
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'PEAR_ErrorToPEAR_Exception');
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
StatusNet::init(@$server, @$path, @$conffile);
|
StatusNet::init(@$server, @$path, @$conffile);
|
||||||
} catch (NoConfigException $e) {
|
} catch (NoConfigException $e) {
|
||||||
|
95
lib/deluserqueuehandler.php
Normal file
95
lib/deluserqueuehandler.php
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* StatusNet - the distributed open-source microblogging tool
|
||||||
|
* Copyright (C) 2010, StatusNet, Inc.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Background job to delete prolific users without disrupting front-end too much.
|
||||||
|
*
|
||||||
|
* Up to 50 messages are deleted on each run through; when all messages are gone,
|
||||||
|
* the actual account is deleted.
|
||||||
|
*
|
||||||
|
* @package QueueHandler
|
||||||
|
* @maintainer Brion Vibber <brion@status.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
class DelUserQueueHandler extends QueueHandler
|
||||||
|
{
|
||||||
|
const DELETION_WINDOW = 50;
|
||||||
|
|
||||||
|
public function transport()
|
||||||
|
{
|
||||||
|
return 'deluser';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle($user)
|
||||||
|
{
|
||||||
|
if (!($user instanceof User)) {
|
||||||
|
common_log(LOG_ERR, "Got a bogus user, not deleting");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::staticGet('id', $user->id);
|
||||||
|
if (!$user) {
|
||||||
|
common_log(LOG_INFO, "User {$user->nickname} was deleted before we got here.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$user->hasRole(Profile_role::DELETED)) {
|
||||||
|
common_log(LOG_INFO, "User {$user->nickname} is not pending deletion; aborting.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$notice = $this->getNextBatch($user);
|
||||||
|
if ($notice->N) {
|
||||||
|
common_log(LOG_INFO, "Deleting next {$notice->N} notices by {$user->nickname}");
|
||||||
|
while ($notice->fetch()) {
|
||||||
|
$del = clone($notice);
|
||||||
|
$del->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
// @todo improve reliability in case we died during the above deletions
|
||||||
|
// with a fatal error. If the job is lost, we should perform some kind
|
||||||
|
// of garbage collection later.
|
||||||
|
|
||||||
|
// Queue up the next batch.
|
||||||
|
$qm = QueueManager::get();
|
||||||
|
$qm->enqueue($user, 'deluser');
|
||||||
|
} else {
|
||||||
|
// Out of notices? Let's finish deleting this guy!
|
||||||
|
$user->delete();
|
||||||
|
common_log(LOG_INFO, "User $user->id $user->nickname deleted.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the next self::DELETION_WINDOW messages for this user.
|
||||||
|
* @return Notice
|
||||||
|
*/
|
||||||
|
protected function getNextBatch(User $user)
|
||||||
|
{
|
||||||
|
$notice = new Notice();
|
||||||
|
$notice->profile_id = $user->id;
|
||||||
|
$notice->limit(self::DELETION_WINDOW);
|
||||||
|
$notice->find();
|
||||||
|
return $notice;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -264,6 +264,9 @@ abstract class QueueManager extends IoManager
|
|||||||
$this->connect('sms', 'SmsQueueHandler');
|
$this->connect('sms', 'SmsQueueHandler');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Background user management tasks...
|
||||||
|
$this->connect('deluser', 'DelUserQueueHandler');
|
||||||
|
|
||||||
// Broadcasting profile updates to OMB remote subscribers
|
// Broadcasting profile updates to OMB remote subscribers
|
||||||
$this->connect('profile', 'ProfileQueueHandler');
|
$this->connect('profile', 'ProfileQueueHandler');
|
||||||
|
|
||||||
|
@ -628,6 +628,12 @@ class Router
|
|||||||
array('action' => 'ApiTimelineTag',
|
array('action' => 'ApiTimelineTag',
|
||||||
'format' => '(xmljson|rss|atom)'));
|
'format' => '(xmljson|rss|atom)'));
|
||||||
|
|
||||||
|
// media related
|
||||||
|
$m->connect(
|
||||||
|
'api/statusnet/media/upload',
|
||||||
|
array('action' => 'ApiMediaUpload')
|
||||||
|
);
|
||||||
|
|
||||||
// search
|
// search
|
||||||
$m->connect('api/search.atom', array('action' => 'twitapisearchatom'));
|
$m->connect('api/search.atom', array('action' => 'twitapisearchatom'));
|
||||||
$m->connect('api/search.json', array('action' => 'twitapisearchjson'));
|
$m->connect('api/search.json', array('action' => 'twitapisearchjson'));
|
||||||
|
@ -228,6 +228,17 @@ class UserProfile extends Widget
|
|||||||
|
|
||||||
function showEntityActions()
|
function showEntityActions()
|
||||||
{
|
{
|
||||||
|
if ($this->profile->hasRole(Profile_role::DELETED)) {
|
||||||
|
$this->out->elementStart('div', 'entity_actions');
|
||||||
|
$this->out->element('h2', null, _('User actions'));
|
||||||
|
$this->out->elementStart('ul');
|
||||||
|
$this->out->elementStart('p', array('class' => 'profile_deleted'));
|
||||||
|
$this->out->text(_('User deletion in progress...'));
|
||||||
|
$this->out->elementEnd('p');
|
||||||
|
$this->out->elementEnd('ul');
|
||||||
|
$this->out->elementEnd('div');
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (Event::handle('StartProfilePageActionsSection', array(&$this->out, $this->profile))) {
|
if (Event::handle('StartProfilePageActionsSection', array(&$this->out, $this->profile))) {
|
||||||
|
|
||||||
$cur = common_current_user();
|
$cur = common_current_user();
|
||||||
|
@ -82,7 +82,8 @@ class UsersalmonAction extends SalmonAction
|
|||||||
throw new ClientException("In reply to a notice not by this user");
|
throw new ClientException("In reply to a notice not by this user");
|
||||||
}
|
}
|
||||||
} else if (!empty($context->attention)) {
|
} else if (!empty($context->attention)) {
|
||||||
if (!in_array($this->user->uri, $context->attention)) {
|
if (!in_array($this->user->uri, $context->attention) &&
|
||||||
|
!in_array(common_profile_url($this->user->nickname), $context->attention)) {
|
||||||
common_log(LOG_ERR, "{$this->user->uri} not in attention list (".implode(',', $context->attention).")");
|
common_log(LOG_ERR, "{$this->user->uri} not in attention list (".implode(',', $context->attention).")");
|
||||||
throw new ClientException("To the attention of user(s) not including this one!");
|
throw new ClientException("To the attention of user(s) not including this one!");
|
||||||
}
|
}
|
||||||
|
@ -32,12 +32,15 @@ class UserxrdAction extends XrdAction
|
|||||||
parent::prepare($args);
|
parent::prepare($args);
|
||||||
|
|
||||||
$this->uri = $this->trimmed('uri');
|
$this->uri = $this->trimmed('uri');
|
||||||
$acct = Discovery::normalize($this->uri);
|
$this->uri = Discovery::normalize($this->uri);
|
||||||
|
|
||||||
list($nick, $domain) = explode('@', substr(urldecode($acct), 5));
|
if (Discovery::isWebfinger($this->uri)) {
|
||||||
$nick = common_canonical_nickname($nick);
|
list($nick, $domain) = explode('@', substr(urldecode($this->uri), 5));
|
||||||
|
$nick = common_canonical_nickname($nick);
|
||||||
$this->user = User::staticGet('nickname', $nick);
|
$this->user = User::staticGet('nickname', $nick);
|
||||||
|
} else {
|
||||||
|
$this->user = User::staticGet('uri', $this->uri);
|
||||||
|
}
|
||||||
if (!$this->user) {
|
if (!$this->user) {
|
||||||
$this->clientError(_('No such user.'), 404);
|
$this->clientError(_('No such user.'), 404);
|
||||||
return false;
|
return false;
|
||||||
|
@ -40,8 +40,9 @@ class Magicsig extends Memcached_DataObject
|
|||||||
public $keypair;
|
public $keypair;
|
||||||
public $alg;
|
public $alg;
|
||||||
|
|
||||||
private $_rsa;
|
public $publicKey;
|
||||||
|
public $privateKey;
|
||||||
|
|
||||||
public function __construct($alg = 'RSA-SHA256')
|
public function __construct($alg = 'RSA-SHA256')
|
||||||
{
|
{
|
||||||
$this->alg = $alg;
|
$this->alg = $alg;
|
||||||
@ -71,8 +72,8 @@ class Magicsig extends Memcached_DataObject
|
|||||||
{
|
{
|
||||||
return array(new ColumnDef('user_id', 'integer',
|
return array(new ColumnDef('user_id', 'integer',
|
||||||
null, false, 'PRI'),
|
null, false, 'PRI'),
|
||||||
new ColumnDef('keypair', 'varchar',
|
new ColumnDef('keypair', 'text',
|
||||||
255, false),
|
false, false),
|
||||||
new ColumnDef('alg', 'varchar',
|
new ColumnDef('alg', 'varchar',
|
||||||
64, false));
|
64, false));
|
||||||
}
|
}
|
||||||
@ -99,17 +100,20 @@ class Magicsig extends Memcached_DataObject
|
|||||||
return parent::insert();
|
return parent::insert();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generate($user_id, $key_length = 512)
|
public function generate($user_id)
|
||||||
{
|
{
|
||||||
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
|
$rsa = new Crypt_RSA();
|
||||||
|
|
||||||
|
$keypair = $rsa->createKey();
|
||||||
|
|
||||||
$keypair = new Crypt_RSA_KeyPair($key_length);
|
$rsa->loadKey($keypair['privatekey']);
|
||||||
$params['public_key'] = $keypair->getPublicKey();
|
|
||||||
$params['private_key'] = $keypair->getPrivateKey();
|
|
||||||
|
|
||||||
$this->_rsa = new Crypt_RSA($params);
|
$this->privateKey = new Crypt_RSA();
|
||||||
PEAR::popErrorHandling();
|
$this->privateKey->loadKey($keypair['privatekey']);
|
||||||
|
|
||||||
|
$this->publicKey = new Crypt_RSA();
|
||||||
|
$this->publicKey->loadKey($keypair['publickey']);
|
||||||
|
|
||||||
$this->user_id = $user_id;
|
$this->user_id = $user_id;
|
||||||
$this->insert();
|
$this->insert();
|
||||||
}
|
}
|
||||||
@ -117,14 +121,11 @@ class Magicsig extends Memcached_DataObject
|
|||||||
|
|
||||||
public function toString($full_pair = true)
|
public function toString($full_pair = true)
|
||||||
{
|
{
|
||||||
$public_key = $this->_rsa->_public_key;
|
$mod = base64_url_encode($this->publicKey->modulus->toBytes());
|
||||||
$private_key = $this->_rsa->_private_key;
|
$exp = base64_url_encode($this->publicKey->exponent->toBytes());
|
||||||
|
|
||||||
$mod = base64_url_encode($public_key->getModulus());
|
|
||||||
$exp = base64_url_encode($public_key->getExponent());
|
|
||||||
$private_exp = '';
|
$private_exp = '';
|
||||||
if ($full_pair && $private_key->getExponent()) {
|
if ($full_pair && $this->privateKey->exponent->toBytes()) {
|
||||||
$private_exp = '.' . base64_url_encode($private_key->getExponent());
|
$private_exp = '.' . base64_url_encode($this->privateKey->exponent->toBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'RSA.' . $mod . '.' . $exp . $private_exp;
|
return 'RSA.' . $mod . '.' . $exp . $private_exp;
|
||||||
@ -132,8 +133,6 @@ class Magicsig extends Memcached_DataObject
|
|||||||
|
|
||||||
public static function fromString($text)
|
public static function fromString($text)
|
||||||
{
|
{
|
||||||
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
|
|
||||||
|
|
||||||
$magic_sig = new Magicsig();
|
$magic_sig = new Magicsig();
|
||||||
|
|
||||||
// remove whitespace
|
// remove whitespace
|
||||||
@ -144,35 +143,40 @@ class Magicsig extends Memcached_DataObject
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$mod = base64_url_decode($matches[1]);
|
$mod = $matches[1];
|
||||||
$exp = base64_url_decode($matches[2]);
|
$exp = $matches[2];
|
||||||
if (!empty($matches[4])) {
|
if (!empty($matches[4])) {
|
||||||
$private_exp = base64_url_decode($matches[4]);
|
$private_exp = $matches[4];
|
||||||
} else {
|
} else {
|
||||||
$private_exp = false;
|
$private_exp = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$params['public_key'] = new Crypt_RSA_KEY($mod, $exp, 'public');
|
$magic_sig->loadKey($mod, $exp, 'public');
|
||||||
if ($params['public_key']->isError()) {
|
|
||||||
$error = $params['public_key']->getLastError();
|
|
||||||
common_log(LOG_DEBUG, 'RSA Error: '. $error->getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ($private_exp) {
|
if ($private_exp) {
|
||||||
$params['private_key'] = new Crypt_RSA_KEY($mod, $private_exp, 'private');
|
$magic_sig->loadKey($mod, $private_exp, 'private');
|
||||||
if ($params['private_key']->isError()) {
|
|
||||||
$error = $params['private_key']->getLastError();
|
|
||||||
common_log(LOG_DEBUG, 'RSA Error: '. $error->getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$magic_sig->_rsa = new Crypt_RSA($params);
|
|
||||||
PEAR::popErrorHandling();
|
|
||||||
|
|
||||||
return $magic_sig;
|
return $magic_sig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function loadKey($mod, $exp, $type = 'public')
|
||||||
|
{
|
||||||
|
common_log(LOG_DEBUG, "Adding ".$type." key: (".$mod .', '. $exp .")");
|
||||||
|
|
||||||
|
$rsa = new Crypt_RSA();
|
||||||
|
$rsa->signatureMode = CRYPT_RSA_SIGNATURE_PKCS1;
|
||||||
|
$rsa->setHash('sha256');
|
||||||
|
$rsa->modulus = new Math_BigInteger(base64_url_decode($mod), 256);
|
||||||
|
$rsa->k = strlen($rsa->modulus->toBytes());
|
||||||
|
$rsa->exponent = new Math_BigInteger(base64_url_decode($exp), 256);
|
||||||
|
|
||||||
|
if ($type == 'private') {
|
||||||
|
$this->privateKey = $rsa;
|
||||||
|
} else {
|
||||||
|
$this->publicKey = $rsa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function getName()
|
public function getName()
|
||||||
{
|
{
|
||||||
return $this->alg;
|
return $this->alg;
|
||||||
@ -183,45 +187,25 @@ class Magicsig extends Memcached_DataObject
|
|||||||
switch ($this->alg) {
|
switch ($this->alg) {
|
||||||
|
|
||||||
case 'RSA-SHA256':
|
case 'RSA-SHA256':
|
||||||
return 'magicsig_sha256';
|
return 'sha256';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function sign($bytes)
|
public function sign($bytes)
|
||||||
{
|
{
|
||||||
$hash = $this->getHash();
|
$sig = $this->privateKey->sign($bytes);
|
||||||
$sig = $this->_rsa->createSign($bytes, null, $hash);
|
return base64_url_encode($sig);
|
||||||
if ($this->_rsa->isError()) {
|
|
||||||
$error = $this->_rsa->getLastError();
|
|
||||||
common_log(LOG_DEBUG, 'RSA Error: '. $error->getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $sig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function verify($signed_bytes, $signature)
|
public function verify($signed_bytes, $signature)
|
||||||
{
|
{
|
||||||
$hash = $this->getHash();
|
$signature = base64_url_decode($signature);
|
||||||
$result = $this->_rsa->validateSign($signed_bytes, $signature, null, $hash);
|
return $this->publicKey->verify($signed_bytes, $signature);
|
||||||
if ($this->_rsa->isError()) {
|
|
||||||
$error = $this->keypair->getLastError();
|
|
||||||
common_log(LOG_DEBUG, 'RSA Error: '. $error->getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define a sha256 function for hashing
|
|
||||||
// (Crypt_RSA should really be updated to use hash() )
|
|
||||||
function magicsig_sha256($bytes)
|
|
||||||
{
|
|
||||||
return hash('sha256', $bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
function base64_url_encode($input)
|
function base64_url_encode($input)
|
||||||
{
|
{
|
||||||
return strtr(base64_encode($input), '+/', '-_');
|
return strtr(base64_encode($input), '+/', '-_');
|
||||||
|
479
plugins/OStatus/extlib/Crypt/AES.php
Normal file
479
plugins/OStatus/extlib/Crypt/AES.php
Normal file
@ -0,0 +1,479 @@
|
|||||||
|
<?php
|
||||||
|
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure-PHP implementation of AES.
|
||||||
|
*
|
||||||
|
* Uses mcrypt, if available, and an internal implementation, otherwise.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* If {@link Crypt_AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
|
||||||
|
* {@link Crypt_AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
|
||||||
|
* it'll be null-padded to 160-bits and 160 bits will be the key length until {@link Crypt_Rijndael::setKey() setKey()}
|
||||||
|
* is called, again, at which point, it'll be recalculated.
|
||||||
|
*
|
||||||
|
* Since Crypt_AES extends Crypt_Rijndael, some functions are available to be called that, in the context of AES, don't
|
||||||
|
* make a whole lot of sense. {@link Crypt_AES::setBlockLength() setBlockLength()}, for instance. Calling that function,
|
||||||
|
* however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
|
||||||
|
*
|
||||||
|
* Here's a short example of how to use this library:
|
||||||
|
* <code>
|
||||||
|
* <?php
|
||||||
|
* include('Crypt/AES.php');
|
||||||
|
*
|
||||||
|
* $aes = new Crypt_AES();
|
||||||
|
*
|
||||||
|
* $aes->setKey('abcdefghijklmnop');
|
||||||
|
*
|
||||||
|
* $size = 10 * 1024;
|
||||||
|
* $plaintext = '';
|
||||||
|
* for ($i = 0; $i < $size; $i++) {
|
||||||
|
* $plaintext.= 'a';
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* echo $aes->decrypt($aes->encrypt($plaintext));
|
||||||
|
* ?>
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* LICENSE: This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||||
|
* MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package Crypt_AES
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright MMVIII Jim Wigginton
|
||||||
|
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||||
|
* @version $Id: AES.php,v 1.7 2010/02/09 06:10:25 terrafrost Exp $
|
||||||
|
* @link http://phpseclib.sourceforge.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Include Crypt_Rijndael
|
||||||
|
*/
|
||||||
|
require_once 'Rijndael.php';
|
||||||
|
|
||||||
|
/**#@+
|
||||||
|
* @access public
|
||||||
|
* @see Crypt_AES::encrypt()
|
||||||
|
* @see Crypt_AES::decrypt()
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Encrypt / decrypt using the Counter mode.
|
||||||
|
*
|
||||||
|
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
|
||||||
|
*
|
||||||
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
|
||||||
|
*/
|
||||||
|
define('CRYPT_AES_MODE_CTR', -1);
|
||||||
|
/**
|
||||||
|
* Encrypt / decrypt using the Electronic Code Book mode.
|
||||||
|
*
|
||||||
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
|
||||||
|
*/
|
||||||
|
define('CRYPT_AES_MODE_ECB', 1);
|
||||||
|
/**
|
||||||
|
* Encrypt / decrypt using the Code Book Chaining mode.
|
||||||
|
*
|
||||||
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
|
||||||
|
*/
|
||||||
|
define('CRYPT_AES_MODE_CBC', 2);
|
||||||
|
/**#@-*/
|
||||||
|
|
||||||
|
/**#@+
|
||||||
|
* @access private
|
||||||
|
* @see Crypt_AES::Crypt_AES()
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Toggles the internal implementation
|
||||||
|
*/
|
||||||
|
define('CRYPT_AES_MODE_INTERNAL', 1);
|
||||||
|
/**
|
||||||
|
* Toggles the mcrypt implementation
|
||||||
|
*/
|
||||||
|
define('CRYPT_AES_MODE_MCRYPT', 2);
|
||||||
|
/**#@-*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure-PHP implementation of AES.
|
||||||
|
*
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @version 0.1.0
|
||||||
|
* @access public
|
||||||
|
* @package Crypt_AES
|
||||||
|
*/
|
||||||
|
class Crypt_AES extends Crypt_Rijndael {
|
||||||
|
/**
|
||||||
|
* mcrypt resource for encryption
|
||||||
|
*
|
||||||
|
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
|
||||||
|
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
|
||||||
|
*
|
||||||
|
* @see Crypt_AES::encrypt()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $enmcrypt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mcrypt resource for decryption
|
||||||
|
*
|
||||||
|
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
|
||||||
|
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
|
||||||
|
*
|
||||||
|
* @see Crypt_AES::decrypt()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $demcrypt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default Constructor.
|
||||||
|
*
|
||||||
|
* Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
|
||||||
|
* CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC. If not explictly set, CRYPT_AES_MODE_CBC will be used.
|
||||||
|
*
|
||||||
|
* @param optional Integer $mode
|
||||||
|
* @return Crypt_AES
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function Crypt_AES($mode = CRYPT_AES_MODE_CBC)
|
||||||
|
{
|
||||||
|
if ( !defined('CRYPT_AES_MODE') ) {
|
||||||
|
switch (true) {
|
||||||
|
case extension_loaded('mcrypt'):
|
||||||
|
// i'd check to see if aes was supported, by doing in_array('des', mcrypt_list_algorithms('')),
|
||||||
|
// but since that can be changed after the object has been created, there doesn't seem to be
|
||||||
|
// a lot of point...
|
||||||
|
define('CRYPT_AES_MODE', CRYPT_AES_MODE_MCRYPT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
define('CRYPT_AES_MODE', CRYPT_AES_MODE_INTERNAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( CRYPT_AES_MODE ) {
|
||||||
|
case CRYPT_AES_MODE_MCRYPT:
|
||||||
|
switch ($mode) {
|
||||||
|
case CRYPT_AES_MODE_ECB:
|
||||||
|
$this->mode = MCRYPT_MODE_ECB;
|
||||||
|
break;
|
||||||
|
case CRYPT_AES_MODE_CTR:
|
||||||
|
// ctr doesn't have a constant associated with it even though it appears to be fairly widely
|
||||||
|
// supported. in lieu of knowing just how widely supported it is, i've, for now, opted not to
|
||||||
|
// include a compatibility layer. the layer has been implemented but, for now, is commented out.
|
||||||
|
$this->mode = 'ctr';
|
||||||
|
//$this->mode = in_array('ctr', mcrypt_list_modes()) ? 'ctr' : CRYPT_AES_MODE_CTR;
|
||||||
|
break;
|
||||||
|
case CRYPT_AES_MODE_CBC:
|
||||||
|
default:
|
||||||
|
$this->mode = MCRYPT_MODE_CBC;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
switch ($mode) {
|
||||||
|
case CRYPT_AES_MODE_ECB:
|
||||||
|
$this->mode = CRYPT_RIJNDAEL_MODE_ECB;
|
||||||
|
break;
|
||||||
|
case CRYPT_AES_MODE_CTR:
|
||||||
|
$this->mode = CRYPT_RIJNDAEL_MODE_CTR;
|
||||||
|
break;
|
||||||
|
case CRYPT_AES_MODE_CBC:
|
||||||
|
default:
|
||||||
|
$this->mode = CRYPT_RIJNDAEL_MODE_CBC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CRYPT_AES_MODE == CRYPT_AES_MODE_INTERNAL) {
|
||||||
|
parent::Crypt_Rijndael($this->mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy function
|
||||||
|
*
|
||||||
|
* Since Crypt_AES extends Crypt_Rijndael, this function is, technically, available, but it doesn't do anything.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param Integer $length
|
||||||
|
*/
|
||||||
|
function setBlockLength($length)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypts a message.
|
||||||
|
*
|
||||||
|
* $plaintext will be padded with up to 16 additional bytes. Other AES implementations may or may not pad in the
|
||||||
|
* same manner. Other common approaches to padding and the reasons why it's necessary are discussed in the following
|
||||||
|
* URL:
|
||||||
|
*
|
||||||
|
* {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
|
||||||
|
*
|
||||||
|
* An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
|
||||||
|
* strlen($plaintext) will still need to be a multiple of 16, however, arbitrary values can be added to make it that
|
||||||
|
* length.
|
||||||
|
*
|
||||||
|
* @see Crypt_AES::decrypt()
|
||||||
|
* @access public
|
||||||
|
* @param String $plaintext
|
||||||
|
*/
|
||||||
|
function encrypt($plaintext)
|
||||||
|
{
|
||||||
|
if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
|
||||||
|
$this->_mcryptSetup();
|
||||||
|
/*
|
||||||
|
if ($this->mode == CRYPT_AES_MODE_CTR) {
|
||||||
|
$iv = $this->encryptIV;
|
||||||
|
$xor = mcrypt_generic($this->enmcrypt, $this->_generate_xor(strlen($plaintext), $iv));
|
||||||
|
$ciphertext = $plaintext ^ $xor;
|
||||||
|
if ($this->continuousBuffer) {
|
||||||
|
$this->encryptIV = $iv;
|
||||||
|
}
|
||||||
|
return $ciphertext;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ($this->mode != 'ctr') {
|
||||||
|
$plaintext = $this->_pad($plaintext);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
|
||||||
|
|
||||||
|
if (!$this->continuousBuffer) {
|
||||||
|
mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ciphertext;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::encrypt($plaintext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypts a message.
|
||||||
|
*
|
||||||
|
* If strlen($ciphertext) is not a multiple of 16, null bytes will be added to the end of the string until it is.
|
||||||
|
*
|
||||||
|
* @see Crypt_AES::encrypt()
|
||||||
|
* @access public
|
||||||
|
* @param String $ciphertext
|
||||||
|
*/
|
||||||
|
function decrypt($ciphertext)
|
||||||
|
{
|
||||||
|
if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
|
||||||
|
$this->_mcryptSetup();
|
||||||
|
/*
|
||||||
|
if ($this->mode == CRYPT_AES_MODE_CTR) {
|
||||||
|
$iv = $this->decryptIV;
|
||||||
|
$xor = mcrypt_generic($this->enmcrypt, $this->_generate_xor(strlen($ciphertext), $iv));
|
||||||
|
$plaintext = $ciphertext ^ $xor;
|
||||||
|
if ($this->continuousBuffer) {
|
||||||
|
$this->decryptIV = $iv;
|
||||||
|
}
|
||||||
|
return $plaintext;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ($this->mode != 'ctr') {
|
||||||
|
// we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
|
||||||
|
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
|
||||||
|
$ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 15) & 0xFFFFFFF0, chr(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
|
||||||
|
|
||||||
|
if (!$this->continuousBuffer) {
|
||||||
|
mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->mode != 'ctr' ? $this->_unpad($plaintext) : $plaintext;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::decrypt($ciphertext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup mcrypt
|
||||||
|
*
|
||||||
|
* Validates all the variables.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function _mcryptSetup()
|
||||||
|
{
|
||||||
|
if (!$this->changed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->explicit_key_length) {
|
||||||
|
// this just copied from Crypt_Rijndael::_setup()
|
||||||
|
$length = strlen($this->key) >> 2;
|
||||||
|
if ($length > 8) {
|
||||||
|
$length = 8;
|
||||||
|
} else if ($length < 4) {
|
||||||
|
$length = 4;
|
||||||
|
}
|
||||||
|
$this->Nk = $length;
|
||||||
|
$this->key_size = $length << 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($this->Nk) {
|
||||||
|
case 4: // 128
|
||||||
|
$this->key_size = 16;
|
||||||
|
break;
|
||||||
|
case 5: // 160
|
||||||
|
case 6: // 192
|
||||||
|
$this->key_size = 24;
|
||||||
|
break;
|
||||||
|
case 7: // 224
|
||||||
|
case 8: // 256
|
||||||
|
$this->key_size = 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->key = substr($this->key, 0, $this->key_size);
|
||||||
|
$this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($this->iv, 0, 16), 16, chr(0));
|
||||||
|
|
||||||
|
if (!isset($this->enmcrypt)) {
|
||||||
|
$mode = $this->mode;
|
||||||
|
//$mode = $this->mode == CRYPT_AES_MODE_CTR ? MCRYPT_MODE_ECB : $this->mode;
|
||||||
|
|
||||||
|
$this->demcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
|
||||||
|
$this->enmcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
|
||||||
|
} // else should mcrypt_generic_deinit be called?
|
||||||
|
|
||||||
|
mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
|
||||||
|
mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
|
||||||
|
|
||||||
|
$this->changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypts a block
|
||||||
|
*
|
||||||
|
* Optimized over Crypt_Rijndael's implementation by means of loop unrolling.
|
||||||
|
*
|
||||||
|
* @see Crypt_Rijndael::_encryptBlock()
|
||||||
|
* @access private
|
||||||
|
* @param String $in
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
function _encryptBlock($in)
|
||||||
|
{
|
||||||
|
$state = unpack('N*word', $in);
|
||||||
|
|
||||||
|
$Nr = $this->Nr;
|
||||||
|
$w = $this->w;
|
||||||
|
$t0 = $this->t0;
|
||||||
|
$t1 = $this->t1;
|
||||||
|
$t2 = $this->t2;
|
||||||
|
$t3 = $this->t3;
|
||||||
|
|
||||||
|
// addRoundKey and reindex $state
|
||||||
|
$state = array(
|
||||||
|
$state['word1'] ^ $w[0][0],
|
||||||
|
$state['word2'] ^ $w[0][1],
|
||||||
|
$state['word3'] ^ $w[0][2],
|
||||||
|
$state['word4'] ^ $w[0][3]
|
||||||
|
);
|
||||||
|
|
||||||
|
// shiftRows + subWord + mixColumns + addRoundKey
|
||||||
|
// we could loop unroll this and use if statements to do more rounds as necessary, but, in my tests, that yields
|
||||||
|
// only a marginal improvement. since that also, imho, hinders the readability of the code, i've opted not to do it.
|
||||||
|
for ($round = 1; $round < $this->Nr; $round++) {
|
||||||
|
$state = array(
|
||||||
|
$t0[$state[0] & 0xFF000000] ^ $t1[$state[1] & 0x00FF0000] ^ $t2[$state[2] & 0x0000FF00] ^ $t3[$state[3] & 0x000000FF] ^ $w[$round][0],
|
||||||
|
$t0[$state[1] & 0xFF000000] ^ $t1[$state[2] & 0x00FF0000] ^ $t2[$state[3] & 0x0000FF00] ^ $t3[$state[0] & 0x000000FF] ^ $w[$round][1],
|
||||||
|
$t0[$state[2] & 0xFF000000] ^ $t1[$state[3] & 0x00FF0000] ^ $t2[$state[0] & 0x0000FF00] ^ $t3[$state[1] & 0x000000FF] ^ $w[$round][2],
|
||||||
|
$t0[$state[3] & 0xFF000000] ^ $t1[$state[0] & 0x00FF0000] ^ $t2[$state[1] & 0x0000FF00] ^ $t3[$state[2] & 0x000000FF] ^ $w[$round][3]
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// subWord
|
||||||
|
$state = array(
|
||||||
|
$this->_subWord($state[0]),
|
||||||
|
$this->_subWord($state[1]),
|
||||||
|
$this->_subWord($state[2]),
|
||||||
|
$this->_subWord($state[3])
|
||||||
|
);
|
||||||
|
|
||||||
|
// shiftRows + addRoundKey
|
||||||
|
$state = array(
|
||||||
|
($state[0] & 0xFF000000) ^ ($state[1] & 0x00FF0000) ^ ($state[2] & 0x0000FF00) ^ ($state[3] & 0x000000FF) ^ $this->w[$this->Nr][0],
|
||||||
|
($state[1] & 0xFF000000) ^ ($state[2] & 0x00FF0000) ^ ($state[3] & 0x0000FF00) ^ ($state[0] & 0x000000FF) ^ $this->w[$this->Nr][1],
|
||||||
|
($state[2] & 0xFF000000) ^ ($state[3] & 0x00FF0000) ^ ($state[0] & 0x0000FF00) ^ ($state[1] & 0x000000FF) ^ $this->w[$this->Nr][2],
|
||||||
|
($state[3] & 0xFF000000) ^ ($state[0] & 0x00FF0000) ^ ($state[1] & 0x0000FF00) ^ ($state[2] & 0x000000FF) ^ $this->w[$this->Nr][3]
|
||||||
|
);
|
||||||
|
|
||||||
|
return pack('N*', $state[0], $state[1], $state[2], $state[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypts a block
|
||||||
|
*
|
||||||
|
* Optimized over Crypt_Rijndael's implementation by means of loop unrolling.
|
||||||
|
*
|
||||||
|
* @see Crypt_Rijndael::_decryptBlock()
|
||||||
|
* @access private
|
||||||
|
* @param String $in
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
function _decryptBlock($in)
|
||||||
|
{
|
||||||
|
$state = unpack('N*word', $in);
|
||||||
|
|
||||||
|
$Nr = $this->Nr;
|
||||||
|
$dw = $this->dw;
|
||||||
|
$dt0 = $this->dt0;
|
||||||
|
$dt1 = $this->dt1;
|
||||||
|
$dt2 = $this->dt2;
|
||||||
|
$dt3 = $this->dt3;
|
||||||
|
|
||||||
|
// addRoundKey and reindex $state
|
||||||
|
$state = array(
|
||||||
|
$state['word1'] ^ $dw[$this->Nr][0],
|
||||||
|
$state['word2'] ^ $dw[$this->Nr][1],
|
||||||
|
$state['word3'] ^ $dw[$this->Nr][2],
|
||||||
|
$state['word4'] ^ $dw[$this->Nr][3]
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// invShiftRows + invSubBytes + invMixColumns + addRoundKey
|
||||||
|
for ($round = $this->Nr - 1; $round > 0; $round--) {
|
||||||
|
$state = array(
|
||||||
|
$dt0[$state[0] & 0xFF000000] ^ $dt1[$state[3] & 0x00FF0000] ^ $dt2[$state[2] & 0x0000FF00] ^ $dt3[$state[1] & 0x000000FF] ^ $dw[$round][0],
|
||||||
|
$dt0[$state[1] & 0xFF000000] ^ $dt1[$state[0] & 0x00FF0000] ^ $dt2[$state[3] & 0x0000FF00] ^ $dt3[$state[2] & 0x000000FF] ^ $dw[$round][1],
|
||||||
|
$dt0[$state[2] & 0xFF000000] ^ $dt1[$state[1] & 0x00FF0000] ^ $dt2[$state[0] & 0x0000FF00] ^ $dt3[$state[3] & 0x000000FF] ^ $dw[$round][2],
|
||||||
|
$dt0[$state[3] & 0xFF000000] ^ $dt1[$state[2] & 0x00FF0000] ^ $dt2[$state[1] & 0x0000FF00] ^ $dt3[$state[0] & 0x000000FF] ^ $dw[$round][3]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// invShiftRows + invSubWord + addRoundKey
|
||||||
|
$state = array(
|
||||||
|
$this->_invSubWord(($state[0] & 0xFF000000) ^ ($state[3] & 0x00FF0000) ^ ($state[2] & 0x0000FF00) ^ ($state[1] & 0x000000FF)) ^ $dw[0][0],
|
||||||
|
$this->_invSubWord(($state[1] & 0xFF000000) ^ ($state[0] & 0x00FF0000) ^ ($state[3] & 0x0000FF00) ^ ($state[2] & 0x000000FF)) ^ $dw[0][1],
|
||||||
|
$this->_invSubWord(($state[2] & 0xFF000000) ^ ($state[1] & 0x00FF0000) ^ ($state[0] & 0x0000FF00) ^ ($state[3] & 0x000000FF)) ^ $dw[0][2],
|
||||||
|
$this->_invSubWord(($state[3] & 0xFF000000) ^ ($state[2] & 0x00FF0000) ^ ($state[1] & 0x0000FF00) ^ ($state[0] & 0x000000FF)) ^ $dw[0][3]
|
||||||
|
);
|
||||||
|
|
||||||
|
return pack('N*', $state[0], $state[1], $state[2], $state[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: ts=4:sw=4:et:
|
||||||
|
// vim6: fdl=1:
|
945
plugins/OStatus/extlib/Crypt/DES.php
Normal file
945
plugins/OStatus/extlib/Crypt/DES.php
Normal file
@ -0,0 +1,945 @@
|
|||||||
|
<?php
|
||||||
|
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure-PHP implementation of DES.
|
||||||
|
*
|
||||||
|
* Uses mcrypt, if available, and an internal implementation, otherwise.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* Useful resources are as follows:
|
||||||
|
*
|
||||||
|
* - {@link http://en.wikipedia.org/wiki/DES_supplementary_material Wikipedia: DES supplementary material}
|
||||||
|
* - {@link http://www.itl.nist.gov/fipspubs/fip46-2.htm FIPS 46-2 - (DES), Data Encryption Standard}
|
||||||
|
* - {@link http://www.cs.eku.edu/faculty/styer/460/Encrypt/JS-DES.html JavaScript DES Example}
|
||||||
|
*
|
||||||
|
* Here's a short example of how to use this library:
|
||||||
|
* <code>
|
||||||
|
* <?php
|
||||||
|
* include('Crypt/DES.php');
|
||||||
|
*
|
||||||
|
* $des = new Crypt_DES();
|
||||||
|
*
|
||||||
|
* $des->setKey('abcdefgh');
|
||||||
|
*
|
||||||
|
* $size = 10 * 1024;
|
||||||
|
* $plaintext = '';
|
||||||
|
* for ($i = 0; $i < $size; $i++) {
|
||||||
|
* $plaintext.= 'a';
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* echo $des->decrypt($des->encrypt($plaintext));
|
||||||
|
* ?>
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* LICENSE: This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||||
|
* MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package Crypt_DES
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright MMVII Jim Wigginton
|
||||||
|
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||||
|
* @version $Id: DES.php,v 1.12 2010/02/09 06:10:26 terrafrost Exp $
|
||||||
|
* @link http://phpseclib.sourceforge.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**#@+
|
||||||
|
* @access private
|
||||||
|
* @see Crypt_DES::_prepareKey()
|
||||||
|
* @see Crypt_DES::_processBlock()
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Contains array_reverse($keys[CRYPT_DES_DECRYPT])
|
||||||
|
*/
|
||||||
|
define('CRYPT_DES_ENCRYPT', 0);
|
||||||
|
/**
|
||||||
|
* Contains array_reverse($keys[CRYPT_DES_ENCRYPT])
|
||||||
|
*/
|
||||||
|
define('CRYPT_DES_DECRYPT', 1);
|
||||||
|
/**#@-*/
|
||||||
|
|
||||||
|
/**#@+
|
||||||
|
* @access public
|
||||||
|
* @see Crypt_DES::encrypt()
|
||||||
|
* @see Crypt_DES::decrypt()
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Encrypt / decrypt using the Counter mode.
|
||||||
|
*
|
||||||
|
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
|
||||||
|
*
|
||||||
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
|
||||||
|
*/
|
||||||
|
define('CRYPT_DES_MODE_CTR', -1);
|
||||||
|
/**
|
||||||
|
* Encrypt / decrypt using the Electronic Code Book mode.
|
||||||
|
*
|
||||||
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
|
||||||
|
*/
|
||||||
|
define('CRYPT_DES_MODE_ECB', 1);
|
||||||
|
/**
|
||||||
|
* Encrypt / decrypt using the Code Book Chaining mode.
|
||||||
|
*
|
||||||
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
|
||||||
|
*/
|
||||||
|
define('CRYPT_DES_MODE_CBC', 2);
|
||||||
|
/**#@-*/
|
||||||
|
|
||||||
|
/**#@+
|
||||||
|
* @access private
|
||||||
|
* @see Crypt_DES::Crypt_DES()
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Toggles the internal implementation
|
||||||
|
*/
|
||||||
|
define('CRYPT_DES_MODE_INTERNAL', 1);
|
||||||
|
/**
|
||||||
|
* Toggles the mcrypt implementation
|
||||||
|
*/
|
||||||
|
define('CRYPT_DES_MODE_MCRYPT', 2);
|
||||||
|
/**#@-*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure-PHP implementation of DES.
|
||||||
|
*
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @version 0.1.0
|
||||||
|
* @access public
|
||||||
|
* @package Crypt_DES
|
||||||
|
*/
|
||||||
|
class Crypt_DES {
|
||||||
|
/**
|
||||||
|
* The Key Schedule
|
||||||
|
*
|
||||||
|
* @see Crypt_DES::setKey()
|
||||||
|
* @var Array
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $keys = "\0\0\0\0\0\0\0\0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Encryption Mode
|
||||||
|
*
|
||||||
|
* @see Crypt_DES::Crypt_DES()
|
||||||
|
* @var Integer
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $mode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Continuous Buffer status
|
||||||
|
*
|
||||||
|
* @see Crypt_DES::enableContinuousBuffer()
|
||||||
|
* @var Boolean
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $continuousBuffer = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Padding status
|
||||||
|
*
|
||||||
|
* @see Crypt_DES::enablePadding()
|
||||||
|
* @var Boolean
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $padding = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Initialization Vector
|
||||||
|
*
|
||||||
|
* @see Crypt_DES::setIV()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $iv = "\0\0\0\0\0\0\0\0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A "sliding" Initialization Vector
|
||||||
|
*
|
||||||
|
* @see Crypt_DES::enableContinuousBuffer()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $encryptIV = "\0\0\0\0\0\0\0\0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A "sliding" Initialization Vector
|
||||||
|
*
|
||||||
|
* @see Crypt_DES::enableContinuousBuffer()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $decryptIV = "\0\0\0\0\0\0\0\0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mcrypt resource for encryption
|
||||||
|
*
|
||||||
|
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
|
||||||
|
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
|
||||||
|
*
|
||||||
|
* @see Crypt_AES::encrypt()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $enmcrypt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mcrypt resource for decryption
|
||||||
|
*
|
||||||
|
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
|
||||||
|
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
|
||||||
|
*
|
||||||
|
* @see Crypt_AES::decrypt()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $demcrypt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the (en|de)mcrypt resource need to be (re)initialized?
|
||||||
|
*
|
||||||
|
* @see setKey()
|
||||||
|
* @see setIV()
|
||||||
|
* @var Boolean
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $changed = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default Constructor.
|
||||||
|
*
|
||||||
|
* Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
|
||||||
|
* CRYPT_DES_MODE_ECB or CRYPT_DES_MODE_CBC. If not explictly set, CRYPT_DES_MODE_CBC will be used.
|
||||||
|
*
|
||||||
|
* @param optional Integer $mode
|
||||||
|
* @return Crypt_DES
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function Crypt_DES($mode = CRYPT_MODE_DES_CBC)
|
||||||
|
{
|
||||||
|
if ( !defined('CRYPT_DES_MODE') ) {
|
||||||
|
switch (true) {
|
||||||
|
case extension_loaded('mcrypt'):
|
||||||
|
// i'd check to see if des was supported, by doing in_array('des', mcrypt_list_algorithms('')),
|
||||||
|
// but since that can be changed after the object has been created, there doesn't seem to be
|
||||||
|
// a lot of point...
|
||||||
|
define('CRYPT_DES_MODE', CRYPT_DES_MODE_MCRYPT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
define('CRYPT_DES_MODE', CRYPT_DES_MODE_INTERNAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( CRYPT_DES_MODE ) {
|
||||||
|
case CRYPT_DES_MODE_MCRYPT:
|
||||||
|
switch ($mode) {
|
||||||
|
case CRYPT_DES_MODE_ECB:
|
||||||
|
$this->mode = MCRYPT_MODE_ECB;
|
||||||
|
break;
|
||||||
|
case CRYPT_DES_MODE_CTR:
|
||||||
|
$this->mode = 'ctr';
|
||||||
|
//$this->mode = in_array('ctr', mcrypt_list_modes()) ? 'ctr' : CRYPT_DES_MODE_CTR;
|
||||||
|
break;
|
||||||
|
case CRYPT_DES_MODE_CBC:
|
||||||
|
default:
|
||||||
|
$this->mode = MCRYPT_MODE_CBC;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
switch ($mode) {
|
||||||
|
case CRYPT_DES_MODE_ECB:
|
||||||
|
case CRYPT_DES_MODE_CTR:
|
||||||
|
case CRYPT_DES_MODE_CBC:
|
||||||
|
$this->mode = $mode;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->mode = CRYPT_DES_MODE_CBC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the key.
|
||||||
|
*
|
||||||
|
* Keys can be of any length. DES, itself, uses 64-bit keys (eg. strlen($key) == 8), however, we
|
||||||
|
* only use the first eight, if $key has more then eight characters in it, and pad $key with the
|
||||||
|
* null byte if it is less then eight characters long.
|
||||||
|
*
|
||||||
|
* DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
|
||||||
|
*
|
||||||
|
* If the key is not explicitly set, it'll be assumed to be all zero's.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param String $key
|
||||||
|
*/
|
||||||
|
function setKey($key)
|
||||||
|
{
|
||||||
|
$this->keys = ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) ? substr($key, 0, 8) : $this->_prepareKey($key);
|
||||||
|
$this->changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the initialization vector. (optional)
|
||||||
|
*
|
||||||
|
* SetIV is not required when CRYPT_DES_MODE_ECB is being used. If not explictly set, it'll be assumed
|
||||||
|
* to be all zero's.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param String $iv
|
||||||
|
*/
|
||||||
|
function setIV($iv)
|
||||||
|
{
|
||||||
|
$this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, 8), 8, chr(0));
|
||||||
|
$this->changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate CTR XOR encryption key
|
||||||
|
*
|
||||||
|
* Encrypt the output of this and XOR it against the ciphertext / plaintext to get the
|
||||||
|
* plaintext / ciphertext in CTR mode.
|
||||||
|
*
|
||||||
|
* @see Crypt_DES::decrypt()
|
||||||
|
* @see Crypt_DES::encrypt()
|
||||||
|
* @access public
|
||||||
|
* @param Integer $length
|
||||||
|
* @param String $iv
|
||||||
|
*/
|
||||||
|
function _generate_xor($length, &$iv)
|
||||||
|
{
|
||||||
|
$xor = '';
|
||||||
|
$num_blocks = ($length + 7) >> 3;
|
||||||
|
for ($i = 0; $i < $num_blocks; $i++) {
|
||||||
|
$xor.= $iv;
|
||||||
|
for ($j = 4; $j <= 8; $j+=4) {
|
||||||
|
$temp = substr($iv, -$j, 4);
|
||||||
|
switch ($temp) {
|
||||||
|
case "\xFF\xFF\xFF\xFF":
|
||||||
|
$iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4);
|
||||||
|
break;
|
||||||
|
case "\x7F\xFF\xFF\xFF":
|
||||||
|
$iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4);
|
||||||
|
break 2;
|
||||||
|
default:
|
||||||
|
extract(unpack('Ncount', $temp));
|
||||||
|
$iv = substr_replace($iv, pack('N', $count + 1), -$j, 4);
|
||||||
|
break 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $xor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypts a message.
|
||||||
|
*
|
||||||
|
* $plaintext will be padded with up to 8 additional bytes. Other DES implementations may or may not pad in the
|
||||||
|
* same manner. Other common approaches to padding and the reasons why it's necessary are discussed in the following
|
||||||
|
* URL:
|
||||||
|
*
|
||||||
|
* {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
|
||||||
|
*
|
||||||
|
* An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
|
||||||
|
* strlen($plaintext) will still need to be a multiple of 8, however, arbitrary values can be added to make it that
|
||||||
|
* length.
|
||||||
|
*
|
||||||
|
* @see Crypt_DES::decrypt()
|
||||||
|
* @access public
|
||||||
|
* @param String $plaintext
|
||||||
|
*/
|
||||||
|
function encrypt($plaintext)
|
||||||
|
{
|
||||||
|
if ($this->mode != CRYPT_DES_MODE_CTR && $this->mode != 'ctr') {
|
||||||
|
$plaintext = $this->_pad($plaintext);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
|
||||||
|
if ($this->changed) {
|
||||||
|
if (!isset($this->enmcrypt)) {
|
||||||
|
$this->enmcrypt = mcrypt_module_open(MCRYPT_DES, '', $this->mode, '');
|
||||||
|
}
|
||||||
|
mcrypt_generic_init($this->enmcrypt, $this->keys, $this->encryptIV);
|
||||||
|
$this->changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
|
||||||
|
|
||||||
|
if (!$this->continuousBuffer) {
|
||||||
|
mcrypt_generic_init($this->enmcrypt, $this->keys, $this->encryptIV);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ciphertext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_array($this->keys)) {
|
||||||
|
$this->keys = $this->_prepareKey("\0\0\0\0\0\0\0\0");
|
||||||
|
}
|
||||||
|
|
||||||
|
$ciphertext = '';
|
||||||
|
switch ($this->mode) {
|
||||||
|
case CRYPT_DES_MODE_ECB:
|
||||||
|
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||||
|
$ciphertext.= $this->_processBlock(substr($plaintext, $i, 8), CRYPT_DES_ENCRYPT);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CRYPT_DES_MODE_CBC:
|
||||||
|
$xor = $this->encryptIV;
|
||||||
|
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||||
|
$block = substr($plaintext, $i, 8);
|
||||||
|
$block = $this->_processBlock($block ^ $xor, CRYPT_DES_ENCRYPT);
|
||||||
|
$xor = $block;
|
||||||
|
$ciphertext.= $block;
|
||||||
|
}
|
||||||
|
if ($this->continuousBuffer) {
|
||||||
|
$this->encryptIV = $xor;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CRYPT_DES_MODE_CTR:
|
||||||
|
$xor = $this->encryptIV;
|
||||||
|
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||||
|
$block = substr($plaintext, $i, 8);
|
||||||
|
$key = $this->_processBlock($this->_generate_xor(8, $xor), CRYPT_DES_ENCRYPT);
|
||||||
|
$ciphertext.= $block ^ $key;
|
||||||
|
}
|
||||||
|
if ($this->continuousBuffer) {
|
||||||
|
$this->encryptIV = $xor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ciphertext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypts a message.
|
||||||
|
*
|
||||||
|
* If strlen($ciphertext) is not a multiple of 8, null bytes will be added to the end of the string until it is.
|
||||||
|
*
|
||||||
|
* @see Crypt_DES::encrypt()
|
||||||
|
* @access public
|
||||||
|
* @param String $ciphertext
|
||||||
|
*/
|
||||||
|
function decrypt($ciphertext)
|
||||||
|
{
|
||||||
|
if ($this->mode != CRYPT_DES_MODE_CTR && $this->mode != 'ctr') {
|
||||||
|
// we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
|
||||||
|
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
|
||||||
|
$ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, chr(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
|
||||||
|
if ($this->changed) {
|
||||||
|
if (!isset($this->demcrypt)) {
|
||||||
|
$this->demcrypt = mcrypt_module_open(MCRYPT_DES, '', $this->mode, '');
|
||||||
|
}
|
||||||
|
mcrypt_generic_init($this->demcrypt, $this->keys, $this->decryptIV);
|
||||||
|
$this->changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
|
||||||
|
|
||||||
|
if (!$this->continuousBuffer) {
|
||||||
|
mcrypt_generic_init($this->demcrypt, $this->keys, $this->decryptIV);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->mode != 'ctr' ? $this->_unpad($plaintext) : $plaintext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_array($this->keys)) {
|
||||||
|
$this->keys = $this->_prepareKey("\0\0\0\0\0\0\0\0");
|
||||||
|
}
|
||||||
|
|
||||||
|
$plaintext = '';
|
||||||
|
switch ($this->mode) {
|
||||||
|
case CRYPT_DES_MODE_ECB:
|
||||||
|
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||||
|
$plaintext.= $this->_processBlock(substr($ciphertext, $i, 8), CRYPT_DES_DECRYPT);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CRYPT_DES_MODE_CBC:
|
||||||
|
$xor = $this->decryptIV;
|
||||||
|
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||||
|
$block = substr($ciphertext, $i, 8);
|
||||||
|
$plaintext.= $this->_processBlock($block, CRYPT_DES_DECRYPT) ^ $xor;
|
||||||
|
$xor = $block;
|
||||||
|
}
|
||||||
|
if ($this->continuousBuffer) {
|
||||||
|
$this->decryptIV = $xor;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CRYPT_DES_MODE_CTR:
|
||||||
|
$xor = $this->decryptIV;
|
||||||
|
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||||
|
$block = substr($ciphertext, $i, 8);
|
||||||
|
$key = $this->_processBlock($this->_generate_xor(8, $xor), CRYPT_DES_ENCRYPT);
|
||||||
|
$plaintext.= $block ^ $key;
|
||||||
|
}
|
||||||
|
if ($this->continuousBuffer) {
|
||||||
|
$this->decryptIV = $xor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->mode != CRYPT_DES_MODE_CTR ? $this->_unpad($plaintext) : $plaintext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Treat consecutive "packets" as if they are a continuous buffer.
|
||||||
|
*
|
||||||
|
* Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
|
||||||
|
* will yield different outputs:
|
||||||
|
*
|
||||||
|
* <code>
|
||||||
|
* echo $des->encrypt(substr($plaintext, 0, 8));
|
||||||
|
* echo $des->encrypt(substr($plaintext, 8, 8));
|
||||||
|
* </code>
|
||||||
|
* <code>
|
||||||
|
* echo $des->encrypt($plaintext);
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
|
||||||
|
* another, as demonstrated with the following:
|
||||||
|
*
|
||||||
|
* <code>
|
||||||
|
* $des->encrypt(substr($plaintext, 0, 8));
|
||||||
|
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
|
||||||
|
* </code>
|
||||||
|
* <code>
|
||||||
|
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
|
||||||
|
* outputs. The reason is due to the fact that the initialization vector's change after every encryption /
|
||||||
|
* decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
|
||||||
|
*
|
||||||
|
* Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
|
||||||
|
* encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
|
||||||
|
* continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
|
||||||
|
* however, they are also less intuitive and more likely to cause you problems.
|
||||||
|
*
|
||||||
|
* @see Crypt_DES::disableContinuousBuffer()
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function enableContinuousBuffer()
|
||||||
|
{
|
||||||
|
$this->continuousBuffer = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Treat consecutive packets as if they are a discontinuous buffer.
|
||||||
|
*
|
||||||
|
* The default behavior.
|
||||||
|
*
|
||||||
|
* @see Crypt_DES::enableContinuousBuffer()
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function disableContinuousBuffer()
|
||||||
|
{
|
||||||
|
$this->continuousBuffer = false;
|
||||||
|
$this->encryptIV = $this->iv;
|
||||||
|
$this->decryptIV = $this->iv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pad "packets".
|
||||||
|
*
|
||||||
|
* DES works by encrypting eight bytes at a time. If you ever need to encrypt or decrypt something that's not
|
||||||
|
* a multiple of eight, it becomes necessary to pad the input so that it's length is a multiple of eight.
|
||||||
|
*
|
||||||
|
* Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH1,
|
||||||
|
* where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
|
||||||
|
* away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
|
||||||
|
* transmitted separately)
|
||||||
|
*
|
||||||
|
* @see Crypt_DES::disablePadding()
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function enablePadding()
|
||||||
|
{
|
||||||
|
$this->padding = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not pad packets.
|
||||||
|
*
|
||||||
|
* @see Crypt_DES::enablePadding()
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function disablePadding()
|
||||||
|
{
|
||||||
|
$this->padding = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pads a string
|
||||||
|
*
|
||||||
|
* Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize (8).
|
||||||
|
* 8 - (strlen($text) & 7) bytes are added, each of which is equal to chr(8 - (strlen($text) & 7)
|
||||||
|
*
|
||||||
|
* If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
|
||||||
|
* and padding will, hence forth, be enabled.
|
||||||
|
*
|
||||||
|
* @see Crypt_DES::_unpad()
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function _pad($text)
|
||||||
|
{
|
||||||
|
$length = strlen($text);
|
||||||
|
|
||||||
|
if (!$this->padding) {
|
||||||
|
if (($length & 7) == 0) {
|
||||||
|
return $text;
|
||||||
|
} else {
|
||||||
|
user_error("The plaintext's length ($length) is not a multiple of the block size (8)", E_USER_NOTICE);
|
||||||
|
$this->padding = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$pad = 8 - ($length & 7);
|
||||||
|
return str_pad($text, $length + $pad, chr($pad));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unpads a string
|
||||||
|
*
|
||||||
|
* If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
|
||||||
|
* and false will be returned.
|
||||||
|
*
|
||||||
|
* @see Crypt_DES::_pad()
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function _unpad($text)
|
||||||
|
{
|
||||||
|
if (!$this->padding) {
|
||||||
|
return $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
$length = ord($text[strlen($text) - 1]);
|
||||||
|
|
||||||
|
if (!$length || $length > 8) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return substr($text, 0, -$length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypts or decrypts a 64-bit block
|
||||||
|
*
|
||||||
|
* $mode should be either CRYPT_DES_ENCRYPT or CRYPT_DES_DECRYPT. See
|
||||||
|
* {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general
|
||||||
|
* idea of what this function does.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param String $block
|
||||||
|
* @param Integer $mode
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
function _processBlock($block, $mode)
|
||||||
|
{
|
||||||
|
// s-boxes. in the official DES docs, they're described as being matrices that
|
||||||
|
// one accesses by using the first and last bits to determine the row and the
|
||||||
|
// middle four bits to determine the column. in this implementation, they've
|
||||||
|
// been converted to vectors
|
||||||
|
static $sbox = array(
|
||||||
|
array(
|
||||||
|
14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1,
|
||||||
|
3, 10 ,10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8,
|
||||||
|
4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7,
|
||||||
|
15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14,
|
||||||
|
9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5,
|
||||||
|
0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2,
|
||||||
|
5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10,
|
||||||
|
1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1,
|
||||||
|
13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7,
|
||||||
|
11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3,
|
||||||
|
1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9,
|
||||||
|
10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8,
|
||||||
|
15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1,
|
||||||
|
8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6,
|
||||||
|
4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13,
|
||||||
|
15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5,
|
||||||
|
0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8,
|
||||||
|
9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10,
|
||||||
|
7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10,
|
||||||
|
3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6,
|
||||||
|
1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7,
|
||||||
|
10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4,
|
||||||
|
10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2,
|
||||||
|
7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13,
|
||||||
|
0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$keys = $this->keys;
|
||||||
|
|
||||||
|
$temp = unpack('Na/Nb', $block);
|
||||||
|
$block = array($temp['a'], $temp['b']);
|
||||||
|
|
||||||
|
// because php does arithmetic right shifts, if the most significant bits are set, right
|
||||||
|
// shifting those into the correct position will add 1's - not 0's. this will intefere
|
||||||
|
// with the | operation unless a second & is done. so we isolate these bits and left shift
|
||||||
|
// them into place. we then & each block with 0x7FFFFFFF to prevennt 1's from being added
|
||||||
|
// for any other shifts.
|
||||||
|
$msb = array(
|
||||||
|
($block[0] >> 31) & 1,
|
||||||
|
($block[1] >> 31) & 1
|
||||||
|
);
|
||||||
|
$block[0] &= 0x7FFFFFFF;
|
||||||
|
$block[1] &= 0x7FFFFFFF;
|
||||||
|
|
||||||
|
// we isolate the appropriate bit in the appropriate integer and shift as appropriate. in
|
||||||
|
// some cases, there are going to be multiple bits in the same integer that need to be shifted
|
||||||
|
// in the same way. we combine those into one shift operation.
|
||||||
|
$block = array(
|
||||||
|
(($block[1] & 0x00000040) << 25) | (($block[1] & 0x00004000) << 16) |
|
||||||
|
(($block[1] & 0x00400001) << 7) | (($block[1] & 0x40000100) >> 2) |
|
||||||
|
(($block[0] & 0x00000040) << 21) | (($block[0] & 0x00004000) << 12) |
|
||||||
|
(($block[0] & 0x00400001) << 3) | (($block[0] & 0x40000100) >> 6) |
|
||||||
|
(($block[1] & 0x00000010) << 19) | (($block[1] & 0x00001000) << 10) |
|
||||||
|
(($block[1] & 0x00100000) << 1) | (($block[1] & 0x10000000) >> 8) |
|
||||||
|
(($block[0] & 0x00000010) << 15) | (($block[0] & 0x00001000) << 6) |
|
||||||
|
(($block[0] & 0x00100000) >> 3) | (($block[0] & 0x10000000) >> 12) |
|
||||||
|
(($block[1] & 0x00000004) << 13) | (($block[1] & 0x00000400) << 4) |
|
||||||
|
(($block[1] & 0x00040000) >> 5) | (($block[1] & 0x04000000) >> 14) |
|
||||||
|
(($block[0] & 0x00000004) << 9) | ( $block[0] & 0x00000400 ) |
|
||||||
|
(($block[0] & 0x00040000) >> 9) | (($block[0] & 0x04000000) >> 18) |
|
||||||
|
(($block[1] & 0x00010000) >> 11) | (($block[1] & 0x01000000) >> 20) |
|
||||||
|
(($block[0] & 0x00010000) >> 15) | (($block[0] & 0x01000000) >> 24)
|
||||||
|
,
|
||||||
|
(($block[1] & 0x00000080) << 24) | (($block[1] & 0x00008000) << 15) |
|
||||||
|
(($block[1] & 0x00800002) << 6) | (($block[0] & 0x00000080) << 20) |
|
||||||
|
(($block[0] & 0x00008000) << 11) | (($block[0] & 0x00800002) << 2) |
|
||||||
|
(($block[1] & 0x00000020) << 18) | (($block[1] & 0x00002000) << 9) |
|
||||||
|
( $block[1] & 0x00200000 ) | (($block[1] & 0x20000000) >> 9) |
|
||||||
|
(($block[0] & 0x00000020) << 14) | (($block[0] & 0x00002000) << 5) |
|
||||||
|
(($block[0] & 0x00200000) >> 4) | (($block[0] & 0x20000000) >> 13) |
|
||||||
|
(($block[1] & 0x00000008) << 12) | (($block[1] & 0x00000800) << 3) |
|
||||||
|
(($block[1] & 0x00080000) >> 6) | (($block[1] & 0x08000000) >> 15) |
|
||||||
|
(($block[0] & 0x00000008) << 8) | (($block[0] & 0x00000800) >> 1) |
|
||||||
|
(($block[0] & 0x00080000) >> 10) | (($block[0] & 0x08000000) >> 19) |
|
||||||
|
(($block[1] & 0x00000200) >> 3) | (($block[0] & 0x00000200) >> 7) |
|
||||||
|
(($block[1] & 0x00020000) >> 12) | (($block[1] & 0x02000000) >> 21) |
|
||||||
|
(($block[0] & 0x00020000) >> 16) | (($block[0] & 0x02000000) >> 25) |
|
||||||
|
($msb[1] << 28) | ($msb[0] << 24)
|
||||||
|
);
|
||||||
|
|
||||||
|
for ($i = 0; $i < 16; $i++) {
|
||||||
|
// start of "the Feistel (F) function" - see the following URL:
|
||||||
|
// http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
|
||||||
|
$temp = (($sbox[0][((($block[1] >> 27) & 0x1F) | (($block[1] & 1) << 5)) ^ $keys[$mode][$i][0]]) << 28)
|
||||||
|
| (($sbox[1][(($block[1] & 0x1F800000) >> 23) ^ $keys[$mode][$i][1]]) << 24)
|
||||||
|
| (($sbox[2][(($block[1] & 0x01F80000) >> 19) ^ $keys[$mode][$i][2]]) << 20)
|
||||||
|
| (($sbox[3][(($block[1] & 0x001F8000) >> 15) ^ $keys[$mode][$i][3]]) << 16)
|
||||||
|
| (($sbox[4][(($block[1] & 0x0001F800) >> 11) ^ $keys[$mode][$i][4]]) << 12)
|
||||||
|
| (($sbox[5][(($block[1] & 0x00001F80) >> 7) ^ $keys[$mode][$i][5]]) << 8)
|
||||||
|
| (($sbox[6][(($block[1] & 0x000001F8) >> 3) ^ $keys[$mode][$i][6]]) << 4)
|
||||||
|
| ( $sbox[7][((($block[1] & 0x1F) << 1) | (($block[1] >> 31) & 1)) ^ $keys[$mode][$i][7]]);
|
||||||
|
|
||||||
|
$msb = ($temp >> 31) & 1;
|
||||||
|
$temp &= 0x7FFFFFFF;
|
||||||
|
$newBlock = (($temp & 0x00010000) << 15) | (($temp & 0x02020120) << 5)
|
||||||
|
| (($temp & 0x00001800) << 17) | (($temp & 0x01000000) >> 10)
|
||||||
|
| (($temp & 0x00000008) << 24) | (($temp & 0x00100000) << 6)
|
||||||
|
| (($temp & 0x00000010) << 21) | (($temp & 0x00008000) << 9)
|
||||||
|
| (($temp & 0x00000200) << 12) | (($temp & 0x10000000) >> 27)
|
||||||
|
| (($temp & 0x00000040) << 14) | (($temp & 0x08000000) >> 8)
|
||||||
|
| (($temp & 0x00004000) << 4) | (($temp & 0x00000002) << 16)
|
||||||
|
| (($temp & 0x00442000) >> 6) | (($temp & 0x40800000) >> 15)
|
||||||
|
| (($temp & 0x00000001) << 11) | (($temp & 0x20000000) >> 20)
|
||||||
|
| (($temp & 0x00080000) >> 13) | (($temp & 0x00000004) << 3)
|
||||||
|
| (($temp & 0x04000000) >> 22) | (($temp & 0x00000480) >> 7)
|
||||||
|
| (($temp & 0x00200000) >> 19) | ($msb << 23);
|
||||||
|
// end of "the Feistel (F) function" - $newBlock is F's output
|
||||||
|
|
||||||
|
$temp = $block[1];
|
||||||
|
$block[1] = $block[0] ^ $newBlock;
|
||||||
|
$block[0] = $temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
$msb = array(
|
||||||
|
($block[0] >> 31) & 1,
|
||||||
|
($block[1] >> 31) & 1
|
||||||
|
);
|
||||||
|
$block[0] &= 0x7FFFFFFF;
|
||||||
|
$block[1] &= 0x7FFFFFFF;
|
||||||
|
|
||||||
|
$block = array(
|
||||||
|
(($block[0] & 0x01000004) << 7) | (($block[1] & 0x01000004) << 6) |
|
||||||
|
(($block[0] & 0x00010000) << 13) | (($block[1] & 0x00010000) << 12) |
|
||||||
|
(($block[0] & 0x00000100) << 19) | (($block[1] & 0x00000100) << 18) |
|
||||||
|
(($block[0] & 0x00000001) << 25) | (($block[1] & 0x00000001) << 24) |
|
||||||
|
(($block[0] & 0x02000008) >> 2) | (($block[1] & 0x02000008) >> 3) |
|
||||||
|
(($block[0] & 0x00020000) << 4) | (($block[1] & 0x00020000) << 3) |
|
||||||
|
(($block[0] & 0x00000200) << 10) | (($block[1] & 0x00000200) << 9) |
|
||||||
|
(($block[0] & 0x00000002) << 16) | (($block[1] & 0x00000002) << 15) |
|
||||||
|
(($block[0] & 0x04000000) >> 11) | (($block[1] & 0x04000000) >> 12) |
|
||||||
|
(($block[0] & 0x00040000) >> 5) | (($block[1] & 0x00040000) >> 6) |
|
||||||
|
(($block[0] & 0x00000400) << 1) | ( $block[1] & 0x00000400 ) |
|
||||||
|
(($block[0] & 0x08000000) >> 20) | (($block[1] & 0x08000000) >> 21) |
|
||||||
|
(($block[0] & 0x00080000) >> 14) | (($block[1] & 0x00080000) >> 15) |
|
||||||
|
(($block[0] & 0x00000800) >> 8) | (($block[1] & 0x00000800) >> 9)
|
||||||
|
,
|
||||||
|
(($block[0] & 0x10000040) << 3) | (($block[1] & 0x10000040) << 2) |
|
||||||
|
(($block[0] & 0x00100000) << 9) | (($block[1] & 0x00100000) << 8) |
|
||||||
|
(($block[0] & 0x00001000) << 15) | (($block[1] & 0x00001000) << 14) |
|
||||||
|
(($block[0] & 0x00000010) << 21) | (($block[1] & 0x00000010) << 20) |
|
||||||
|
(($block[0] & 0x20000080) >> 6) | (($block[1] & 0x20000080) >> 7) |
|
||||||
|
( $block[0] & 0x00200000 ) | (($block[1] & 0x00200000) >> 1) |
|
||||||
|
(($block[0] & 0x00002000) << 6) | (($block[1] & 0x00002000) << 5) |
|
||||||
|
(($block[0] & 0x00000020) << 12) | (($block[1] & 0x00000020) << 11) |
|
||||||
|
(($block[0] & 0x40000000) >> 15) | (($block[1] & 0x40000000) >> 16) |
|
||||||
|
(($block[0] & 0x00400000) >> 9) | (($block[1] & 0x00400000) >> 10) |
|
||||||
|
(($block[0] & 0x00004000) >> 3) | (($block[1] & 0x00004000) >> 4) |
|
||||||
|
(($block[0] & 0x00800000) >> 18) | (($block[1] & 0x00800000) >> 19) |
|
||||||
|
(($block[0] & 0x00008000) >> 12) | (($block[1] & 0x00008000) >> 13) |
|
||||||
|
($msb[0] << 7) | ($msb[1] << 6)
|
||||||
|
);
|
||||||
|
|
||||||
|
return pack('NN', $block[0], $block[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the key schedule.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param String $key
|
||||||
|
* @return Array
|
||||||
|
*/
|
||||||
|
function _prepareKey($key)
|
||||||
|
{
|
||||||
|
static $shifts = array( // number of key bits shifted per round
|
||||||
|
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
|
||||||
|
);
|
||||||
|
|
||||||
|
// pad the key and remove extra characters as appropriate.
|
||||||
|
$key = str_pad(substr($key, 0, 8), 8, chr(0));
|
||||||
|
|
||||||
|
$temp = unpack('Na/Nb', $key);
|
||||||
|
$key = array($temp['a'], $temp['b']);
|
||||||
|
$msb = array(
|
||||||
|
($key[0] >> 31) & 1,
|
||||||
|
($key[1] >> 31) & 1
|
||||||
|
);
|
||||||
|
$key[0] &= 0x7FFFFFFF;
|
||||||
|
$key[1] &= 0x7FFFFFFF;
|
||||||
|
|
||||||
|
$key = array(
|
||||||
|
(($key[1] & 0x00000002) << 26) | (($key[1] & 0x00000204) << 17) |
|
||||||
|
(($key[1] & 0x00020408) << 8) | (($key[1] & 0x02040800) >> 1) |
|
||||||
|
(($key[0] & 0x00000002) << 22) | (($key[0] & 0x00000204) << 13) |
|
||||||
|
(($key[0] & 0x00020408) << 4) | (($key[0] & 0x02040800) >> 5) |
|
||||||
|
(($key[1] & 0x04080000) >> 10) | (($key[0] & 0x04080000) >> 14) |
|
||||||
|
(($key[1] & 0x08000000) >> 19) | (($key[0] & 0x08000000) >> 23) |
|
||||||
|
(($key[0] & 0x00000010) >> 1) | (($key[0] & 0x00001000) >> 10) |
|
||||||
|
(($key[0] & 0x00100000) >> 19) | (($key[0] & 0x10000000) >> 28)
|
||||||
|
,
|
||||||
|
(($key[1] & 0x00000080) << 20) | (($key[1] & 0x00008000) << 11) |
|
||||||
|
(($key[1] & 0x00800000) << 2) | (($key[0] & 0x00000080) << 16) |
|
||||||
|
(($key[0] & 0x00008000) << 7) | (($key[0] & 0x00800000) >> 2) |
|
||||||
|
(($key[1] & 0x00000040) << 13) | (($key[1] & 0x00004000) << 4) |
|
||||||
|
(($key[1] & 0x00400000) >> 5) | (($key[1] & 0x40000000) >> 14) |
|
||||||
|
(($key[0] & 0x00000040) << 9) | ( $key[0] & 0x00004000 ) |
|
||||||
|
(($key[0] & 0x00400000) >> 9) | (($key[0] & 0x40000000) >> 18) |
|
||||||
|
(($key[1] & 0x00000020) << 6) | (($key[1] & 0x00002000) >> 3) |
|
||||||
|
(($key[1] & 0x00200000) >> 12) | (($key[1] & 0x20000000) >> 21) |
|
||||||
|
(($key[0] & 0x00000020) << 2) | (($key[0] & 0x00002000) >> 7) |
|
||||||
|
(($key[0] & 0x00200000) >> 16) | (($key[0] & 0x20000000) >> 25) |
|
||||||
|
(($key[1] & 0x00000010) >> 1) | (($key[1] & 0x00001000) >> 10) |
|
||||||
|
(($key[1] & 0x00100000) >> 19) | (($key[1] & 0x10000000) >> 28) |
|
||||||
|
($msb[1] << 24) | ($msb[0] << 20)
|
||||||
|
);
|
||||||
|
|
||||||
|
$keys = array();
|
||||||
|
for ($i = 0; $i < 16; $i++) {
|
||||||
|
$key[0] <<= $shifts[$i];
|
||||||
|
$temp = ($key[0] & 0xF0000000) >> 28;
|
||||||
|
$key[0] = ($key[0] | $temp) & 0x0FFFFFFF;
|
||||||
|
|
||||||
|
$key[1] <<= $shifts[$i];
|
||||||
|
$temp = ($key[1] & 0xF0000000) >> 28;
|
||||||
|
$key[1] = ($key[1] | $temp) & 0x0FFFFFFF;
|
||||||
|
|
||||||
|
$temp = array(
|
||||||
|
(($key[1] & 0x00004000) >> 9) | (($key[1] & 0x00000800) >> 7) |
|
||||||
|
(($key[1] & 0x00020000) >> 14) | (($key[1] & 0x00000010) >> 2) |
|
||||||
|
(($key[1] & 0x08000000) >> 26) | (($key[1] & 0x00800000) >> 23)
|
||||||
|
,
|
||||||
|
(($key[1] & 0x02400000) >> 20) | (($key[1] & 0x00000001) << 4) |
|
||||||
|
(($key[1] & 0x00002000) >> 10) | (($key[1] & 0x00040000) >> 18) |
|
||||||
|
(($key[1] & 0x00000080) >> 6)
|
||||||
|
,
|
||||||
|
( $key[1] & 0x00000020 ) | (($key[1] & 0x00000200) >> 5) |
|
||||||
|
(($key[1] & 0x00010000) >> 13) | (($key[1] & 0x01000000) >> 22) |
|
||||||
|
(($key[1] & 0x00000004) >> 1) | (($key[1] & 0x00100000) >> 20)
|
||||||
|
,
|
||||||
|
(($key[1] & 0x00001000) >> 7) | (($key[1] & 0x00200000) >> 17) |
|
||||||
|
(($key[1] & 0x00000002) << 2) | (($key[1] & 0x00000100) >> 6) |
|
||||||
|
(($key[1] & 0x00008000) >> 14) | (($key[1] & 0x04000000) >> 26)
|
||||||
|
,
|
||||||
|
(($key[0] & 0x00008000) >> 10) | ( $key[0] & 0x00000010 ) |
|
||||||
|
(($key[0] & 0x02000000) >> 22) | (($key[0] & 0x00080000) >> 17) |
|
||||||
|
(($key[0] & 0x00000200) >> 8) | (($key[0] & 0x00000002) >> 1)
|
||||||
|
,
|
||||||
|
(($key[0] & 0x04000000) >> 21) | (($key[0] & 0x00010000) >> 12) |
|
||||||
|
(($key[0] & 0x00000020) >> 2) | (($key[0] & 0x00000800) >> 9) |
|
||||||
|
(($key[0] & 0x00800000) >> 22) | (($key[0] & 0x00000100) >> 8)
|
||||||
|
,
|
||||||
|
(($key[0] & 0x00001000) >> 7) | (($key[0] & 0x00000088) >> 3) |
|
||||||
|
(($key[0] & 0x00020000) >> 14) | (($key[0] & 0x00000001) << 2) |
|
||||||
|
(($key[0] & 0x00400000) >> 21)
|
||||||
|
,
|
||||||
|
(($key[0] & 0x00000400) >> 5) | (($key[0] & 0x00004000) >> 10) |
|
||||||
|
(($key[0] & 0x00000040) >> 3) | (($key[0] & 0x00100000) >> 18) |
|
||||||
|
(($key[0] & 0x08000000) >> 26) | (($key[0] & 0x01000000) >> 24)
|
||||||
|
);
|
||||||
|
|
||||||
|
$keys[] = $temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
$temp = array(
|
||||||
|
CRYPT_DES_ENCRYPT => $keys,
|
||||||
|
CRYPT_DES_DECRYPT => array_reverse($keys)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: ts=4:sw=4:et:
|
||||||
|
// vim6: fdl=1:
|
816
plugins/OStatus/extlib/Crypt/Hash.php
Normal file
816
plugins/OStatus/extlib/Crypt/Hash.php
Normal file
@ -0,0 +1,816 @@
|
|||||||
|
<?php
|
||||||
|
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
|
||||||
|
*
|
||||||
|
* Uses hash() or mhash() if available and an internal implementation, otherwise. Currently supports the following:
|
||||||
|
*
|
||||||
|
* md2, md5, md5-96, sha1, sha1-96, sha256, sha384, and sha512
|
||||||
|
*
|
||||||
|
* If {@link Crypt_Hash::setKey() setKey()} is called, {@link Crypt_Hash::hash() hash()} will return the HMAC as opposed to
|
||||||
|
* the hash. If no valid algorithm is provided, sha1 will be used.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* {@internal The variable names are the same as those in
|
||||||
|
* {@link http://tools.ietf.org/html/rfc2104#section-2 RFC2104}.}}
|
||||||
|
*
|
||||||
|
* Here's a short example of how to use this library:
|
||||||
|
* <code>
|
||||||
|
* <?php
|
||||||
|
* include('Crypt/Hash.php');
|
||||||
|
*
|
||||||
|
* $hash = new Crypt_Hash('sha1');
|
||||||
|
*
|
||||||
|
* $hash->setKey('abcdefg');
|
||||||
|
*
|
||||||
|
* echo base64_encode($hash->hash('abcdefg'));
|
||||||
|
* ?>
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* LICENSE: This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||||
|
* MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package Crypt_Hash
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright MMVII Jim Wigginton
|
||||||
|
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||||
|
* @version $Id: Hash.php,v 1.6 2009/11/23 23:37:07 terrafrost Exp $
|
||||||
|
* @link http://phpseclib.sourceforge.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**#@+
|
||||||
|
* @access private
|
||||||
|
* @see Crypt_Hash::Crypt_Hash()
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Toggles the internal implementation
|
||||||
|
*/
|
||||||
|
define('CRYPT_HASH_MODE_INTERNAL', 1);
|
||||||
|
/**
|
||||||
|
* Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+.
|
||||||
|
*/
|
||||||
|
define('CRYPT_HASH_MODE_MHASH', 2);
|
||||||
|
/**
|
||||||
|
* Toggles the hash() implementation, which works on PHP 5.1.2+.
|
||||||
|
*/
|
||||||
|
define('CRYPT_HASH_MODE_HASH', 3);
|
||||||
|
/**#@-*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
|
||||||
|
*
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @version 0.1.0
|
||||||
|
* @access public
|
||||||
|
* @package Crypt_Hash
|
||||||
|
*/
|
||||||
|
class Crypt_Hash {
|
||||||
|
/**
|
||||||
|
* Byte-length of compression blocks / key (Internal HMAC)
|
||||||
|
*
|
||||||
|
* @see Crypt_Hash::setAlgorithm()
|
||||||
|
* @var Integer
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $b;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Byte-length of hash output (Internal HMAC)
|
||||||
|
*
|
||||||
|
* @see Crypt_Hash::setHash()
|
||||||
|
* @var Integer
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $l = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash Algorithm
|
||||||
|
*
|
||||||
|
* @see Crypt_Hash::setHash()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $hash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key
|
||||||
|
*
|
||||||
|
* @see Crypt_Hash::setKey()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $key = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outer XOR (Internal HMAC)
|
||||||
|
*
|
||||||
|
* @see Crypt_Hash::setKey()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $opad;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inner XOR (Internal HMAC)
|
||||||
|
*
|
||||||
|
* @see Crypt_Hash::setKey()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $ipad;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default Constructor.
|
||||||
|
*
|
||||||
|
* @param optional String $hash
|
||||||
|
* @return Crypt_Hash
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function Crypt_Hash($hash = 'sha1')
|
||||||
|
{
|
||||||
|
if ( !defined('CRYPT_HASH_MODE') ) {
|
||||||
|
switch (true) {
|
||||||
|
case extension_loaded('hash'):
|
||||||
|
define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH);
|
||||||
|
break;
|
||||||
|
case extension_loaded('mhash'):
|
||||||
|
define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_MHASH);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_INTERNAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setHash($hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the key for HMACs
|
||||||
|
*
|
||||||
|
* Keys can be of any length.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param String $key
|
||||||
|
*/
|
||||||
|
function setKey($key)
|
||||||
|
{
|
||||||
|
$this->key = $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the hash function.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param String $hash
|
||||||
|
*/
|
||||||
|
function setHash($hash)
|
||||||
|
{
|
||||||
|
switch ($hash) {
|
||||||
|
case 'md5-96':
|
||||||
|
case 'sha1-96':
|
||||||
|
$this->l = 12; // 96 / 8 = 12
|
||||||
|
break;
|
||||||
|
case 'md2':
|
||||||
|
case 'md5':
|
||||||
|
$this->l = 16;
|
||||||
|
break;
|
||||||
|
case 'sha1':
|
||||||
|
$this->l = 20;
|
||||||
|
break;
|
||||||
|
case 'sha256':
|
||||||
|
$this->l = 32;
|
||||||
|
break;
|
||||||
|
case 'sha384':
|
||||||
|
$this->l = 48;
|
||||||
|
break;
|
||||||
|
case 'sha512':
|
||||||
|
$this->l = 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($hash) {
|
||||||
|
case 'md2':
|
||||||
|
$mode = CRYPT_HASH_MODE_INTERNAL;
|
||||||
|
break;
|
||||||
|
case 'sha384':
|
||||||
|
case 'sha512':
|
||||||
|
$mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_MHASH ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$mode = CRYPT_HASH_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( $mode ) {
|
||||||
|
case CRYPT_HASH_MODE_MHASH:
|
||||||
|
switch ($hash) {
|
||||||
|
case 'md5':
|
||||||
|
case 'md5-96':
|
||||||
|
$this->hash = MHASH_MD5;
|
||||||
|
break;
|
||||||
|
case 'sha256':
|
||||||
|
$this->hash = MHASH_SHA256;
|
||||||
|
break;
|
||||||
|
case 'sha1':
|
||||||
|
case 'sha1-96':
|
||||||
|
default:
|
||||||
|
$this->hash = MHASH_SHA1;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case CRYPT_HASH_MODE_HASH:
|
||||||
|
switch ($hash) {
|
||||||
|
case 'md5':
|
||||||
|
case 'md5-96':
|
||||||
|
$this->hash = 'md5';
|
||||||
|
return;
|
||||||
|
case 'sha256':
|
||||||
|
case 'sha384':
|
||||||
|
case 'sha512':
|
||||||
|
$this->hash = $hash;
|
||||||
|
return;
|
||||||
|
case 'sha1':
|
||||||
|
case 'sha1-96':
|
||||||
|
default:
|
||||||
|
$this->hash = 'sha1';
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($hash) {
|
||||||
|
case 'md2':
|
||||||
|
$this->b = 16;
|
||||||
|
$this->hash = array($this, '_md2');
|
||||||
|
break;
|
||||||
|
case 'md5':
|
||||||
|
case 'md5-96':
|
||||||
|
$this->b = 64;
|
||||||
|
$this->hash = array($this, '_md5');
|
||||||
|
break;
|
||||||
|
case 'sha256':
|
||||||
|
$this->b = 64;
|
||||||
|
$this->hash = array($this, '_sha256');
|
||||||
|
break;
|
||||||
|
case 'sha384':
|
||||||
|
case 'sha512':
|
||||||
|
$this->b = 128;
|
||||||
|
$this->hash = array($this, '_sha512');
|
||||||
|
break;
|
||||||
|
case 'sha1':
|
||||||
|
case 'sha1-96':
|
||||||
|
default:
|
||||||
|
$this->b = 64;
|
||||||
|
$this->hash = array($this, '_sha1');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->ipad = str_repeat(chr(0x36), $this->b);
|
||||||
|
$this->opad = str_repeat(chr(0x5C), $this->b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the HMAC.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param String $text
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
function hash($text)
|
||||||
|
{
|
||||||
|
$mode = is_array($this->hash) ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
|
||||||
|
|
||||||
|
if (!empty($this->key)) {
|
||||||
|
switch ( $mode ) {
|
||||||
|
case CRYPT_HASH_MODE_MHASH:
|
||||||
|
$output = mhash($this->hash, $text, $this->key);
|
||||||
|
break;
|
||||||
|
case CRYPT_HASH_MODE_HASH:
|
||||||
|
$output = hash_hmac($this->hash, $text, $this->key, true);
|
||||||
|
break;
|
||||||
|
case CRYPT_HASH_MODE_INTERNAL:
|
||||||
|
/* "Applications that use keys longer than B bytes will first hash the key using H and then use the
|
||||||
|
resultant L byte string as the actual key to HMAC."
|
||||||
|
|
||||||
|
-- http://tools.ietf.org/html/rfc2104#section-2 */
|
||||||
|
$key = strlen($this->key) > $this->b ? call_user_func($this->$hash, $this->key) : $this->key;
|
||||||
|
|
||||||
|
$key = str_pad($key, $this->b, chr(0)); // step 1
|
||||||
|
$temp = $this->ipad ^ $key; // step 2
|
||||||
|
$temp .= $text; // step 3
|
||||||
|
$temp = call_user_func($this->hash, $temp); // step 4
|
||||||
|
$output = $this->opad ^ $key; // step 5
|
||||||
|
$output.= $temp; // step 6
|
||||||
|
$output = call_user_func($this->hash, $output); // step 7
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch ( $mode ) {
|
||||||
|
case CRYPT_HASH_MODE_MHASH:
|
||||||
|
$output = mhash($this->hash, $text);
|
||||||
|
break;
|
||||||
|
case CRYPT_HASH_MODE_HASH:
|
||||||
|
$output = hash($this->hash, $text, true);
|
||||||
|
break;
|
||||||
|
case CRYPT_HASH_MODE_INTERNAL:
|
||||||
|
$output = call_user_func($this->hash, $text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return substr($output, 0, $this->l);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the hash length (in bytes)
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @return Integer
|
||||||
|
*/
|
||||||
|
function getLength()
|
||||||
|
{
|
||||||
|
return $this->l;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for MD5
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param String $text
|
||||||
|
*/
|
||||||
|
function _md5($m)
|
||||||
|
{
|
||||||
|
return pack('H*', md5($m));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for SHA1
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param String $text
|
||||||
|
*/
|
||||||
|
function _sha1($m)
|
||||||
|
{
|
||||||
|
return pack('H*', sha1($m));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure-PHP implementation of MD2
|
||||||
|
*
|
||||||
|
* See {@link http://tools.ietf.org/html/rfc1319 RFC1319}.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param String $text
|
||||||
|
*/
|
||||||
|
function _md2($m)
|
||||||
|
{
|
||||||
|
static $s = array(
|
||||||
|
41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
|
||||||
|
19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
|
||||||
|
76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
|
||||||
|
138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
|
||||||
|
245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
|
||||||
|
148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
|
||||||
|
39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
|
||||||
|
181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
|
||||||
|
150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
|
||||||
|
112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
|
||||||
|
96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
|
||||||
|
85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
|
||||||
|
234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
|
||||||
|
129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
|
||||||
|
8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
|
||||||
|
203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
|
||||||
|
166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
|
||||||
|
31, 26, 219, 153, 141, 51, 159, 17, 131, 20
|
||||||
|
);
|
||||||
|
|
||||||
|
// Step 1. Append Padding Bytes
|
||||||
|
$pad = 16 - (strlen($m) & 0xF);
|
||||||
|
$m.= str_repeat(chr($pad), $pad);
|
||||||
|
|
||||||
|
$length = strlen($m);
|
||||||
|
|
||||||
|
// Step 2. Append Checksum
|
||||||
|
$c = str_repeat(chr(0), 16);
|
||||||
|
$l = chr(0);
|
||||||
|
for ($i = 0; $i < $length; $i+= 16) {
|
||||||
|
for ($j = 0; $j < 16; $j++) {
|
||||||
|
$c[$j] = chr($s[ord($m[$i + $j] ^ $l)]);
|
||||||
|
$l = $c[$j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$m.= $c;
|
||||||
|
|
||||||
|
$length+= 16;
|
||||||
|
|
||||||
|
// Step 3. Initialize MD Buffer
|
||||||
|
$x = str_repeat(chr(0), 48);
|
||||||
|
|
||||||
|
// Step 4. Process Message in 16-Byte Blocks
|
||||||
|
for ($i = 0; $i < $length; $i+= 16) {
|
||||||
|
for ($j = 0; $j < 16; $j++) {
|
||||||
|
$x[$j + 16] = $m[$i + $j];
|
||||||
|
$x[$j + 32] = $x[$j + 16] ^ $x[$j];
|
||||||
|
}
|
||||||
|
$t = chr(0);
|
||||||
|
for ($j = 0; $j < 18; $j++) {
|
||||||
|
for ($k = 0; $k < 48; $k++) {
|
||||||
|
$x[$k] = $t = $x[$k] ^ chr($s[ord($t)]);
|
||||||
|
//$t = $x[$k] = $x[$k] ^ chr($s[ord($t)]);
|
||||||
|
}
|
||||||
|
$t = chr(ord($t) + $j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 5. Output
|
||||||
|
return substr($x, 0, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure-PHP implementation of SHA256
|
||||||
|
*
|
||||||
|
* See {@link http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-256_.28a_SHA-2_variant.29_pseudocode SHA-256 (a SHA-2 variant) pseudocode - Wikipedia}.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param String $text
|
||||||
|
*/
|
||||||
|
function _sha256($m)
|
||||||
|
{
|
||||||
|
if (extension_loaded('suhosin')) {
|
||||||
|
return pack('H*', sha256($m));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize variables
|
||||||
|
$hash = array(
|
||||||
|
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
||||||
|
);
|
||||||
|
// Initialize table of round constants
|
||||||
|
// (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
|
||||||
|
static $k = array(
|
||||||
|
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||||
|
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||||
|
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||||
|
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||||
|
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||||
|
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||||
|
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||||
|
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||||
|
);
|
||||||
|
|
||||||
|
// Pre-processing
|
||||||
|
$length = strlen($m);
|
||||||
|
// to round to nearest 56 mod 64, we'll add 64 - (length + (64 - 56)) % 64
|
||||||
|
$m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F));
|
||||||
|
$m[$length] = chr(0x80);
|
||||||
|
// we don't support hashing strings 512MB long
|
||||||
|
$m.= pack('N2', 0, $length << 3);
|
||||||
|
|
||||||
|
// Process the message in successive 512-bit chunks
|
||||||
|
$chunks = str_split($m, 64);
|
||||||
|
foreach ($chunks as $chunk) {
|
||||||
|
$w = array();
|
||||||
|
for ($i = 0; $i < 16; $i++) {
|
||||||
|
extract(unpack('Ntemp', $this->_string_shift($chunk, 4)));
|
||||||
|
$w[] = $temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extend the sixteen 32-bit words into sixty-four 32-bit words
|
||||||
|
for ($i = 16; $i < 64; $i++) {
|
||||||
|
$s0 = $this->_rightRotate($w[$i - 15], 7) ^
|
||||||
|
$this->_rightRotate($w[$i - 15], 18) ^
|
||||||
|
$this->_rightShift( $w[$i - 15], 3);
|
||||||
|
$s1 = $this->_rightRotate($w[$i - 2], 17) ^
|
||||||
|
$this->_rightRotate($w[$i - 2], 19) ^
|
||||||
|
$this->_rightShift( $w[$i - 2], 10);
|
||||||
|
$w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize hash value for this chunk
|
||||||
|
list($a, $b, $c, $d, $e, $f, $g, $h) = $hash;
|
||||||
|
|
||||||
|
// Main loop
|
||||||
|
for ($i = 0; $i < 64; $i++) {
|
||||||
|
$s0 = $this->_rightRotate($a, 2) ^
|
||||||
|
$this->_rightRotate($a, 13) ^
|
||||||
|
$this->_rightRotate($a, 22);
|
||||||
|
$maj = ($a & $b) ^
|
||||||
|
($a & $c) ^
|
||||||
|
($b & $c);
|
||||||
|
$t2 = $this->_add($s0, $maj);
|
||||||
|
|
||||||
|
$s1 = $this->_rightRotate($e, 6) ^
|
||||||
|
$this->_rightRotate($e, 11) ^
|
||||||
|
$this->_rightRotate($e, 25);
|
||||||
|
$ch = ($e & $f) ^
|
||||||
|
($this->_not($e) & $g);
|
||||||
|
$t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]);
|
||||||
|
|
||||||
|
$h = $g;
|
||||||
|
$g = $f;
|
||||||
|
$f = $e;
|
||||||
|
$e = $this->_add($d, $t1);
|
||||||
|
$d = $c;
|
||||||
|
$c = $b;
|
||||||
|
$b = $a;
|
||||||
|
$a = $this->_add($t1, $t2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add this chunk's hash to result so far
|
||||||
|
$hash = array(
|
||||||
|
$this->_add($hash[0], $a),
|
||||||
|
$this->_add($hash[1], $b),
|
||||||
|
$this->_add($hash[2], $c),
|
||||||
|
$this->_add($hash[3], $d),
|
||||||
|
$this->_add($hash[4], $e),
|
||||||
|
$this->_add($hash[5], $f),
|
||||||
|
$this->_add($hash[6], $g),
|
||||||
|
$this->_add($hash[7], $h)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Produce the final hash value (big-endian)
|
||||||
|
return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure-PHP implementation of SHA384 and SHA512
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param String $text
|
||||||
|
*/
|
||||||
|
function _sha512($m)
|
||||||
|
{
|
||||||
|
if (!class_exists('Math_BigInteger')) {
|
||||||
|
require_once('Math/BigInteger.php');
|
||||||
|
}
|
||||||
|
|
||||||
|
static $init384, $init512, $k;
|
||||||
|
|
||||||
|
if (!isset($k)) {
|
||||||
|
// Initialize variables
|
||||||
|
$init384 = array( // initial values for SHA384
|
||||||
|
'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939',
|
||||||
|
'67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4'
|
||||||
|
);
|
||||||
|
$init512 = array( // initial values for SHA512
|
||||||
|
'6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1',
|
||||||
|
'510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179'
|
||||||
|
);
|
||||||
|
|
||||||
|
for ($i = 0; $i < 8; $i++) {
|
||||||
|
$init384[$i] = new Math_BigInteger($init384[$i], 16);
|
||||||
|
$init384[$i]->setPrecision(64);
|
||||||
|
$init512[$i] = new Math_BigInteger($init512[$i], 16);
|
||||||
|
$init512[$i]->setPrecision(64);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize table of round constants
|
||||||
|
// (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
|
||||||
|
$k = array(
|
||||||
|
'428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc',
|
||||||
|
'3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118',
|
||||||
|
'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2',
|
||||||
|
'72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694',
|
||||||
|
'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65',
|
||||||
|
'2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5',
|
||||||
|
'983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4',
|
||||||
|
'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70',
|
||||||
|
'27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df',
|
||||||
|
'650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b',
|
||||||
|
'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30',
|
||||||
|
'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8',
|
||||||
|
'19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8',
|
||||||
|
'391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3',
|
||||||
|
'748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec',
|
||||||
|
'90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b',
|
||||||
|
'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178',
|
||||||
|
'06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b',
|
||||||
|
'28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c',
|
||||||
|
'4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817'
|
||||||
|
);
|
||||||
|
|
||||||
|
for ($i = 0; $i < 80; $i++) {
|
||||||
|
$k[$i] = new Math_BigInteger($k[$i], 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$hash = $this->l == 48 ? $init384 : $init512;
|
||||||
|
|
||||||
|
// Pre-processing
|
||||||
|
$length = strlen($m);
|
||||||
|
// to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128
|
||||||
|
$m.= str_repeat(chr(0), 128 - (($length + 16) & 0x7F));
|
||||||
|
$m[$length] = chr(0x80);
|
||||||
|
// we don't support hashing strings 512MB long
|
||||||
|
$m.= pack('N4', 0, 0, 0, $length << 3);
|
||||||
|
|
||||||
|
// Process the message in successive 1024-bit chunks
|
||||||
|
$chunks = str_split($m, 128);
|
||||||
|
foreach ($chunks as $chunk) {
|
||||||
|
$w = array();
|
||||||
|
for ($i = 0; $i < 16; $i++) {
|
||||||
|
$temp = new Math_BigInteger($this->_string_shift($chunk, 8), 256);
|
||||||
|
$temp->setPrecision(64);
|
||||||
|
$w[] = $temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extend the sixteen 32-bit words into eighty 32-bit words
|
||||||
|
for ($i = 16; $i < 80; $i++) {
|
||||||
|
$temp = array(
|
||||||
|
$w[$i - 15]->bitwise_rightRotate(1),
|
||||||
|
$w[$i - 15]->bitwise_rightRotate(8),
|
||||||
|
$w[$i - 15]->bitwise_rightShift(7)
|
||||||
|
);
|
||||||
|
$s0 = $temp[0]->bitwise_xor($temp[1]);
|
||||||
|
$s0 = $s0->bitwise_xor($temp[2]);
|
||||||
|
$temp = array(
|
||||||
|
$w[$i - 2]->bitwise_rightRotate(19),
|
||||||
|
$w[$i - 2]->bitwise_rightRotate(61),
|
||||||
|
$w[$i - 2]->bitwise_rightShift(6)
|
||||||
|
);
|
||||||
|
$s1 = $temp[0]->bitwise_xor($temp[1]);
|
||||||
|
$s1 = $s1->bitwise_xor($temp[2]);
|
||||||
|
$w[$i] = $w[$i - 16]->copy();
|
||||||
|
$w[$i] = $w[$i]->add($s0);
|
||||||
|
$w[$i] = $w[$i]->add($w[$i - 7]);
|
||||||
|
$w[$i] = $w[$i]->add($s1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize hash value for this chunk
|
||||||
|
$a = $hash[0]->copy();
|
||||||
|
$b = $hash[1]->copy();
|
||||||
|
$c = $hash[2]->copy();
|
||||||
|
$d = $hash[3]->copy();
|
||||||
|
$e = $hash[4]->copy();
|
||||||
|
$f = $hash[5]->copy();
|
||||||
|
$g = $hash[6]->copy();
|
||||||
|
$h = $hash[7]->copy();
|
||||||
|
|
||||||
|
// Main loop
|
||||||
|
for ($i = 0; $i < 80; $i++) {
|
||||||
|
$temp = array(
|
||||||
|
$a->bitwise_rightRotate(28),
|
||||||
|
$a->bitwise_rightRotate(34),
|
||||||
|
$a->bitwise_rightRotate(39)
|
||||||
|
);
|
||||||
|
$s0 = $temp[0]->bitwise_xor($temp[1]);
|
||||||
|
$s0 = $s0->bitwise_xor($temp[2]);
|
||||||
|
$temp = array(
|
||||||
|
$a->bitwise_and($b),
|
||||||
|
$a->bitwise_and($c),
|
||||||
|
$b->bitwise_and($c)
|
||||||
|
);
|
||||||
|
$maj = $temp[0]->bitwise_xor($temp[1]);
|
||||||
|
$maj = $maj->bitwise_xor($temp[2]);
|
||||||
|
$t2 = $s0->add($maj);
|
||||||
|
|
||||||
|
$temp = array(
|
||||||
|
$e->bitwise_rightRotate(14),
|
||||||
|
$e->bitwise_rightRotate(18),
|
||||||
|
$e->bitwise_rightRotate(41)
|
||||||
|
);
|
||||||
|
$s1 = $temp[0]->bitwise_xor($temp[1]);
|
||||||
|
$s1 = $s1->bitwise_xor($temp[2]);
|
||||||
|
$temp = array(
|
||||||
|
$e->bitwise_and($f),
|
||||||
|
$g->bitwise_and($e->bitwise_not())
|
||||||
|
);
|
||||||
|
$ch = $temp[0]->bitwise_xor($temp[1]);
|
||||||
|
$t1 = $h->add($s1);
|
||||||
|
$t1 = $t1->add($ch);
|
||||||
|
$t1 = $t1->add($k[$i]);
|
||||||
|
$t1 = $t1->add($w[$i]);
|
||||||
|
|
||||||
|
$h = $g->copy();
|
||||||
|
$g = $f->copy();
|
||||||
|
$f = $e->copy();
|
||||||
|
$e = $d->add($t1);
|
||||||
|
$d = $c->copy();
|
||||||
|
$c = $b->copy();
|
||||||
|
$b = $a->copy();
|
||||||
|
$a = $t1->add($t2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add this chunk's hash to result so far
|
||||||
|
$hash = array(
|
||||||
|
$hash[0]->add($a),
|
||||||
|
$hash[1]->add($b),
|
||||||
|
$hash[2]->add($c),
|
||||||
|
$hash[3]->add($d),
|
||||||
|
$hash[4]->add($e),
|
||||||
|
$hash[5]->add($f),
|
||||||
|
$hash[6]->add($g),
|
||||||
|
$hash[7]->add($h)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Produce the final hash value (big-endian)
|
||||||
|
// (Crypt_Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here)
|
||||||
|
$temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() .
|
||||||
|
$hash[4]->toBytes() . $hash[5]->toBytes();
|
||||||
|
if ($this->l != 48) {
|
||||||
|
$temp.= $hash[6]->toBytes() . $hash[7]->toBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Right Rotate
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param Integer $int
|
||||||
|
* @param Integer $amt
|
||||||
|
* @see _sha256()
|
||||||
|
* @return Integer
|
||||||
|
*/
|
||||||
|
function _rightRotate($int, $amt)
|
||||||
|
{
|
||||||
|
$invamt = 32 - $amt;
|
||||||
|
$mask = (1 << $invamt) - 1;
|
||||||
|
return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Right Shift
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param Integer $int
|
||||||
|
* @param Integer $amt
|
||||||
|
* @see _sha256()
|
||||||
|
* @return Integer
|
||||||
|
*/
|
||||||
|
function _rightShift($int, $amt)
|
||||||
|
{
|
||||||
|
$mask = (1 << (32 - $amt)) - 1;
|
||||||
|
return ($int >> $amt) & $mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param Integer $int
|
||||||
|
* @see _sha256()
|
||||||
|
* @return Integer
|
||||||
|
*/
|
||||||
|
function _not($int)
|
||||||
|
{
|
||||||
|
return ~$int & 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add
|
||||||
|
*
|
||||||
|
* _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the
|
||||||
|
* possibility of overflow exists, care has to be taken. Math_BigInteger() could be used but this should be faster.
|
||||||
|
*
|
||||||
|
* @param String $string
|
||||||
|
* @param optional Integer $index
|
||||||
|
* @return String
|
||||||
|
* @see _sha256()
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function _add()
|
||||||
|
{
|
||||||
|
static $mod;
|
||||||
|
if (!isset($mod)) {
|
||||||
|
$mod = pow(2, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = 0;
|
||||||
|
$arguments = func_get_args();
|
||||||
|
foreach ($arguments as $argument) {
|
||||||
|
$result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmod($result, $mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String Shift
|
||||||
|
*
|
||||||
|
* Inspired by array_shift
|
||||||
|
*
|
||||||
|
* @param String $string
|
||||||
|
* @param optional Integer $index
|
||||||
|
* @return String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function _string_shift(&$string, $index = 1)
|
||||||
|
{
|
||||||
|
$substr = substr($string, 0, $index);
|
||||||
|
$string = substr($string, $index);
|
||||||
|
return $substr;
|
||||||
|
}
|
||||||
|
}
|
493
plugins/OStatus/extlib/Crypt/RC4.php
Normal file
493
plugins/OStatus/extlib/Crypt/RC4.php
Normal file
@ -0,0 +1,493 @@
|
|||||||
|
<?php
|
||||||
|
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure-PHP implementation of RC4.
|
||||||
|
*
|
||||||
|
* Uses mcrypt, if available, and an internal implementation, otherwise.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* Useful resources are as follows:
|
||||||
|
*
|
||||||
|
* - {@link http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt ARCFOUR Algorithm}
|
||||||
|
* - {@link http://en.wikipedia.org/wiki/RC4 - Wikipedia: RC4}
|
||||||
|
*
|
||||||
|
* RC4 is also known as ARCFOUR or ARC4. The reason is elaborated upon at Wikipedia. This class is named RC4 and not
|
||||||
|
* ARCFOUR or ARC4 because RC4 is how it is refered to in the SSH1 specification.
|
||||||
|
*
|
||||||
|
* Here's a short example of how to use this library:
|
||||||
|
* <code>
|
||||||
|
* <?php
|
||||||
|
* include('Crypt/RC4.php');
|
||||||
|
*
|
||||||
|
* $rc4 = new Crypt_RC4();
|
||||||
|
*
|
||||||
|
* $rc4->setKey('abcdefgh');
|
||||||
|
*
|
||||||
|
* $size = 10 * 1024;
|
||||||
|
* $plaintext = '';
|
||||||
|
* for ($i = 0; $i < $size; $i++) {
|
||||||
|
* $plaintext.= 'a';
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* echo $rc4->decrypt($rc4->encrypt($plaintext));
|
||||||
|
* ?>
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* LICENSE: This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||||
|
* MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package Crypt_RC4
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright MMVII Jim Wigginton
|
||||||
|
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||||
|
* @version $Id: RC4.php,v 1.8 2009/06/09 04:00:38 terrafrost Exp $
|
||||||
|
* @link http://phpseclib.sourceforge.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**#@+
|
||||||
|
* @access private
|
||||||
|
* @see Crypt_RC4::Crypt_RC4()
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Toggles the internal implementation
|
||||||
|
*/
|
||||||
|
define('CRYPT_RC4_MODE_INTERNAL', 1);
|
||||||
|
/**
|
||||||
|
* Toggles the mcrypt implementation
|
||||||
|
*/
|
||||||
|
define('CRYPT_RC4_MODE_MCRYPT', 2);
|
||||||
|
/**#@-*/
|
||||||
|
|
||||||
|
/**#@+
|
||||||
|
* @access private
|
||||||
|
* @see Crypt_RC4::_crypt()
|
||||||
|
*/
|
||||||
|
define('CRYPT_RC4_ENCRYPT', 0);
|
||||||
|
define('CRYPT_RC4_DECRYPT', 1);
|
||||||
|
/**#@-*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure-PHP implementation of RC4.
|
||||||
|
*
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @version 0.1.0
|
||||||
|
* @access public
|
||||||
|
* @package Crypt_RC4
|
||||||
|
*/
|
||||||
|
class Crypt_RC4 {
|
||||||
|
/**
|
||||||
|
* The Key
|
||||||
|
*
|
||||||
|
* @see Crypt_RC4::setKey()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $key = "\0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Key Stream for encryption
|
||||||
|
*
|
||||||
|
* If CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT, this will be equal to the mcrypt object
|
||||||
|
*
|
||||||
|
* @see Crypt_RC4::setKey()
|
||||||
|
* @var Array
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $encryptStream = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Key Stream for decryption
|
||||||
|
*
|
||||||
|
* If CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT, this will be equal to the mcrypt object
|
||||||
|
*
|
||||||
|
* @see Crypt_RC4::setKey()
|
||||||
|
* @var Array
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $decryptStream = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The $i and $j indexes for encryption
|
||||||
|
*
|
||||||
|
* @see Crypt_RC4::_crypt()
|
||||||
|
* @var Integer
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $encryptIndex = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The $i and $j indexes for decryption
|
||||||
|
*
|
||||||
|
* @see Crypt_RC4::_crypt()
|
||||||
|
* @var Integer
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $decryptIndex = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MCrypt parameters
|
||||||
|
*
|
||||||
|
* @see Crypt_RC4::setMCrypt()
|
||||||
|
* @var Array
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $mcrypt = array('', '');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Encryption Algorithm
|
||||||
|
*
|
||||||
|
* Only used if CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT. Only possible values are MCRYPT_RC4 or MCRYPT_ARCFOUR.
|
||||||
|
*
|
||||||
|
* @see Crypt_RC4::Crypt_RC4()
|
||||||
|
* @var Integer
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $mode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default Constructor.
|
||||||
|
*
|
||||||
|
* Determines whether or not the mcrypt extension should be used.
|
||||||
|
*
|
||||||
|
* @param optional Integer $mode
|
||||||
|
* @return Crypt_RC4
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function Crypt_RC4()
|
||||||
|
{
|
||||||
|
if ( !defined('CRYPT_RC4_MODE') ) {
|
||||||
|
switch (true) {
|
||||||
|
case extension_loaded('mcrypt') && (defined('MCRYPT_ARCFOUR') || defined('MCRYPT_RC4')):
|
||||||
|
// i'd check to see if rc4 was supported, by doing in_array('arcfour', mcrypt_list_algorithms('')),
|
||||||
|
// but since that can be changed after the object has been created, there doesn't seem to be
|
||||||
|
// a lot of point...
|
||||||
|
define('CRYPT_RC4_MODE', CRYPT_RC4_MODE_MCRYPT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
define('CRYPT_RC4_MODE', CRYPT_RC4_MODE_INTERNAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( CRYPT_RC4_MODE ) {
|
||||||
|
case CRYPT_RC4_MODE_MCRYPT:
|
||||||
|
switch (true) {
|
||||||
|
case defined('MCRYPT_ARCFOUR'):
|
||||||
|
$this->mode = MCRYPT_ARCFOUR;
|
||||||
|
break;
|
||||||
|
case defined('MCRYPT_RC4');
|
||||||
|
$this->mode = MCRYPT_RC4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the key.
|
||||||
|
*
|
||||||
|
* Keys can be between 1 and 256 bytes long. If they are longer then 256 bytes, the first 256 bytes will
|
||||||
|
* be used. If no key is explicitly set, it'll be assumed to be a single null byte.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param String $key
|
||||||
|
*/
|
||||||
|
function setKey($key)
|
||||||
|
{
|
||||||
|
$this->key = $key;
|
||||||
|
|
||||||
|
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$keyLength = strlen($key);
|
||||||
|
$keyStream = array();
|
||||||
|
for ($i = 0; $i < 256; $i++) {
|
||||||
|
$keyStream[$i] = $i;
|
||||||
|
}
|
||||||
|
$j = 0;
|
||||||
|
for ($i = 0; $i < 256; $i++) {
|
||||||
|
$j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255;
|
||||||
|
$temp = $keyStream[$i];
|
||||||
|
$keyStream[$i] = $keyStream[$j];
|
||||||
|
$keyStream[$j] = $temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->encryptIndex = $this->decryptIndex = array(0, 0);
|
||||||
|
$this->encryptStream = $this->decryptStream = $keyStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy function.
|
||||||
|
*
|
||||||
|
* Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1].
|
||||||
|
* If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before
|
||||||
|
* calling setKey().
|
||||||
|
*
|
||||||
|
* [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol,
|
||||||
|
* the IV's are relatively easy to predict, an attack described by
|
||||||
|
* {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir}
|
||||||
|
* can be used to quickly guess at the rest of the key. The following links elaborate:
|
||||||
|
*
|
||||||
|
* {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
|
||||||
|
* {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack}
|
||||||
|
*
|
||||||
|
* @param String $iv
|
||||||
|
* @see Crypt_RC4::setKey()
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function setIV($iv)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets MCrypt parameters. (optional)
|
||||||
|
*
|
||||||
|
* If MCrypt is being used, empty strings will be used, unless otherwise specified.
|
||||||
|
*
|
||||||
|
* @link http://php.net/function.mcrypt-module-open#function.mcrypt-module-open
|
||||||
|
* @access public
|
||||||
|
* @param optional Integer $algorithm_directory
|
||||||
|
* @param optional Integer $mode_directory
|
||||||
|
*/
|
||||||
|
function setMCrypt($algorithm_directory = '', $mode_directory = '')
|
||||||
|
{
|
||||||
|
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
|
||||||
|
$this->mcrypt = array($algorithm_directory, $mode_directory);
|
||||||
|
$this->_closeMCrypt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypts a message.
|
||||||
|
*
|
||||||
|
* @see Crypt_RC4::_crypt()
|
||||||
|
* @access public
|
||||||
|
* @param String $plaintext
|
||||||
|
*/
|
||||||
|
function encrypt($plaintext)
|
||||||
|
{
|
||||||
|
return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypts a message.
|
||||||
|
*
|
||||||
|
* $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
|
||||||
|
* Atleast if the continuous buffer is disabled.
|
||||||
|
*
|
||||||
|
* @see Crypt_RC4::_crypt()
|
||||||
|
* @access public
|
||||||
|
* @param String $ciphertext
|
||||||
|
*/
|
||||||
|
function decrypt($ciphertext)
|
||||||
|
{
|
||||||
|
return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypts or decrypts a message.
|
||||||
|
*
|
||||||
|
* @see Crypt_RC4::encrypt()
|
||||||
|
* @see Crypt_RC4::decrypt()
|
||||||
|
* @access private
|
||||||
|
* @param String $text
|
||||||
|
* @param Integer $mode
|
||||||
|
*/
|
||||||
|
function _crypt($text, $mode)
|
||||||
|
{
|
||||||
|
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
|
||||||
|
$keyStream = $mode == CRYPT_RC4_ENCRYPT ? 'encryptStream' : 'decryptStream';
|
||||||
|
|
||||||
|
if ($this->$keyStream === false) {
|
||||||
|
$this->$keyStream = mcrypt_module_open($this->mode, $this->mcrypt[0], MCRYPT_MODE_STREAM, $this->mcrypt[1]);
|
||||||
|
mcrypt_generic_init($this->$keyStream, $this->key, '');
|
||||||
|
} else if (!$this->continuousBuffer) {
|
||||||
|
mcrypt_generic_init($this->$keyStream, $this->key, '');
|
||||||
|
}
|
||||||
|
$newText = mcrypt_generic($this->$keyStream, $text);
|
||||||
|
if (!$this->continuousBuffer) {
|
||||||
|
mcrypt_generic_deinit($this->$keyStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $newText;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->encryptStream === false) {
|
||||||
|
$this->setKey($this->key);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($mode) {
|
||||||
|
case CRYPT_RC4_ENCRYPT:
|
||||||
|
$keyStream = $this->encryptStream;
|
||||||
|
list($i, $j) = $this->encryptIndex;
|
||||||
|
break;
|
||||||
|
case CRYPT_RC4_DECRYPT:
|
||||||
|
$keyStream = $this->decryptStream;
|
||||||
|
list($i, $j) = $this->decryptIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
$newText = '';
|
||||||
|
for ($k = 0; $k < strlen($text); $k++) {
|
||||||
|
$i = ($i + 1) & 255;
|
||||||
|
$j = ($j + $keyStream[$i]) & 255;
|
||||||
|
$temp = $keyStream[$i];
|
||||||
|
$keyStream[$i] = $keyStream[$j];
|
||||||
|
$keyStream[$j] = $temp;
|
||||||
|
$temp = $keyStream[($keyStream[$i] + $keyStream[$j]) & 255];
|
||||||
|
$newText.= chr(ord($text[$k]) ^ $temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->continuousBuffer) {
|
||||||
|
switch ($mode) {
|
||||||
|
case CRYPT_RC4_ENCRYPT:
|
||||||
|
$this->encryptStream = $keyStream;
|
||||||
|
$this->encryptIndex = array($i, $j);
|
||||||
|
break;
|
||||||
|
case CRYPT_RC4_DECRYPT:
|
||||||
|
$this->decryptStream = $keyStream;
|
||||||
|
$this->decryptIndex = array($i, $j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $newText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Treat consecutive "packets" as if they are a continuous buffer.
|
||||||
|
*
|
||||||
|
* Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
|
||||||
|
* will yield different outputs:
|
||||||
|
*
|
||||||
|
* <code>
|
||||||
|
* echo $rc4->encrypt(substr($plaintext, 0, 8));
|
||||||
|
* echo $rc4->encrypt(substr($plaintext, 8, 8));
|
||||||
|
* </code>
|
||||||
|
* <code>
|
||||||
|
* echo $rc4->encrypt($plaintext);
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
|
||||||
|
* another, as demonstrated with the following:
|
||||||
|
*
|
||||||
|
* <code>
|
||||||
|
* $rc4->encrypt(substr($plaintext, 0, 8));
|
||||||
|
* echo $rc4->decrypt($des->encrypt(substr($plaintext, 8, 8)));
|
||||||
|
* </code>
|
||||||
|
* <code>
|
||||||
|
* echo $rc4->decrypt($des->encrypt(substr($plaintext, 8, 8)));
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
|
||||||
|
* outputs. The reason is due to the fact that the initialization vector's change after every encryption /
|
||||||
|
* decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
|
||||||
|
*
|
||||||
|
* Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
|
||||||
|
* encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
|
||||||
|
* continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
|
||||||
|
* however, they are also less intuitive and more likely to cause you problems.
|
||||||
|
*
|
||||||
|
* @see Crypt_RC4::disableContinuousBuffer()
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function enableContinuousBuffer()
|
||||||
|
{
|
||||||
|
$this->continuousBuffer = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Treat consecutive packets as if they are a discontinuous buffer.
|
||||||
|
*
|
||||||
|
* The default behavior.
|
||||||
|
*
|
||||||
|
* @see Crypt_RC4::enableContinuousBuffer()
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function disableContinuousBuffer()
|
||||||
|
{
|
||||||
|
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_INTERNAL ) {
|
||||||
|
$this->encryptIndex = $this->decryptIndex = array(0, 0);
|
||||||
|
$this->setKey($this->key);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->continuousBuffer = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy function.
|
||||||
|
*
|
||||||
|
* Since RC4 is a stream cipher and not a block cipher, no padding is necessary. The only reason this function is
|
||||||
|
* included is so that you can switch between a block cipher and a stream cipher transparently.
|
||||||
|
*
|
||||||
|
* @see Crypt_RC4::disablePadding()
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function enablePadding()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy function.
|
||||||
|
*
|
||||||
|
* @see Crypt_RC4::enablePadding()
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function disablePadding()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class destructor.
|
||||||
|
*
|
||||||
|
* Will be called, automatically, if you're using PHP5. If you're using PHP4, call it yourself. Only really
|
||||||
|
* needs to be called if mcrypt is being used.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function __destruct()
|
||||||
|
{
|
||||||
|
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
|
||||||
|
$this->_closeMCrypt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properly close the MCrypt objects.
|
||||||
|
*
|
||||||
|
* @access prviate
|
||||||
|
*/
|
||||||
|
function _closeMCrypt()
|
||||||
|
{
|
||||||
|
if ( $this->encryptStream !== false ) {
|
||||||
|
if ( $this->continuousBuffer ) {
|
||||||
|
mcrypt_generic_deinit($this->encryptStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
mcrypt_module_close($this->encryptStream);
|
||||||
|
|
||||||
|
$this->encryptStream = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $this->decryptStream !== false ) {
|
||||||
|
if ( $this->continuousBuffer ) {
|
||||||
|
mcrypt_generic_deinit($this->decryptStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
mcrypt_module_close($this->decryptStream);
|
||||||
|
|
||||||
|
$this->decryptStream = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -1,234 +0,0 @@
|
|||||||
<?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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
@ -1,315 +0,0 @@
|
|||||||
<?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__));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
@ -1,804 +0,0 @@
|
|||||||
<?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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
@ -1,482 +0,0 @@
|
|||||||
<?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';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
@ -1,313 +0,0 @@
|
|||||||
<?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';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
@ -1,361 +0,0 @@
|
|||||||
<?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';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
@ -1,135 +0,0 @@
|
|||||||
<?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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
125
plugins/OStatus/extlib/Crypt/Random.php
Normal file
125
plugins/OStatus/extlib/Crypt/Random.php
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
<?php
|
||||||
|
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Random Number Generator
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* Here's a short example of how to use this library:
|
||||||
|
* <code>
|
||||||
|
* <?php
|
||||||
|
* include('Crypt/Random.php');
|
||||||
|
*
|
||||||
|
* echo crypt_random();
|
||||||
|
* ?>
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* LICENSE: This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||||
|
* MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package Crypt_Random
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright MMVII Jim Wigginton
|
||||||
|
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||||
|
* @version $Id: Random.php,v 1.6 2010/02/28 05:28:38 terrafrost Exp $
|
||||||
|
* @link http://phpseclib.sourceforge.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a random value.
|
||||||
|
*
|
||||||
|
* On 32-bit machines, the largest distance that can exist between $min and $max is 2**31.
|
||||||
|
* If $min and $max are farther apart than that then the last ($max - range) numbers.
|
||||||
|
*
|
||||||
|
* Depending on how this is being used, it may be worth while to write a replacement. For example,
|
||||||
|
* a PHP-based web app that stores its data in an SQL database can collect more entropy than this function
|
||||||
|
* can.
|
||||||
|
*
|
||||||
|
* @param optional Integer $min
|
||||||
|
* @param optional Integer $max
|
||||||
|
* @return Integer
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function crypt_random($min = 0, $max = 0x7FFFFFFF)
|
||||||
|
{
|
||||||
|
if ($min == $max) {
|
||||||
|
return $min;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see http://en.wikipedia.org/wiki//dev/random
|
||||||
|
if (file_exists('/dev/urandom')) {
|
||||||
|
$fp = fopen('/dev/urandom', 'rb');
|
||||||
|
extract(unpack('Nrandom', fread($fp, 4)));
|
||||||
|
fclose($fp);
|
||||||
|
|
||||||
|
// say $min = 0 and $max = 3. if we didn't do abs() then we could have stuff like this:
|
||||||
|
// -4 % 3 + 0 = -1, even though -1 < $min
|
||||||
|
return abs($random) % ($max - $min) + $min;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prior to PHP 4.2.0, mt_srand() had to be called before mt_rand() could be called.
|
||||||
|
Prior to PHP 5.2.6, mt_rand()'s automatic seeding was subpar, as elaborated here:
|
||||||
|
|
||||||
|
http://www.suspekt.org/2008/08/17/mt_srand-and-not-so-random-numbers/
|
||||||
|
|
||||||
|
The seeding routine is pretty much ripped from PHP's own internal GENERATE_SEED() macro:
|
||||||
|
|
||||||
|
http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3_2/ext/standard/php_rand.h?view=markup */
|
||||||
|
if (version_compare(PHP_VERSION, '5.2.5', '<=')) {
|
||||||
|
static $seeded;
|
||||||
|
if (!isset($seeded)) {
|
||||||
|
$seeded = true;
|
||||||
|
mt_srand(fmod(time() * getmypid(), 0x7FFFFFFF) ^ fmod(1000000 * lcg_value(), 0x7FFFFFFF));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static $crypto;
|
||||||
|
|
||||||
|
// The CSPRNG's Yarrow and Fortuna periodically reseed. This function can be reseeded by hitting F5
|
||||||
|
// in the browser and reloading the page.
|
||||||
|
|
||||||
|
if (!isset($crypto)) {
|
||||||
|
$key = $iv = '';
|
||||||
|
for ($i = 0; $i < 8; $i++) {
|
||||||
|
$key.= pack('n', mt_rand(0, 0xFFFF));
|
||||||
|
$iv .= pack('n', mt_rand(0, 0xFFFF));
|
||||||
|
}
|
||||||
|
switch (true) {
|
||||||
|
case class_exists('Crypt_AES'):
|
||||||
|
$crypto = new Crypt_AES(CRYPT_AES_MODE_CTR);
|
||||||
|
break;
|
||||||
|
case class_exists('Crypt_TripleDES'):
|
||||||
|
$crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
|
||||||
|
break;
|
||||||
|
case class_exists('Crypt_DES'):
|
||||||
|
$crypto = new Crypt_DES(CRYPT_DES_MODE_CTR);
|
||||||
|
break;
|
||||||
|
case class_exists('Crypt_RC4'):
|
||||||
|
$crypto = new Crypt_RC4();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
extract(unpack('Nrandom', pack('H*', sha1(mt_rand(0, 0x7FFFFFFF)))));
|
||||||
|
return abs($random) % ($max - $min) + $min;
|
||||||
|
}
|
||||||
|
$crypto->setKey($key);
|
||||||
|
$crypto->setIV($iv);
|
||||||
|
}
|
||||||
|
|
||||||
|
extract(unpack('Nrandom', $crypto->encrypt("\0\0\0\0")));
|
||||||
|
return abs($random) % ($max - $min) + $min;
|
||||||
|
}
|
||||||
|
?>
|
1242
plugins/OStatus/extlib/Crypt/Rijndael.php
Normal file
1242
plugins/OStatus/extlib/Crypt/Rijndael.php
Normal file
File diff suppressed because it is too large
Load Diff
690
plugins/OStatus/extlib/Crypt/TripleDES.php
Normal file
690
plugins/OStatus/extlib/Crypt/TripleDES.php
Normal file
@ -0,0 +1,690 @@
|
|||||||
|
<?php
|
||||||
|
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure-PHP implementation of Triple DES.
|
||||||
|
*
|
||||||
|
* Uses mcrypt, if available, and an internal implementation, otherwise. Operates in the EDE3 mode (encrypt-decrypt-encrypt).
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* Here's a short example of how to use this library:
|
||||||
|
* <code>
|
||||||
|
* <?php
|
||||||
|
* include('Crypt/TripleDES.php');
|
||||||
|
*
|
||||||
|
* $des = new Crypt_TripleDES();
|
||||||
|
*
|
||||||
|
* $des->setKey('abcdefghijklmnopqrstuvwx');
|
||||||
|
*
|
||||||
|
* $size = 10 * 1024;
|
||||||
|
* $plaintext = '';
|
||||||
|
* for ($i = 0; $i < $size; $i++) {
|
||||||
|
* $plaintext.= 'a';
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* echo $des->decrypt($des->encrypt($plaintext));
|
||||||
|
* ?>
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* LICENSE: This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||||
|
* MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package Crypt_TripleDES
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright MMVII Jim Wigginton
|
||||||
|
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||||
|
* @version $Id: TripleDES.php,v 1.13 2010/02/26 03:40:25 terrafrost Exp $
|
||||||
|
* @link http://phpseclib.sourceforge.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Include Crypt_DES
|
||||||
|
*/
|
||||||
|
require_once 'DES.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt / decrypt using inner chaining
|
||||||
|
*
|
||||||
|
* Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (CRYPT_DES_MODE_CBC3).
|
||||||
|
*/
|
||||||
|
define('CRYPT_DES_MODE_3CBC', 3);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt / decrypt using outer chaining
|
||||||
|
*
|
||||||
|
* Outer chaining is used by SSH-2 and when the mode is set to CRYPT_DES_MODE_CBC.
|
||||||
|
*/
|
||||||
|
define('CRYPT_DES_MODE_CBC3', CRYPT_DES_MODE_CBC);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure-PHP implementation of Triple DES.
|
||||||
|
*
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @version 0.1.0
|
||||||
|
* @access public
|
||||||
|
* @package Crypt_TerraDES
|
||||||
|
*/
|
||||||
|
class Crypt_TripleDES {
|
||||||
|
/**
|
||||||
|
* The Three Keys
|
||||||
|
*
|
||||||
|
* @see Crypt_TripleDES::setKey()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $key = "\0\0\0\0\0\0\0\0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Encryption Mode
|
||||||
|
*
|
||||||
|
* @see Crypt_TripleDES::Crypt_TripleDES()
|
||||||
|
* @var Integer
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $mode = CRYPT_DES_MODE_CBC;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Continuous Buffer status
|
||||||
|
*
|
||||||
|
* @see Crypt_TripleDES::enableContinuousBuffer()
|
||||||
|
* @var Boolean
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $continuousBuffer = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Padding status
|
||||||
|
*
|
||||||
|
* @see Crypt_TripleDES::enablePadding()
|
||||||
|
* @var Boolean
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $padding = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Initialization Vector
|
||||||
|
*
|
||||||
|
* @see Crypt_TripleDES::setIV()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $iv = "\0\0\0\0\0\0\0\0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A "sliding" Initialization Vector
|
||||||
|
*
|
||||||
|
* @see Crypt_TripleDES::enableContinuousBuffer()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $encryptIV = "\0\0\0\0\0\0\0\0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A "sliding" Initialization Vector
|
||||||
|
*
|
||||||
|
* @see Crypt_TripleDES::enableContinuousBuffer()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $decryptIV = "\0\0\0\0\0\0\0\0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Crypt_DES objects
|
||||||
|
*
|
||||||
|
* @var Array
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $des;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mcrypt resource for encryption
|
||||||
|
*
|
||||||
|
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
|
||||||
|
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
|
||||||
|
*
|
||||||
|
* @see Crypt_AES::encrypt()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $enmcrypt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mcrypt resource for decryption
|
||||||
|
*
|
||||||
|
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
|
||||||
|
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
|
||||||
|
*
|
||||||
|
* @see Crypt_AES::decrypt()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $demcrypt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the (en|de)mcrypt resource need to be (re)initialized?
|
||||||
|
*
|
||||||
|
* @see setKey()
|
||||||
|
* @see setIV()
|
||||||
|
* @var Boolean
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $changed = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default Constructor.
|
||||||
|
*
|
||||||
|
* Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
|
||||||
|
* CRYPT_DES_MODE_ECB or CRYPT_DES_MODE_CBC. If not explictly set, CRYPT_DES_MODE_CBC will be used.
|
||||||
|
*
|
||||||
|
* @param optional Integer $mode
|
||||||
|
* @return Crypt_TripleDES
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function Crypt_TripleDES($mode = CRYPT_DES_MODE_CBC)
|
||||||
|
{
|
||||||
|
if ( !defined('CRYPT_DES_MODE') ) {
|
||||||
|
switch (true) {
|
||||||
|
case extension_loaded('mcrypt'):
|
||||||
|
// i'd check to see if des was supported, by doing in_array('des', mcrypt_list_algorithms('')),
|
||||||
|
// but since that can be changed after the object has been created, there doesn't seem to be
|
||||||
|
// a lot of point...
|
||||||
|
define('CRYPT_DES_MODE', CRYPT_DES_MODE_MCRYPT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
define('CRYPT_DES_MODE', CRYPT_DES_MODE_INTERNAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $mode == CRYPT_DES_MODE_3CBC ) {
|
||||||
|
$this->mode = CRYPT_DES_MODE_3CBC;
|
||||||
|
$this->des = array(
|
||||||
|
new Crypt_DES(CRYPT_DES_MODE_CBC),
|
||||||
|
new Crypt_DES(CRYPT_DES_MODE_CBC),
|
||||||
|
new Crypt_DES(CRYPT_DES_MODE_CBC)
|
||||||
|
);
|
||||||
|
|
||||||
|
// we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects
|
||||||
|
$this->des[0]->disablePadding();
|
||||||
|
$this->des[1]->disablePadding();
|
||||||
|
$this->des[2]->disablePadding();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( CRYPT_DES_MODE ) {
|
||||||
|
case CRYPT_DES_MODE_MCRYPT:
|
||||||
|
switch ($mode) {
|
||||||
|
case CRYPT_DES_MODE_ECB:
|
||||||
|
$this->mode = MCRYPT_MODE_ECB;
|
||||||
|
break;
|
||||||
|
case CRYPT_DES_MODE_CTR:
|
||||||
|
$this->mode = 'ctr';
|
||||||
|
break;
|
||||||
|
case CRYPT_DES_MODE_CBC:
|
||||||
|
default:
|
||||||
|
$this->mode = MCRYPT_MODE_CBC;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->des = array(
|
||||||
|
new Crypt_DES(CRYPT_DES_MODE_ECB),
|
||||||
|
new Crypt_DES(CRYPT_DES_MODE_ECB),
|
||||||
|
new Crypt_DES(CRYPT_DES_MODE_ECB)
|
||||||
|
);
|
||||||
|
|
||||||
|
// we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects
|
||||||
|
$this->des[0]->disablePadding();
|
||||||
|
$this->des[1]->disablePadding();
|
||||||
|
$this->des[2]->disablePadding();
|
||||||
|
|
||||||
|
switch ($mode) {
|
||||||
|
case CRYPT_DES_MODE_ECB:
|
||||||
|
case CRYPT_DES_MODE_CTR:
|
||||||
|
case CRYPT_DES_MODE_CBC:
|
||||||
|
$this->mode = $mode;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->mode = CRYPT_DES_MODE_CBC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the key.
|
||||||
|
*
|
||||||
|
* Keys can be of any length. Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or
|
||||||
|
* 192-bit (eg. strlen($key) == 24) keys. This function pads and truncates $key as appropriate.
|
||||||
|
*
|
||||||
|
* DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
|
||||||
|
*
|
||||||
|
* If the key is not explicitly set, it'll be assumed to be all zero's.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param String $key
|
||||||
|
*/
|
||||||
|
function setKey($key)
|
||||||
|
{
|
||||||
|
$length = strlen($key);
|
||||||
|
if ($length > 8) {
|
||||||
|
$key = str_pad($key, 24, chr(0));
|
||||||
|
// if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:
|
||||||
|
// http://php.net/function.mcrypt-encrypt#47973
|
||||||
|
//$key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
|
||||||
|
}
|
||||||
|
$this->key = $key;
|
||||||
|
switch (true) {
|
||||||
|
case CRYPT_DES_MODE == CRYPT_DES_MODE_INTERNAL:
|
||||||
|
case $this->mode == CRYPT_DES_MODE_3CBC:
|
||||||
|
$this->des[0]->setKey(substr($key, 0, 8));
|
||||||
|
$this->des[1]->setKey(substr($key, 8, 8));
|
||||||
|
$this->des[2]->setKey(substr($key, 16, 8));
|
||||||
|
}
|
||||||
|
$this->changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the initialization vector. (optional)
|
||||||
|
*
|
||||||
|
* SetIV is not required when CRYPT_DES_MODE_ECB is being used. If not explictly set, it'll be assumed
|
||||||
|
* to be all zero's.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param String $iv
|
||||||
|
*/
|
||||||
|
function setIV($iv)
|
||||||
|
{
|
||||||
|
$this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, 8), 8, chr(0));
|
||||||
|
if ($this->mode == CRYPT_DES_MODE_3CBC) {
|
||||||
|
$this->des[0]->setIV($iv);
|
||||||
|
$this->des[1]->setIV($iv);
|
||||||
|
$this->des[2]->setIV($iv);
|
||||||
|
}
|
||||||
|
$this->changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate CTR XOR encryption key
|
||||||
|
*
|
||||||
|
* Encrypt the output of this and XOR it against the ciphertext / plaintext to get the
|
||||||
|
* plaintext / ciphertext in CTR mode.
|
||||||
|
*
|
||||||
|
* @see Crypt_DES::decrypt()
|
||||||
|
* @see Crypt_DES::encrypt()
|
||||||
|
* @access public
|
||||||
|
* @param Integer $length
|
||||||
|
* @param String $iv
|
||||||
|
*/
|
||||||
|
function _generate_xor($length, &$iv)
|
||||||
|
{
|
||||||
|
$xor = '';
|
||||||
|
$num_blocks = ($length + 7) >> 3;
|
||||||
|
for ($i = 0; $i < $num_blocks; $i++) {
|
||||||
|
$xor.= $iv;
|
||||||
|
for ($j = 4; $j <= 8; $j+=4) {
|
||||||
|
$temp = substr($iv, -$j, 4);
|
||||||
|
switch ($temp) {
|
||||||
|
case "\xFF\xFF\xFF\xFF":
|
||||||
|
$iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4);
|
||||||
|
break;
|
||||||
|
case "\x7F\xFF\xFF\xFF":
|
||||||
|
$iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4);
|
||||||
|
break 2;
|
||||||
|
default:
|
||||||
|
extract(unpack('Ncount', $temp));
|
||||||
|
$iv = substr_replace($iv, pack('N', $count + 1), -$j, 4);
|
||||||
|
break 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $xor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypts a message.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param String $plaintext
|
||||||
|
*/
|
||||||
|
function encrypt($plaintext)
|
||||||
|
{
|
||||||
|
if ($this->mode != CRYPT_DES_MODE_CTR && $this->mode != 'ctr') {
|
||||||
|
$plaintext = $this->_pad($plaintext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the key is smaller then 8, do what we'd normally do
|
||||||
|
if ($this->mode == CRYPT_DES_MODE_3CBC && strlen($this->key) > 8) {
|
||||||
|
$ciphertext = $this->des[2]->encrypt($this->des[1]->decrypt($this->des[0]->encrypt($plaintext)));
|
||||||
|
|
||||||
|
return $ciphertext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
|
||||||
|
if ($this->changed) {
|
||||||
|
if (!isset($this->enmcrypt)) {
|
||||||
|
$this->enmcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');
|
||||||
|
}
|
||||||
|
mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
|
||||||
|
$this->changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
|
||||||
|
|
||||||
|
if (!$this->continuousBuffer) {
|
||||||
|
mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ciphertext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen($this->key) <= 8) {
|
||||||
|
$this->des[0]->mode = $this->mode;
|
||||||
|
|
||||||
|
return $this->des[0]->encrypt($plaintext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
|
||||||
|
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
|
||||||
|
$plaintext = str_pad($plaintext, ceil(strlen($plaintext) / 8) * 8, chr(0));
|
||||||
|
|
||||||
|
$des = $this->des;
|
||||||
|
|
||||||
|
$ciphertext = '';
|
||||||
|
switch ($this->mode) {
|
||||||
|
case CRYPT_DES_MODE_ECB:
|
||||||
|
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||||
|
$block = substr($plaintext, $i, 8);
|
||||||
|
$block = $des[0]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||||
|
$block = $des[1]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||||
|
$block = $des[2]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||||
|
$ciphertext.= $block;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CRYPT_DES_MODE_CBC:
|
||||||
|
$xor = $this->encryptIV;
|
||||||
|
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||||
|
$block = substr($plaintext, $i, 8) ^ $xor;
|
||||||
|
$block = $des[0]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||||
|
$block = $des[1]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||||
|
$block = $des[2]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||||
|
$xor = $block;
|
||||||
|
$ciphertext.= $block;
|
||||||
|
}
|
||||||
|
if ($this->continuousBuffer) {
|
||||||
|
$this->encryptIV = $xor;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CRYPT_DES_MODE_CTR:
|
||||||
|
$xor = $this->encryptIV;
|
||||||
|
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||||
|
$key = $this->_generate_xor(8, $xor);
|
||||||
|
$key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||||
|
$key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT);
|
||||||
|
$key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||||
|
$block = substr($plaintext, $i, 8);
|
||||||
|
$ciphertext.= $block ^ $key;
|
||||||
|
}
|
||||||
|
if ($this->continuousBuffer) {
|
||||||
|
$this->encryptIV = $xor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ciphertext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypts a message.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param String $ciphertext
|
||||||
|
*/
|
||||||
|
function decrypt($ciphertext)
|
||||||
|
{
|
||||||
|
if ($this->mode == CRYPT_DES_MODE_3CBC && strlen($this->key) > 8) {
|
||||||
|
$plaintext = $this->des[0]->decrypt($this->des[1]->encrypt($this->des[2]->decrypt($ciphertext)));
|
||||||
|
|
||||||
|
return $this->_unpad($plaintext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
|
||||||
|
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
|
||||||
|
$ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, chr(0));
|
||||||
|
|
||||||
|
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
|
||||||
|
if ($this->changed) {
|
||||||
|
if (!isset($this->demcrypt)) {
|
||||||
|
$this->demcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');
|
||||||
|
}
|
||||||
|
mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
|
||||||
|
$this->changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
|
||||||
|
|
||||||
|
if (!$this->continuousBuffer) {
|
||||||
|
mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->mode != 'ctr' ? $this->_unpad($plaintext) : $plaintext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen($this->key) <= 8) {
|
||||||
|
$this->des[0]->mode = $this->mode;
|
||||||
|
|
||||||
|
return $this->_unpad($this->des[0]->decrypt($plaintext));
|
||||||
|
}
|
||||||
|
|
||||||
|
$des = $this->des;
|
||||||
|
|
||||||
|
$plaintext = '';
|
||||||
|
switch ($this->mode) {
|
||||||
|
case CRYPT_DES_MODE_ECB:
|
||||||
|
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||||
|
$block = substr($ciphertext, $i, 8);
|
||||||
|
$block = $des[2]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||||
|
$block = $des[1]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||||
|
$block = $des[0]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||||
|
$plaintext.= $block;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CRYPT_DES_MODE_CBC:
|
||||||
|
$xor = $this->decryptIV;
|
||||||
|
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||||
|
$orig = $block = substr($ciphertext, $i, 8);
|
||||||
|
$block = $des[2]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||||
|
$block = $des[1]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||||
|
$block = $des[0]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||||
|
$plaintext.= $block ^ $xor;
|
||||||
|
$xor = $orig;
|
||||||
|
}
|
||||||
|
if ($this->continuousBuffer) {
|
||||||
|
$this->decryptIV = $xor;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CRYPT_DES_MODE_CTR:
|
||||||
|
$xor = $this->decryptIV;
|
||||||
|
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||||
|
$key = $this->_generate_xor(8, $xor);
|
||||||
|
$key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||||
|
$key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT);
|
||||||
|
$key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||||
|
$block = substr($ciphertext, $i, 8);
|
||||||
|
$plaintext.= $block ^ $key;
|
||||||
|
}
|
||||||
|
if ($this->continuousBuffer) {
|
||||||
|
$this->decryptIV = $xor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->mode != CRYPT_DES_MODE_CTR ? $this->_unpad($plaintext) : $plaintext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Treat consecutive "packets" as if they are a continuous buffer.
|
||||||
|
*
|
||||||
|
* Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
|
||||||
|
* will yield different outputs:
|
||||||
|
*
|
||||||
|
* <code>
|
||||||
|
* echo $des->encrypt(substr($plaintext, 0, 8));
|
||||||
|
* echo $des->encrypt(substr($plaintext, 8, 8));
|
||||||
|
* </code>
|
||||||
|
* <code>
|
||||||
|
* echo $des->encrypt($plaintext);
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
|
||||||
|
* another, as demonstrated with the following:
|
||||||
|
*
|
||||||
|
* <code>
|
||||||
|
* $des->encrypt(substr($plaintext, 0, 8));
|
||||||
|
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
|
||||||
|
* </code>
|
||||||
|
* <code>
|
||||||
|
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
|
||||||
|
* outputs. The reason is due to the fact that the initialization vector's change after every encryption /
|
||||||
|
* decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
|
||||||
|
*
|
||||||
|
* Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
|
||||||
|
* encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
|
||||||
|
* continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
|
||||||
|
* however, they are also less intuitive and more likely to cause you problems.
|
||||||
|
*
|
||||||
|
* @see Crypt_TripleDES::disableContinuousBuffer()
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function enableContinuousBuffer()
|
||||||
|
{
|
||||||
|
$this->continuousBuffer = true;
|
||||||
|
if ($this->mode == CRYPT_DES_MODE_3CBC) {
|
||||||
|
$this->des[0]->enableContinuousBuffer();
|
||||||
|
$this->des[1]->enableContinuousBuffer();
|
||||||
|
$this->des[2]->enableContinuousBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Treat consecutive packets as if they are a discontinuous buffer.
|
||||||
|
*
|
||||||
|
* The default behavior.
|
||||||
|
*
|
||||||
|
* @see Crypt_TripleDES::enableContinuousBuffer()
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function disableContinuousBuffer()
|
||||||
|
{
|
||||||
|
$this->continuousBuffer = false;
|
||||||
|
$this->encryptIV = $this->iv;
|
||||||
|
$this->decryptIV = $this->iv;
|
||||||
|
|
||||||
|
if ($this->mode == CRYPT_DES_MODE_3CBC) {
|
||||||
|
$this->des[0]->disableContinuousBuffer();
|
||||||
|
$this->des[1]->disableContinuousBuffer();
|
||||||
|
$this->des[2]->disableContinuousBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pad "packets".
|
||||||
|
*
|
||||||
|
* DES works by encrypting eight bytes at a time. If you ever need to encrypt or decrypt something that's not
|
||||||
|
* a multiple of eight, it becomes necessary to pad the input so that it's length is a multiple of eight.
|
||||||
|
*
|
||||||
|
* Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH1,
|
||||||
|
* where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
|
||||||
|
* away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
|
||||||
|
* transmitted separately)
|
||||||
|
*
|
||||||
|
* @see Crypt_TripleDES::disablePadding()
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function enablePadding()
|
||||||
|
{
|
||||||
|
$this->padding = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not pad packets.
|
||||||
|
*
|
||||||
|
* @see Crypt_TripleDES::enablePadding()
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function disablePadding()
|
||||||
|
{
|
||||||
|
$this->padding = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pads a string
|
||||||
|
*
|
||||||
|
* Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize (8).
|
||||||
|
* 8 - (strlen($text) & 7) bytes are added, each of which is equal to chr(8 - (strlen($text) & 7)
|
||||||
|
*
|
||||||
|
* If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
|
||||||
|
* and padding will, hence forth, be enabled.
|
||||||
|
*
|
||||||
|
* @see Crypt_TripleDES::_unpad()
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function _pad($text)
|
||||||
|
{
|
||||||
|
$length = strlen($text);
|
||||||
|
|
||||||
|
if (!$this->padding) {
|
||||||
|
if (($length & 7) == 0) {
|
||||||
|
return $text;
|
||||||
|
} else {
|
||||||
|
user_error("The plaintext's length ($length) is not a multiple of the block size (8)", E_USER_NOTICE);
|
||||||
|
$this->padding = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$pad = 8 - ($length & 7);
|
||||||
|
return str_pad($text, $length + $pad, chr($pad));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unpads a string
|
||||||
|
*
|
||||||
|
* If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
|
||||||
|
* and false will be returned.
|
||||||
|
*
|
||||||
|
* @see Crypt_TripleDES::_pad()
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function _unpad($text)
|
||||||
|
{
|
||||||
|
if (!$this->padding) {
|
||||||
|
return $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
$length = ord($text[strlen($text) - 1]);
|
||||||
|
|
||||||
|
if (!$length || $length > 8) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return substr($text, 0, -$length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: ts=4:sw=4:et:
|
||||||
|
// vim6: fdl=1:
|
3545
plugins/OStatus/extlib/Math/BigInteger.php
Normal file
3545
plugins/OStatus/extlib/Math/BigInteger.php
Normal file
File diff suppressed because it is too large
Load Diff
@ -154,12 +154,13 @@ class Discovery_LRDD_Host_Meta implements Discovery_LRDD
|
|||||||
{
|
{
|
||||||
public function discover($uri)
|
public function discover($uri)
|
||||||
{
|
{
|
||||||
if (!Discovery::isWebfinger($uri)) {
|
if (Discovery::isWebfinger($uri)) {
|
||||||
return false;
|
// We have a webfinger acct: - start with host-meta
|
||||||
|
list($name, $domain) = explode('@', $uri);
|
||||||
|
} else {
|
||||||
|
$domain = parse_url($uri, PHP_URL_HOST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have a webfinger acct: - start with host-meta
|
|
||||||
list($name, $domain) = explode('@', $uri);
|
|
||||||
$url = 'http://'. $domain .'/.well-known/host-meta';
|
$url = 'http://'. $domain .'/.well-known/host-meta';
|
||||||
|
|
||||||
$xrd = Discovery::fetchXrd($url);
|
$xrd = Discovery::fetchXrd($url);
|
||||||
|
@ -211,11 +211,11 @@ class FeedDiscovery
|
|||||||
$type = $node->attributes->getNamedItem('type');
|
$type = $node->attributes->getNamedItem('type');
|
||||||
$href = $node->attributes->getNamedItem('href');
|
$href = $node->attributes->getNamedItem('href');
|
||||||
if ($rel && $type && $href) {
|
if ($rel && $type && $href) {
|
||||||
$rel = trim($rel->value);
|
$rel = array_filter(explode(" ", $rel->value));
|
||||||
$type = trim($type->value);
|
$type = trim($type->value);
|
||||||
$href = trim($href->value);
|
$href = trim($href->value);
|
||||||
|
|
||||||
if (trim($rel) == 'alternate' && array_key_exists($type, $feeds) && empty($feeds[$type])) {
|
if (in_array('alternate', $rel) && array_key_exists($type, $feeds) && empty($feeds[$type])) {
|
||||||
// Save the first feed found of each type...
|
// Save the first feed found of each type...
|
||||||
$feeds[$type] = $this->resolveURI($href, $base);
|
$feeds[$type] = $this->resolveURI($href, $base);
|
||||||
}
|
}
|
||||||
|
@ -46,10 +46,10 @@ class XrdAction extends Action
|
|||||||
if (empty($xrd->subject)) {
|
if (empty($xrd->subject)) {
|
||||||
$xrd->subject = Discovery::normalize($this->uri);
|
$xrd->subject = Discovery::normalize($this->uri);
|
||||||
}
|
}
|
||||||
$xrd->alias[] = common_profile_url($nick);
|
$xrd->alias[] = $this->user->uri;
|
||||||
$xrd->links[] = array('rel' => Discovery::PROFILEPAGE,
|
$xrd->links[] = array('rel' => Discovery::PROFILEPAGE,
|
||||||
'type' => 'text/html',
|
'type' => 'text/html',
|
||||||
'href' => common_profile_url($nick));
|
'href' => $this->user->uri);
|
||||||
|
|
||||||
$xrd->links[] = array('rel' => Discovery::UPDATESFROM,
|
$xrd->links[] = array('rel' => Discovery::UPDATESFROM,
|
||||||
'href' => common_local_url('ApiTimelineUser',
|
'href' => common_local_url('ApiTimelineUser',
|
||||||
@ -65,7 +65,7 @@ class XrdAction extends Action
|
|||||||
// XFN
|
// XFN
|
||||||
$xrd->links[] = array('rel' => 'http://gmpg.org/xfn/11',
|
$xrd->links[] = array('rel' => 'http://gmpg.org/xfn/11',
|
||||||
'type' => 'text/html',
|
'type' => 'text/html',
|
||||||
'href' => common_profile_url($nick));
|
'href' => $this->user->uri);
|
||||||
// FOAF
|
// FOAF
|
||||||
$xrd->links[] = array('rel' => 'describedby',
|
$xrd->links[] = array('rel' => 'describedby',
|
||||||
'type' => 'application/rdf+xml',
|
'type' => 'application/rdf+xml',
|
||||||
|
89
plugins/OStatus/scripts/testfeed.php
Normal file
89
plugins/OStatus/scripts/testfeed.php
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* StatusNet - a distributed open-source microblogging tool
|
||||||
|
* Copyright (C) 2010, StatusNet, Inc.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));
|
||||||
|
|
||||||
|
$longoptions = array('skip=', 'count=');
|
||||||
|
|
||||||
|
$helptext = <<<END_OF_HELP
|
||||||
|
testfeed.php [options] http://example.com/atom-feed-url
|
||||||
|
Pull an Atom feed and run items in it as though they were live PuSH updates.
|
||||||
|
Mainly intended for testing funky feed formats.
|
||||||
|
|
||||||
|
--skip=N Ignore the first N items in the feed.
|
||||||
|
--count=N Only process up to N items from the feed, after skipping.
|
||||||
|
|
||||||
|
|
||||||
|
END_OF_HELP;
|
||||||
|
|
||||||
|
require_once INSTALLDIR.'/scripts/commandline.inc';
|
||||||
|
|
||||||
|
if (empty($args[0]) || !Validate::uri($args[0])) {
|
||||||
|
print "$helptext";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$feedurl = $args[0];
|
||||||
|
$skip = have_option('skip') ? intval(get_option_value('skip')) : 0;
|
||||||
|
$count = have_option('count') ? intval(get_option_value('count')) : 0;
|
||||||
|
|
||||||
|
|
||||||
|
$sub = FeedSub::staticGet('topic', $feedurl);
|
||||||
|
if (!$sub) {
|
||||||
|
print "Feed $feedurl is not subscribed.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$xml = file_get_contents($feedurl);
|
||||||
|
if ($xml === false) {
|
||||||
|
print "Bad fetch.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$feed = new DOMDocument();
|
||||||
|
if (!$feed->loadXML($xml)) {
|
||||||
|
print "Bad XML.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($skip || $count) {
|
||||||
|
$entries = $feed->getElementsByTagNameNS(ActivityUtils::ATOM, 'entry');
|
||||||
|
$remove = array();
|
||||||
|
for ($i = 0; $i < $skip && $i < $entries->length; $i++) {
|
||||||
|
$item = $entries->item($i);
|
||||||
|
if ($item) {
|
||||||
|
$remove[] = $item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($count) {
|
||||||
|
for ($i = $skip + $count; $i < $entries->length; $i++) {
|
||||||
|
$item = $entries->item($i);
|
||||||
|
if ($item) {
|
||||||
|
$remove[] = $item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($remove as $item) {
|
||||||
|
$item->parentNode->removeChild($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Event::handle('StartFeedSubReceive', array($sub, $feed));
|
||||||
|
|
Loading…
Reference in New Issue
Block a user