Merge pull request #804 from MrPetovan/task/6629-securemail-update-composer-dependencies

[securemail] Update Composer dependencies
This commit is contained in:
Tobias Diekershoff 2019-02-14 15:15:29 +01:00 committed by GitHub
commit c818eab21c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
162 changed files with 14021 additions and 7792 deletions

21
securemail/composer.json Normal file
View file

@ -0,0 +1,21 @@
{
"name": "friendica-addons/securemail",
"description": "Send notification mail encrypted with user-defined public GPG key.",
"type": "friendica-addon",
"authors": [
{
"name": "Fabio Comuni",
"homepage": "https://kirgroup.com/profile/fabrixxm",
"role": "Developer"
}
],
"require": {
"phpseclib/phpseclib": "^2.0",
"singpolyma/openpgp-php": "^0.3.0"
},
"license": "AGPL-3.0+",
"minimum-stability": "stable",
"config": {
"autoloader-suffix": "SecuremailAddon"
}
}

153
securemail/composer.lock generated Normal file
View file

@ -0,0 +1,153 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "b3a33a493eae34d9245ca7cc1b4572ea",
"packages": [
{
"name": "phpseclib/phpseclib",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/phpseclib/phpseclib.git",
"reference": "ab8028c93c03cc8d9c824efa75dc94f1db2369bf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/ab8028c93c03cc8d9c824efa75dc94f1db2369bf",
"reference": "ab8028c93c03cc8d9c824efa75dc94f1db2369bf",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phing/phing": "~2.7",
"phpunit/phpunit": "~4.0",
"sami/sami": "~2.0",
"squizlabs/php_codesniffer": "~2.0"
},
"suggest": {
"ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
"ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
},
"type": "library",
"autoload": {
"files": [
"phpseclib/bootstrap.php"
],
"psr-4": {
"phpseclib\\": "phpseclib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jim Wigginton",
"email": "terrafrost@php.net",
"role": "Lead Developer"
},
{
"name": "Patrick Monnerat",
"email": "pm@datasphere.ch",
"role": "Developer"
},
{
"name": "Andreas Fischer",
"email": "bantu@phpbb.com",
"role": "Developer"
},
{
"name": "Hans-Jürgen Petrich",
"email": "petrich@tronic-media.com",
"role": "Developer"
},
{
"name": "Graham Campbell",
"email": "graham@alt-three.com",
"role": "Developer"
}
],
"description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
"homepage": "http://phpseclib.sourceforge.net",
"keywords": [
"BigInteger",
"aes",
"asn.1",
"asn1",
"blowfish",
"crypto",
"cryptography",
"encryption",
"rsa",
"security",
"sftp",
"signature",
"signing",
"ssh",
"twofish",
"x.509",
"x509"
],
"time": "2016-10-04T00:57:04+00:00"
},
{
"name": "singpolyma/openpgp-php",
"version": "0.3.0",
"source": {
"type": "git",
"url": "https://github.com/singpolyma/openpgp-php.git",
"reference": "6006111bbc4c3b6cb8f0acb7d6c4a7047df366e8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/singpolyma/openpgp-php/zipball/6006111bbc4c3b6cb8f0acb7d6c4a7047df366e8",
"reference": "6006111bbc4c3b6cb8f0acb7d6c4a7047df366e8",
"shasum": ""
},
"require": {
"phpseclib/phpseclib": ">=2.0.0 <=2.0.4"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"type": "library",
"autoload": {
"classmap": [
"lib/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Unlicense"
],
"authors": [
{
"name": "Arto Bendiken",
"email": "arto.bendiken@gmail.com"
},
{
"name": "Stephen Paul Weber",
"email": "singpolyma@singpolyma.net"
}
],
"description": "Pure-PHP implementation of the OpenPGP Message Format (RFC 4880)",
"time": "2017-04-12T21:23:15+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}

View file

@ -15,199 +15,166 @@ use Friendica\Core\PConfig;
use Friendica\Core\Renderer;
use Friendica\Util\Emailer;
/* because the fraking openpgp-php is in composer, require libs in composer
* and then don't use autoloader to load classes... */
$path = __DIR__ . '/vendor/phpseclib/phpseclib/phpseclib/';
set_include_path(get_include_path() . PATH_SEPARATOR . $path);
/* so, we don't use the autoloader and include what we need */
$path = __DIR__ . '/vendor/singpolyma/openpgp-php/lib';
set_include_path(get_include_path() . PATH_SEPARATOR . $path);
require_once __DIR__ . '/vendor/autoload.php';
require_once 'openpgp.php';
require_once 'openpgp_crypt_symmetric.php';
function securemail_install()
{
Hook::register('addon_settings', 'addon/securemail/securemail.php', 'securemail_settings');
Hook::register('addon_settings_post', 'addon/securemail/securemail.php', 'securemail_settings_post');
Hook::register('emailer_send_prepare', 'addon/securemail/securemail.php', 'securemail_emailer_send_prepare');
function securemail_install() {
Hook::register('addon_settings', 'addon/securemail/securemail.php', 'securemail_settings');
Hook::register('addon_settings_post', 'addon/securemail/securemail.php', 'securemail_settings_post');
Hook::register('emailer_send_prepare', 'addon/securemail/securemail.php', 'securemail_emailer_send_prepare');
Logger::log('installed securemail');
Logger::log('installed securemail');
}
function securemail_uninstall() {
Hook::unregister('addon_settings', 'addon/securemail/securemail.php', 'securemail_settings');
Hook::unregister('addon_settings_post', 'addon/securemail/securemail.php', 'securemail_settings_post');
function securemail_uninstall()
{
Hook::unregister('addon_settings', 'addon/securemail/securemail.php', 'securemail_settings');
Hook::unregister('addon_settings_post', 'addon/securemail/securemail.php', 'securemail_settings_post');
Hook::unregister('emailer_send_prepare', 'addon/securemail/securemail.php', 'securemail_emailer_send_prepare');
Hook::unregister('emailer_send_prepare', 'addon/securemail/securemail.php', 'securemail_emailer_send_prepare');
Logger::log('removed securemail');
Logger::log('removed securemail');
}
/**
* @brief Build user settings form
*
* @link https://github.com/friendica/friendica/blob/develop/doc/Addons.md#addon_settings 'addon_settings' hook
* @link https://github.com/friendica/friendica/blob/develop/doc/Addons.md#addon_settings 'addon_settings' hook
*
* @param App $a App instance
* @param App $a App instance
* @param string $s output html
*
* @see App
* @see App
*/
function securemail_settings(App &$a, &$s){
if (!local_user()) {
return;
}
function securemail_settings(App &$a, &$s)
{
if (!local_user()) {
return;
}
$enable = intval(PConfig::get(local_user(), 'securemail', 'enable'));
$publickey = PConfig::get(local_user(), 'securemail', 'pkey');
$enable = intval(PConfig::get(local_user(), 'securemail', 'enable'));
$publickey = PConfig::get(local_user(), 'securemail', 'pkey');
$t = Renderer::getMarkupTemplate('admin.tpl', 'addon/securemail/');
$t = Renderer::getMarkupTemplate('admin.tpl', 'addon/securemail/');
$s .= Renderer::replaceMacros($t, [
'$title' => L10n::t('"Secure Mail" Settings'),
'$submit' => L10n::t('Save Settings'),
'$test' => L10n::t('Save and send test'), //NOTE: update also in 'post'
'$enable' => ['securemail-enable', L10n::t('Enable Secure Mail'), $enable, ''],
'$publickey' => ['securemail-pkey', L10n::t('Public key'), $publickey, L10n::t('Your public PGP key, ascii armored format'), 'rows="10"']
]);
$s .= Renderer::replaceMacros($t, [
'$title' => L10n::t('"Secure Mail" Settings'),
'$submit' => L10n::t('Save Settings'),
'$test' => L10n::t('Save and send test'), //NOTE: update also in 'post'
'$enable' => ['securemail-enable', L10n::t('Enable Secure Mail'), $enable, ''],
'$publickey' => ['securemail-pkey', L10n::t('Public key'), $publickey, L10n::t('Your public PGP key, ascii armored format'), 'rows="10"']
]);
}
/**
* @brief Handle data from user settings form
*
* @link https://github.com/friendica/friendica/blob/develop/doc/Addons.md#addon_settings_post 'addon_settings_post' hook
* @link https://github.com/friendica/friendica/blob/develop/doc/Addons.md#addon_settings_post 'addon_settings_post' hook
*
* @param App $a App instance
* @param App $a App instance
* @param array $b hook data
*
* @see App
* @see App
*/
function securemail_settings_post(App &$a, array &$b){
function securemail_settings_post(App &$a, array &$b)
{
if (!local_user()) {
return;
}
if (!local_user()) {
return;
}
if ($_POST['securemail-submit']) {
PConfig::set(local_user(), 'securemail', 'pkey', trim($_POST['securemail-pkey']));
$enable = (!empty($_POST['securemail-enable']) ? 1 : 0);
PConfig::set(local_user(), 'securemail', 'enable', $enable);
info(L10n::t('Secure Mail Settings saved.') . EOL);
if ($_POST['securemail-submit']) {
PConfig::set(local_user(), 'securemail', 'pkey', trim($_POST['securemail-pkey']));
$enable = (!empty($_POST['securemail-enable']) ? 1 : 0);
PConfig::set(local_user(), 'securemail', 'enable', $enable);
info(L10n::t('Secure Mail Settings saved.') . EOL);
if ($_POST['securemail-submit'] == L10n::t('Save and send test')) {
$sitename = Config::get('config', 'sitename');
if ($_POST['securemail-submit'] == L10n::t('Save and send test')) {
$sitename = Config::get('config', 'sitename');
$hostname = $a->getHostName();
if (strpos($hostname, ':')) {
$hostname = substr($hostname, 0, strpos($hostname, ':'));
}
$hostname = $a->getHostName();
if (strpos($hostname, ':')) {
$hostname = substr($hostname, 0, strpos($hostname, ':'));
}
$sender_email = Config::get('config', 'sender_email');
if (empty($sender_email)) {
$sender_email = 'noreply@' . $hostname;
}
$sender_email = Config::get('config', 'sender_email');
if (empty($sender_email)) {
$sender_email = 'noreply@' . $hostname;
}
$subject = 'Friendica - Secure Mail - Test';
$message = 'This is a test message from your Friendica Secure Mail addon.';
$subject = 'Friendica - Secure Mail - Test';
$message = 'This is a test message from your Friendica Secure Mail addon.';
$params = [
'uid' => local_user(),
'fromName' => $sitename,
'fromEmail' => $sender_email,
'toEmail' => $a->user['email'],
'messageSubject' => $subject,
'htmlVersion' => "<p>{$message}</p>",
'textVersion' => $message,
];
$params = [
'uid' => local_user(),
'fromName' => $sitename,
'fromEmail' => $sender_email,
'toEmail' => $a->user['email'],
'messageSubject' => $subject,
'htmlVersion' => "<p>{$message}</p>",
'textVersion' => $message,
];
// enable addon for test
PConfig::set(local_user(), 'securemail', 'enable', 1);
// enable addon for test
PConfig::set(local_user(), 'securemail', 'enable', 1);
$res = Emailer::send($params);
$res = Emailer::send($params);
// revert to saved value
PConfig::set(local_user(), 'securemail', 'enable', $enable);
// revert to saved value
PConfig::set(local_user(), 'securemail', 'enable', $enable);
if ($res) {
info(L10n::t('Test email sent') . EOL);
} else {
notice(L10n::t('There was an error sending the test email') . EOL);
}
}
}
if ($res) {
info(L10n::t('Test email sent') . EOL);
} else {
notice(L10n::t('There was an error sending the test email') . EOL);
}
}
}
}
/**
* @brief Encrypt notification emails text
*
* @link https://github.com/friendica/friendica/blob/develop/doc/Addons.md#emailer_send_prepare 'emailer_send_prepare' hook
* @link https://github.com/friendica/friendica/blob/develop/doc/Addons.md#emailer_send_prepare 'emailer_send_prepare' hook
*
* @param App $a App instance
* @param App $a App instance
* @param array $b hook data
*
* @see App
* @see App
*/
function securemail_emailer_send_prepare(App &$a, array &$b) {
if (empty($b['uid'])) {
return;
}
function securemail_emailer_send_prepare(App &$a, array &$b)
{
if (empty($b['uid'])) {
return;
}
$uid = $b['uid'];
$uid = $b['uid'];
$enable_checked = PConfig::get($uid, 'securemail', 'enable');
if (!$enable_checked) {
return;
}
$enable_checked = PConfig::get($uid, 'securemail', 'enable');
if (!$enable_checked) {
return;
}
$public_key_ascii = PConfig::get($uid, 'securemail', 'pkey');
$public_key_ascii = PConfig::get($uid, 'securemail', 'pkey');
preg_match('/-----BEGIN ([A-Za-z ]+)-----/', $public_key_ascii, $matches);
$marker = empty($matches[1]) ? 'MESSAGE' : $matches[1];
$public_key = OpenPGP::unarmor($public_key_ascii, $marker);
preg_match('/-----BEGIN ([A-Za-z ]+)-----/', $public_key_ascii, $matches);
$marker = empty($matches[1]) ? 'MESSAGE' : $matches[1];
$public_key = OpenPGP::unarmor($public_key_ascii, $marker);
$key = OpenPGP_Message::parse($public_key);
$key = OpenPGP_Message::parse($public_key);
$data = new OpenPGP_LiteralDataPacket($b['textVersion'], [
'format' => 'u',
'filename' => 'encrypted.gpg'
]);
$encrypted = OpenPGP_Crypt_Symmetric::encrypt($key, new OpenPGP_Message([$data]));
$armored_encrypted = wordwrap(
OpenPGP::enarmor($encrypted->to_bytes(), 'PGP MESSAGE'),
64,
"\n",
true
);
$data = new OpenPGP_LiteralDataPacket($b['textVersion'], [
'format' => 'u',
'filename' => 'encrypted.gpg'
]);
$encrypted = OpenPGP_Crypt_Symmetric::encrypt($key, new OpenPGP_Message([$data]));
$armored_encrypted = wordwrap(
OpenPGP::enarmor($encrypted->to_bytes(), 'PGP MESSAGE'),
64,
"\n",
true
);
$b['textVersion'] = $armored_encrypted;
$b['htmlVersion'] = null;
$b['textVersion'] = $armored_encrypted;
$b['htmlVersion'] = null;
}
/**
* add addon composer autoloader maps to system autoloader
function securemail_autoloader() {
$loader = require dirname(dirname(__DIR__)) . '/vendor/autoload.php';
$map = require __DIR__ . '/vendor/composer/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/vendor/composer/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/vendor/composer/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
securemail_autoloader();
*/

7
securemail/vendor/autoload.php vendored Normal file
View file

@ -0,0 +1,7 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitSecuremailAddon::getLoader();

View file

@ -0,0 +1,445 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see http://www.php-fig.org/psr/psr-0/
* @see http://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
private $fallbackDirsPsr4 = array();
// PSR-0
private $prefixesPsr0 = array();
private $fallbackDirsPsr0 = array();
private $useIncludePath = false;
private $classMap = array();
private $classMapAuthoritative = false;
private $missingClasses = array();
private $apcuPrefix;
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', $this->prefixesPsr0);
}
return array();
}
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array $classMap Class to filename map
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 base directories
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
/**
* Unregisters this instance as an autoloader.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return bool|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*/
function includeFile($file)
{
include $file;
}

21
securemail/vendor/composer/LICENSE vendored Normal file
View file

@ -0,0 +1,21 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -0,0 +1,58 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'MCryptWrapper' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp_mcrypt_wrapper.php',
'OpenPGP' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_AsymmetricSessionKeyPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_CompressedDataPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_Crypt_RSA' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp_crypt_rsa.php',
'OpenPGP_Crypt_Symmetric' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp_crypt_symmetric.php',
'OpenPGP_EncryptedDataPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_ExperimentalPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_IntegrityProtectedDataPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_LiteralDataPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_MarkerPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_Message' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_ModificationDetectionCodePacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_OnePassSignaturePacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_Packet' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_PublicKeyPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_PublicSubkeyPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_S2K' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SecretKeyPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SecretSubkeyPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_EmbeddedSignaturePacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_ExportableCertificationPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_FeaturesPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_IssuerPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_KeyExpirationTimePacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_KeyFlagsPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_KeyServerPreferencesPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_NotationDataPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_PolicyURIPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_PreferredCompressionAlgorithmsPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_PreferredHashAlgorithmsPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_PreferredKeyServerPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_PreferredSymmetricAlgorithmsPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_PrimaryUserIDPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_ReasonforRevocationPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_RegularExpressionPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_RevocablePacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_RevocationKeyPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_SignatureCreationTimePacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_SignatureExpirationTimePacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_SignatureTargetPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_SignersUserIDPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_Subpacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_TrustSignaturePacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SymmetricSessionKeyPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_TrustPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_UserAttributePacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_UserIDPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php',
);

View file

@ -0,0 +1,10 @@
<?php
// autoload_files.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
);

View file

@ -0,0 +1,9 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

View file

@ -0,0 +1,10 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'phpseclib\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
);

View file

@ -0,0 +1,70 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInitSecuremailAddon
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInitSecuremailAddon', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInitSecuremailAddon', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitSecuremailAddon::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInitSecuremailAddon::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequireSecuremailAddon($fileIdentifier, $file);
}
return $loader;
}
}
function composerRequireSecuremailAddon($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
}
}

View file

@ -0,0 +1,88 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInitSecuremailAddon
{
public static $files = array (
'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
);
public static $prefixLengthsPsr4 = array (
'p' =>
array (
'phpseclib\\' => 10,
),
);
public static $prefixDirsPsr4 = array (
'phpseclib\\' =>
array (
0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib',
),
);
public static $classMap = array (
'MCryptWrapper' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp_mcrypt_wrapper.php',
'OpenPGP' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_AsymmetricSessionKeyPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_CompressedDataPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_Crypt_RSA' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp_crypt_rsa.php',
'OpenPGP_Crypt_Symmetric' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp_crypt_symmetric.php',
'OpenPGP_EncryptedDataPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_ExperimentalPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_IntegrityProtectedDataPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_LiteralDataPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_MarkerPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_Message' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_ModificationDetectionCodePacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_OnePassSignaturePacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_Packet' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_PublicKeyPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_PublicSubkeyPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_S2K' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SecretKeyPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SecretSubkeyPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_EmbeddedSignaturePacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_ExportableCertificationPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_FeaturesPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_IssuerPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_KeyExpirationTimePacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_KeyFlagsPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_KeyServerPreferencesPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_NotationDataPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_PolicyURIPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_PreferredCompressionAlgorithmsPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_PreferredHashAlgorithmsPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_PreferredKeyServerPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_PreferredSymmetricAlgorithmsPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_PrimaryUserIDPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_ReasonforRevocationPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_RegularExpressionPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_RevocablePacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_RevocationKeyPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_SignatureCreationTimePacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_SignatureExpirationTimePacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_SignatureTargetPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_SignersUserIDPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_Subpacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SignaturePacket_TrustSignaturePacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_SymmetricSessionKeyPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_TrustPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_UserAttributePacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
'OpenPGP_UserIDPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInitSecuremailAddon::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitSecuremailAddon::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInitSecuremailAddon::$classMap;
}, null, ClassLoader::class);
}
}

View file

@ -0,0 +1,141 @@
[
{
"name": "phpseclib/phpseclib",
"version": "2.0.4",
"version_normalized": "2.0.4.0",
"source": {
"type": "git",
"url": "https://github.com/phpseclib/phpseclib.git",
"reference": "ab8028c93c03cc8d9c824efa75dc94f1db2369bf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/ab8028c93c03cc8d9c824efa75dc94f1db2369bf",
"reference": "ab8028c93c03cc8d9c824efa75dc94f1db2369bf",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phing/phing": "~2.7",
"phpunit/phpunit": "~4.0",
"sami/sami": "~2.0",
"squizlabs/php_codesniffer": "~2.0"
},
"suggest": {
"ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
"ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
},
"time": "2016-10-04T00:57:04+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"files": [
"phpseclib/bootstrap.php"
],
"psr-4": {
"phpseclib\\": "phpseclib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jim Wigginton",
"email": "terrafrost@php.net",
"role": "Lead Developer"
},
{
"name": "Patrick Monnerat",
"email": "pm@datasphere.ch",
"role": "Developer"
},
{
"name": "Andreas Fischer",
"email": "bantu@phpbb.com",
"role": "Developer"
},
{
"name": "Hans-Jürgen Petrich",
"email": "petrich@tronic-media.com",
"role": "Developer"
},
{
"name": "Graham Campbell",
"email": "graham@alt-three.com",
"role": "Developer"
}
],
"description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
"homepage": "http://phpseclib.sourceforge.net",
"keywords": [
"BigInteger",
"aes",
"asn.1",
"asn1",
"blowfish",
"crypto",
"cryptography",
"encryption",
"rsa",
"security",
"sftp",
"signature",
"signing",
"ssh",
"twofish",
"x.509",
"x509"
]
},
{
"name": "singpolyma/openpgp-php",
"version": "0.3.0",
"version_normalized": "0.3.0.0",
"source": {
"type": "git",
"url": "https://github.com/singpolyma/openpgp-php.git",
"reference": "6006111bbc4c3b6cb8f0acb7d6c4a7047df366e8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/singpolyma/openpgp-php/zipball/6006111bbc4c3b6cb8f0acb7d6c4a7047df366e8",
"reference": "6006111bbc4c3b6cb8f0acb7d6c4a7047df366e8",
"shasum": ""
},
"require": {
"phpseclib/phpseclib": ">=2.0.0 <=2.0.4"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"time": "2017-04-12T21:23:15+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"classmap": [
"lib/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Unlicense"
],
"authors": [
{
"name": "Arto Bendiken",
"email": "arto.bendiken@gmail.com"
},
{
"name": "Stephen Paul Weber",
"email": "singpolyma@singpolyma.net"
}
],
"description": "Pure-PHP implementation of the OpenPGP Message Format (RFC 4880)"
}
]

View file

@ -3,3 +3,4 @@ phpseclib Lead Developer: TerraFrost (Jim Wigginton)
phpseclib Developers: monnerat (Patrick Monnerat)
bantu (Andreas Fischer)
petrich (Hans-Jürgen Petrich)
GrahamCampbell (Graham Campbell)

View file

@ -1,83 +0,0 @@
# Changelog
## 0.3.9 - 2014-11-09
- PHP 5.6 improvements ([#482](https://github.com/phpseclib/phpseclib/pull/482), [#491](https://github.com/phpseclib/phpseclib/issues/491))
## 0.3.8 - 2014-09-12
- improve support for indef lengths in File_ASN1
- add hmac-sha2-256 support to Net_SSH2
- make it so negotiated algorithms can be seen before Net_SSH2 login
- add sha256-96 and sha512-96 to Crypt_Hash
- window size handling adjustments in Net_SSH2
## 0.3.7 - 2014-07-05
- auto-detect public vs private keys
- add file_exists, is_dir, is_file, readlink and symlink to Net_SFTP
- add support for recursive nlist and rawlist
- make it so nlist and rawlist can return pre-sorted output
- make it so callback functions can make exec() return early
- add signSPKAC and saveSPKAC methods to File_X509
- add support for PKCS8 keys in Crypt_RSA
- add pbkdf1 support to setPassword() in Crypt_Base
- add getWindowColumns, getWindowRows, setWindowColumns, setWindowRows to Net_SSH2
- add support for filenames with spaces in them to Net_SCP
## 0.3.6 - 2014-02-23
- add preliminary support for custom SSH subsystems
- add ssh-agent support
## 0.3.5 - 2013-07-11
- numerous SFTP changes:
- chown
- chgrp
- truncate
- improved file type detection
- put() can write to te middle of a file
- mkdir accepts the same paramters that PHP's mkdir does
- the ability to upload/download 2GB files
- across-the-board speedups for the various encryption algorithms
- multi-factor authentication support for Net_SSH2
- a $callback parameter for Net_SSH2::exec
- new classes:
- Net_SFTP_StreamWrapper
- Net_SCP
- Crypt_Twofish
- Crypt_Blowfish
## 0.3.1 - 2012-11-20
- add Net_SSH2::enableQuietMode() for suppressing stderr
- add Crypt_RSA::__toString() and Crypt_RSA::getSize()
- fix problems with File_X509::validateDate(), File_X509::sign() and Crypt_RSA::verify()
- use OpenSSL to speed up modular exponention in Math_BigInteger
- improved timeout functionality in Net_SSH2
- add support for SFTPv2
- add support for CRLs in File_X509
- SSH-2.0-SSH doesn't implement hmac-*-96 correctly
## 0.3.0 - 2012-07-08
- add support for reuming Net_SFTP::put()
- add support for recursive deletes and recursive chmods to Net_SFTP
- add setTimeout() to Net_SSH2
- add support for PBKDF2 to the various Crypt_* classes via setPassword()
- add File_X509 and File_ASN1
- add the ability to decode various formats in Crypt_RSA
- make Net_SSH2::getServerPublicHostKey() return a printer-friendly version of the public key
## 0.2.2 - 2011-05-09
- CFB and OFB modes were added to all block ciphers
- support for interactive mode was added to Net_SSH2
- Net_SSH2 now has limited keyboard_interactive authentication support
- support was added for PuTTY formatted RSA private keys and XML formatted RSA private keys
- Crypt_RSA::loadKey() will now try all key types automatically
= add support for AES-128-CBC and DES-EDE3-CFB encrypted RSA private keys
- add Net_SFTP::stat(), Net_SFTP::lstat() and Net_SFTP::rawlist()
- logging was added to Net_SSH1
- the license was changed to the less restrictive MIT license

View file

@ -1,4 +1,4 @@
Copyright 2007-2013 TerraFrost and other contributors
Copyright 2007-2016 TerraFrost and other contributors
http://phpseclib.sourceforge.net/
Permission is hereby granted, free of charge, to any person obtaining

View file

@ -1,14 +1,14 @@
# phpseclib - PHP Secure Communications Library
[![Build Status](https://secure.travis-ci.org/phpseclib/phpseclib.png?branch=master)](http://travis-ci.org/phpseclib/phpseclib)
[![Build Status](https://travis-ci.org/phpseclib/phpseclib.svg?branch=2.0)](https://travis-ci.org/phpseclib/phpseclib)
MIT-licensed pure-PHP implementations of an arbitrary-precision integer
arithmetic library, fully PKCS#1 (v2.1) compliant RSA, DES, 3DES, RC4, Rijndael,
AES, Blowfish, Twofish, SSH-1, SSH-2, SFTP, and X.509
* [Download (0.3.9)](http://sourceforge.net/projects/phpseclib/files/phpseclib0.3.9.zip/download)
* [Download (1.0.4)](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.4.zip/download)
* [Browse Git](https://github.com/phpseclib/phpseclib)
* [Code Coverage Report](http://phpseclib.bantux.org/code_coverage/master/latest/)
* [Code Coverage Report](http://phpseclib.bantux.org/code_coverage/2.0/latest/)
<img src="http://phpseclib.sourceforge.net/pear-icon.png" alt="PEAR Channel" width="16" height="16">
PEAR Channel: [phpseclib.sourceforge.net](http://phpseclib.sourceforge.net/pear.htm)
@ -16,7 +16,7 @@ PEAR Channel: [phpseclib.sourceforge.net](http://phpseclib.sourceforge.net/pear.
## Documentation
* [Documentation / Manual](http://phpseclib.sourceforge.net/)
* [API Documentation](http://phpseclib.bantux.org/api/master/) (generated by Sami)
* [API Documentation](http://phpseclib.bantux.org/api/2.0/) (generated by Sami)
## Support
@ -40,7 +40,7 @@ Dependencies are managed via Composer.
2. Install Dependencies
``` sh
php composer.phar install --dev
php composer.phar install
```
## Contributing

View file

@ -0,0 +1,76 @@
{
"name": "phpseclib/phpseclib",
"type": "library",
"description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
"keywords": [
"security",
"crypto",
"cryptography",
"encryption",
"signature",
"signing",
"rsa",
"aes",
"blowfish",
"twofish",
"ssh",
"sftp",
"x509",
"x.509",
"asn1",
"asn.1",
"BigInteger"
],
"homepage": "http://phpseclib.sourceforge.net",
"license": "MIT",
"authors": [
{
"name": "Jim Wigginton",
"email": "terrafrost@php.net",
"role": "Lead Developer"
},
{
"name": "Patrick Monnerat",
"email": "pm@datasphere.ch",
"role": "Developer"
},
{
"name": "Andreas Fischer",
"email": "bantu@phpbb.com",
"role": "Developer"
},
{
"name": "Hans-Jürgen Petrich",
"email": "petrich@tronic-media.com",
"role": "Developer"
},
{
"name": "Graham Campbell",
"email": "graham@alt-three.com",
"role": "Developer"
}
],
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phing/phing": "~2.7",
"phpunit/phpunit": "~4.0",
"sami/sami": "~2.0",
"squizlabs/php_codesniffer": "~2.0"
},
"suggest": {
"ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations.",
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
"ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations."
},
"autoload": {
"files": [
"phpseclib/bootstrap.php"
],
"psr-4": {
"phpseclib\\": "phpseclib/"
}
}
}

1819
securemail/vendor/phpseclib/phpseclib/composer.lock generated vendored Normal file
View file

@ -0,0 +1,1819 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "8599992bf6058a9da82372eb8bcae2c2",
"content-hash": "fde47c84178c55c06de858a2128e3d07",
"packages": [],
"packages-dev": [
{
"name": "doctrine/instantiator",
"version": "1.0.5",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
"shasum": ""
},
"require": {
"php": ">=5.3,<8.0-DEV"
},
"require-dev": {
"athletic/athletic": "~0.1.8",
"ext-pdo": "*",
"ext-phar": "*",
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "http://ocramius.github.com/"
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"homepage": "https://github.com/doctrine/instantiator",
"keywords": [
"constructor",
"instantiate"
],
"time": "2015-06-14 21:17:01"
},
{
"name": "michelf/php-markdown",
"version": "1.6.0",
"source": {
"type": "git",
"url": "https://github.com/michelf/php-markdown.git",
"reference": "156e56ee036505ec637d761ee62dc425d807183c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/michelf/php-markdown/zipball/156e56ee036505ec637d761ee62dc425d807183c",
"reference": "156e56ee036505ec637d761ee62dc425d807183c",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-lib": "1.4.x-dev"
}
},
"autoload": {
"psr-0": {
"Michelf": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Michel Fortin",
"email": "michel.fortin@michelf.ca",
"homepage": "https://michelf.ca/",
"role": "Developer"
},
{
"name": "John Gruber",
"homepage": "https://daringfireball.net/"
}
],
"description": "PHP Markdown",
"homepage": "https://michelf.ca/projects/php-markdown/",
"keywords": [
"markdown"
],
"time": "2015-12-24 01:37:31"
},
{
"name": "nikic/php-parser",
"version": "v0.9.5",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "ef70767475434bdb3615b43c327e2cae17ef12eb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ef70767475434bdb3615b43c327e2cae17ef12eb",
"reference": "ef70767475434bdb3615b43c327e2cae17ef12eb",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=5.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "0.9-dev"
}
},
"autoload": {
"psr-0": {
"PHPParser": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Nikita Popov"
}
],
"description": "A PHP parser written in PHP",
"keywords": [
"parser",
"php"
],
"time": "2014-07-23 18:24:17"
},
{
"name": "phing/phing",
"version": "2.14.0",
"source": {
"type": "git",
"url": "https://github.com/phingofficial/phing.git",
"reference": "7dd73c83c377623def54b58121f46b4dcb35dd61"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phingofficial/phing/zipball/7dd73c83c377623def54b58121f46b4dcb35dd61",
"reference": "7dd73c83c377623def54b58121f46b4dcb35dd61",
"shasum": ""
},
"require": {
"php": ">=5.2.0"
},
"require-dev": {
"ext-pdo_sqlite": "*",
"lastcraft/simpletest": "@dev",
"mikey179/vfsstream": "^1.6",
"pdepend/pdepend": "2.x",
"pear/archive_tar": "1.4.x",
"pear/http_request2": "dev-trunk",
"pear/net_growl": "dev-trunk",
"pear/pear-core-minimal": "1.10.1",
"pear/versioncontrol_git": "@dev",
"pear/versioncontrol_svn": "~0.5",
"phpdocumentor/phpdocumentor": "2.x",
"phploc/phploc": "~2.0.6",
"phpmd/phpmd": "~2.2",
"phpunit/phpunit": ">=3.7",
"sebastian/git": "~1.0",
"sebastian/phpcpd": "2.x",
"squizlabs/php_codesniffer": "~2.2",
"symfony/yaml": "~2.7"
},
"suggest": {
"pdepend/pdepend": "PHP version of JDepend",
"pear/archive_tar": "Tar file management class",
"pear/versioncontrol_git": "A library that provides OO interface to handle Git repository",
"pear/versioncontrol_svn": "A simple OO-style interface for Subversion, the free/open-source version control system",
"phpdocumentor/phpdocumentor": "Documentation Generator for PHP",
"phploc/phploc": "A tool for quickly measuring the size of a PHP project",
"phpmd/phpmd": "PHP version of PMD tool",
"phpunit/php-code-coverage": "Library that provides collection, processing, and rendering functionality for PHP code coverage information",
"phpunit/phpunit": "The PHP Unit Testing Framework",
"sebastian/phpcpd": "Copy/Paste Detector (CPD) for PHP code",
"tedivm/jshrink": "Javascript Minifier built in PHP"
},
"bin": [
"bin/phing"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.14.x-dev"
}
},
"autoload": {
"classmap": [
"classes/phing/"
]
},
"notification-url": "https://packagist.org/downloads/",
"include-path": [
"classes"
],
"license": [
"LGPL-3.0"
],
"authors": [
{
"name": "Michiel Rook",
"email": "mrook@php.net"
},
{
"name": "Phing Community",
"homepage": "https://www.phing.info/trac/wiki/Development/Contributors"
}
],
"description": "PHing Is Not GNU make; it's a PHP project build system or build tool based on Apache Ant.",
"homepage": "https://www.phing.info/",
"keywords": [
"build",
"phing",
"task",
"tool"
],
"time": "2016-03-10 21:39:23"
},
{
"name": "phpdocumentor/reflection-common",
"version": "1.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
"reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
"shasum": ""
},
"require": {
"php": ">=5.5"
},
"require-dev": {
"phpunit/phpunit": "^4.6"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": [
"src"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jaap van Otterdijk",
"email": "opensource@ijaap.nl"
}
],
"description": "Common reflection classes used by phpdocumentor to reflect the code structure",
"homepage": "http://www.phpdoc.org",
"keywords": [
"FQSEN",
"phpDocumentor",
"phpdoc",
"reflection",
"static analysis"
],
"time": "2015-12-27 11:43:31"
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "3.1.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "9270140b940ff02e58ec577c237274e92cd40cdd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9270140b940ff02e58ec577c237274e92cd40cdd",
"reference": "9270140b940ff02e58ec577c237274e92cd40cdd",
"shasum": ""
},
"require": {
"php": ">=5.5",
"phpdocumentor/reflection-common": "^1.0@dev",
"phpdocumentor/type-resolver": "^0.2.0",
"webmozart/assert": "^1.0"
},
"require-dev": {
"mockery/mockery": "^0.9.4",
"phpunit/phpunit": "^4.4"
},
"type": "library",
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"time": "2016-06-10 09:48:41"
},
{
"name": "phpdocumentor/type-resolver",
"version": "0.2",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443",
"reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443",
"shasum": ""
},
"require": {
"php": ">=5.5",
"phpdocumentor/reflection-common": "^1.0"
},
"require-dev": {
"mockery/mockery": "^0.9.4",
"phpunit/phpunit": "^5.2||^4.8.24"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
}
],
"time": "2016-06-10 07:14:17"
},
{
"name": "phpspec/prophecy",
"version": "v1.6.1",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "58a8137754bc24b25740d4281399a4a3596058e0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0",
"reference": "58a8137754bc24b25740d4281399a4a3596058e0",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": "^5.3|^7.0",
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
"sebastian/comparator": "^1.1",
"sebastian/recursion-context": "^1.0"
},
"require-dev": {
"phpspec/phpspec": "^2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.6.x-dev"
}
},
"autoload": {
"psr-0": {
"Prophecy\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Konstantin Kudryashov",
"email": "ever.zet@gmail.com",
"homepage": "http://everzet.com"
},
{
"name": "Marcello Duarte",
"email": "marcello.duarte@gmail.com"
}
],
"description": "Highly opinionated mocking framework for PHP 5.3+",
"homepage": "https://github.com/phpspec/prophecy",
"keywords": [
"Double",
"Dummy",
"fake",
"mock",
"spy",
"stub"
],
"time": "2016-06-07 08:13:47"
},
{
"name": "phpunit/php-code-coverage",
"version": "2.2.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
"reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"phpunit/php-file-iterator": "~1.3",
"phpunit/php-text-template": "~1.2",
"phpunit/php-token-stream": "~1.3",
"sebastian/environment": "^1.3.2",
"sebastian/version": "~1.0"
},
"require-dev": {
"ext-xdebug": ">=2.1.4",
"phpunit/phpunit": "~4"
},
"suggest": {
"ext-dom": "*",
"ext-xdebug": ">=2.2.1",
"ext-xmlwriter": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.2.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
"keywords": [
"coverage",
"testing",
"xunit"
],
"time": "2015-10-06 15:47:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
"reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"keywords": [
"filesystem",
"iterator"
],
"time": "2015-06-21 13:08:43"
},
{
"name": "phpunit/php-text-template",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Simple template engine.",
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
"keywords": [
"template"
],
"time": "2015-06-21 13:50:34"
},
{
"name": "phpunit/php-timer",
"version": "1.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260",
"reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4|~5"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Utility class for timing",
"homepage": "https://github.com/sebastianbergmann/php-timer/",
"keywords": [
"timer"
],
"time": "2016-05-12 18:03:57"
},
{
"name": "phpunit/php-token-stream",
"version": "1.4.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
"reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
"reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Wrapper around PHP's tokenizer extension.",
"homepage": "https://github.com/sebastianbergmann/php-token-stream/",
"keywords": [
"tokenizer"
],
"time": "2015-09-15 10:49:45"
},
{
"name": "phpunit/phpunit",
"version": "4.8.26",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "fc1d8cd5b5de11625979125c5639347896ac2c74"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fc1d8cd5b5de11625979125c5639347896ac2c74",
"reference": "fc1d8cd5b5de11625979125c5639347896ac2c74",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-json": "*",
"ext-pcre": "*",
"ext-reflection": "*",
"ext-spl": "*",
"php": ">=5.3.3",
"phpspec/prophecy": "^1.3.1",
"phpunit/php-code-coverage": "~2.1",
"phpunit/php-file-iterator": "~1.4",
"phpunit/php-text-template": "~1.2",
"phpunit/php-timer": "^1.0.6",
"phpunit/phpunit-mock-objects": "~2.3",
"sebastian/comparator": "~1.1",
"sebastian/diff": "~1.2",
"sebastian/environment": "~1.3",
"sebastian/exporter": "~1.2",
"sebastian/global-state": "~1.0",
"sebastian/version": "~1.0",
"symfony/yaml": "~2.1|~3.0"
},
"suggest": {
"phpunit/php-invoker": "~1.1"
},
"bin": [
"phpunit"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.8.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "The PHP Unit Testing framework.",
"homepage": "https://phpunit.de/",
"keywords": [
"phpunit",
"testing",
"xunit"
],
"time": "2016-05-17 03:09:28"
},
{
"name": "phpunit/phpunit-mock-objects",
"version": "2.3.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
"reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983",
"reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": ">=5.3.3",
"phpunit/php-text-template": "~1.2",
"sebastian/exporter": "~1.2"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"suggest": {
"ext-soap": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.3.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Mock Object library for PHPUnit",
"homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
"keywords": [
"mock",
"xunit"
],
"time": "2015-10-02 06:51:40"
},
{
"name": "pimple/pimple",
"version": "v2.1.1",
"source": {
"type": "git",
"url": "https://github.com/silexphp/Pimple.git",
"reference": "ea22fb2880faf7b7b0e17c9809c6fe25b071fd76"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/silexphp/Pimple/zipball/ea22fb2880faf7b7b0e17c9809c6fe25b071fd76",
"reference": "ea22fb2880faf7b7b0e17c9809c6fe25b071fd76",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.1.x-dev"
}
},
"autoload": {
"psr-0": {
"Pimple": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "Pimple is a simple Dependency Injection Container for PHP 5.3",
"homepage": "http://pimple.sensiolabs.org",
"keywords": [
"container",
"dependency injection"
],
"time": "2014-07-24 07:10:08"
},
{
"name": "sami/sami",
"version": "v2.0.0",
"source": {
"type": "git",
"url": "https://github.com/FriendsOfPHP/Sami.git",
"reference": "fa58b324f41aa2aefe21dac4f22d8c98965fc012"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/FriendsOfPHP/Sami/zipball/fa58b324f41aa2aefe21dac4f22d8c98965fc012",
"reference": "fa58b324f41aa2aefe21dac4f22d8c98965fc012",
"shasum": ""
},
"require": {
"michelf/php-markdown": "~1.3",
"nikic/php-parser": "0.9.*",
"php": ">=5.3.0",
"pimple/pimple": "2.*",
"symfony/console": "~2.1",
"symfony/filesystem": "~2.1",
"symfony/finder": "~2.1",
"symfony/process": "~2.1",
"symfony/yaml": "~2.1",
"twig/twig": "1.*"
},
"bin": [
"sami.php"
],
"type": "application",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"psr-0": {
"Sami": "."
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "Sami, an API documentation generator",
"homepage": "http://sami.sensiolabs.org",
"keywords": [
"phpdoc"
],
"time": "2014-06-25 12:05:18"
},
{
"name": "sebastian/comparator",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "937efb279bd37a375bcadf584dec0726f84dbf22"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22",
"reference": "937efb279bd37a375bcadf584dec0726f84dbf22",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"sebastian/diff": "~1.2",
"sebastian/exporter": "~1.2"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides the functionality to compare PHP values for equality",
"homepage": "http://www.github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
"equality"
],
"time": "2015-07-26 15:48:44"
},
{
"name": "sebastian/diff",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
"reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.8"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Kore Nordmann",
"email": "mail@kore-nordmann.de"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Diff implementation",
"homepage": "https://github.com/sebastianbergmann/diff",
"keywords": [
"diff"
],
"time": "2015-12-08 07:14:41"
},
{
"name": "sebastian/environment",
"version": "1.3.7",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716",
"reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "http://www.github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
"hhvm"
],
"time": "2016-05-17 03:18:57"
},
{
"name": "sebastian/exporter",
"version": "1.2.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "42c4c2eec485ee3e159ec9884f95b431287edde4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4",
"reference": "42c4c2eec485ee3e159ec9884f95b431287edde4",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"sebastian/recursion-context": "~1.0"
},
"require-dev": {
"ext-mbstring": "*",
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides the functionality to export PHP variables for visualization",
"homepage": "http://www.github.com/sebastianbergmann/exporter",
"keywords": [
"export",
"exporter"
],
"time": "2016-06-17 09:04:28"
},
{
"name": "sebastian/global-state",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
"reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.2"
},
"suggest": {
"ext-uopz": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Snapshotting of global state",
"homepage": "http://www.github.com/sebastianbergmann/global-state",
"keywords": [
"global state"
],
"time": "2015-10-12 03:26:01"
},
{
"name": "sebastian/recursion-context",
"version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "913401df809e99e4f47b27cdd781f4a258d58791"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791",
"reference": "913401df809e99e4f47b27cdd781f4a258d58791",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"time": "2015-11-11 19:50:13"
},
{
"name": "sebastian/version",
"version": "1.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
"reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
"shasum": ""
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"time": "2015-06-21 13:59:46"
},
{
"name": "squizlabs/php_codesniffer",
"version": "2.6.1",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "fb72ed32f8418db5e7770be1653e62e0d6f5dd3d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/fb72ed32f8418db5e7770be1653e62e0d6f5dd3d",
"reference": "fb72ed32f8418db5e7770be1653e62e0d6f5dd3d",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": ">=5.1.2"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"bin": [
"scripts/phpcs",
"scripts/phpcbf"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
}
},
"autoload": {
"classmap": [
"CodeSniffer.php",
"CodeSniffer/CLI.php",
"CodeSniffer/Exception.php",
"CodeSniffer/File.php",
"CodeSniffer/Fixer.php",
"CodeSniffer/Report.php",
"CodeSniffer/Reporting.php",
"CodeSniffer/Sniff.php",
"CodeSniffer/Tokens.php",
"CodeSniffer/Reports/",
"CodeSniffer/Tokenizers/",
"CodeSniffer/DocGenerators/",
"CodeSniffer/Standards/AbstractPatternSniff.php",
"CodeSniffer/Standards/AbstractScopeSniff.php",
"CodeSniffer/Standards/AbstractVariableSniff.php",
"CodeSniffer/Standards/IncorrectPatternException.php",
"CodeSniffer/Standards/Generic/Sniffs/",
"CodeSniffer/Standards/MySource/Sniffs/",
"CodeSniffer/Standards/PEAR/Sniffs/",
"CodeSniffer/Standards/PSR1/Sniffs/",
"CodeSniffer/Standards/PSR2/Sniffs/",
"CodeSniffer/Standards/Squiz/Sniffs/",
"CodeSniffer/Standards/Zend/Sniffs/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "http://www.squizlabs.com/php-codesniffer",
"keywords": [
"phpcs",
"standards"
],
"time": "2016-05-30 22:24:32"
},
{
"name": "symfony/console",
"version": "v2.8.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3",
"reference": "5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3",
"shasum": ""
},
"require": {
"php": ">=5.3.9",
"symfony/polyfill-mbstring": "~1.0"
},
"require-dev": {
"psr/log": "~1.0",
"symfony/event-dispatcher": "~2.1|~3.0.0",
"symfony/process": "~2.1|~3.0.0"
},
"suggest": {
"psr/log": "For using the console logger",
"symfony/event-dispatcher": "",
"symfony/process": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Console\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2016-06-06 15:06:25"
},
{
"name": "symfony/filesystem",
"version": "v2.8.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "dee379131dceed90a429e951546b33edfe7dccbb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/dee379131dceed90a429e951546b33edfe7dccbb",
"reference": "dee379131dceed90a429e951546b33edfe7dccbb",
"shasum": ""
},
"require": {
"php": ">=5.3.9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Filesystem\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
"time": "2016-04-12 18:01:21"
},
{
"name": "symfony/finder",
"version": "v2.8.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "3ec095fab1800222732ca522a95dce8fa124007b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/3ec095fab1800222732ca522a95dce8fa124007b",
"reference": "3ec095fab1800222732ca522a95dce8fa124007b",
"shasum": ""
},
"require": {
"php": ">=5.3.9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Finder\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
"time": "2016-06-06 11:11:27"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.2.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "dff51f72b0706335131b00a7f49606168c582594"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594",
"reference": "dff51f72b0706335131b00a7f49606168c582594",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"time": "2016-05-18 14:26:46"
},
{
"name": "symfony/process",
"version": "v2.8.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "115347d00c342198cdc52a7bd8bc15b5ab43500c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/115347d00c342198cdc52a7bd8bc15b5ab43500c",
"reference": "115347d00c342198cdc52a7bd8bc15b5ab43500c",
"shasum": ""
},
"require": {
"php": ">=5.3.9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Process\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
"time": "2016-06-06 11:11:27"
},
{
"name": "symfony/yaml",
"version": "v2.8.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "815fabf3f48c7d1df345a69d1ad1a88f59757b34"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/815fabf3f48c7d1df345a69d1ad1a88f59757b34",
"reference": "815fabf3f48c7d1df345a69d1ad1a88f59757b34",
"shasum": ""
},
"require": {
"php": ">=5.3.9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Yaml\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2016-06-06 11:11:27"
},
{
"name": "twig/twig",
"version": "v1.24.1",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "3566d311a92aae4deec6e48682dc5a4528c4a512"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/3566d311a92aae4deec6e48682dc5a4528c4a512",
"reference": "3566d311a92aae4deec6e48682dc5a4528c4a512",
"shasum": ""
},
"require": {
"php": ">=5.2.7"
},
"require-dev": {
"symfony/debug": "~2.7",
"symfony/phpunit-bridge": "~2.7"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.24-dev"
}
},
"autoload": {
"psr-0": {
"Twig_": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
},
{
"name": "Armin Ronacher",
"email": "armin.ronacher@active-4.com",
"role": "Project Founder"
},
{
"name": "Twig Team",
"homepage": "http://twig.sensiolabs.org/contributors",
"role": "Contributors"
}
],
"description": "Twig, the flexible, fast, and secure template language for PHP",
"homepage": "http://twig.sensiolabs.org",
"keywords": [
"templating"
],
"time": "2016-05-30 09:11:59"
},
{
"name": "webmozart/assert",
"version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/webmozart/assert.git",
"reference": "30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/assert/zipball/30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde",
"reference": "30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "^4.6"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\Assert\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Assertions to validate method input/output with nice error messages.",
"keywords": [
"assert",
"check",
"validate"
],
"time": "2015-08-24 13:29:44"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=5.3.3"
},
"platform-dev": []
}

View file

@ -5,23 +5,27 @@
*
* Uses mcrypt, if available/possible, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
* PHP version 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 192-bits and 192 bits will be the key length until {@link Crypt_AES::setKey() setKey()}
* NOTE: Since AES.php is (for compatibility and phpseclib-historical reasons) virtually
* just a wrapper to Rijndael.php you may consider using Rijndael.php instead of
* to save one include_once().
*
* If {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
* {@link self::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 192-bits and 192 bits will be the key length until {@link self::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,
* Since \phpseclib\Crypt\AES extends \phpseclib\Crypt\Rijndael, some functions are available to be called that, in the context of AES, don't
* make a whole lot of sense. {@link self::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';
* include 'vendor/autoload.php';
*
* $aes = new Crypt_AES();
* $aes = new \phpseclib\Crypt\AES();
*
* $aes->setKey('abcdefghijklmnop');
*
@ -35,118 +39,33 @@
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_AES
* @package AES
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2008 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Rijndael
*/
if (!class_exists('Crypt_Rijndael')) {
include_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', CRYPT_MODE_CTR);
/**
* 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', CRYPT_MODE_ECB);
/**
* 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', CRYPT_MODE_CBC);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/
define('CRYPT_AES_MODE_CFB', CRYPT_MODE_CFB);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/
define('CRYPT_AES_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/
/**#@+
* @access private
* @see Crypt_Base::Crypt_Base()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_AES_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_AES_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
namespace phpseclib\Crypt;
/**
* Pure-PHP implementation of AES.
*
* @package Crypt_AES
* @package AES
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Crypt_AES extends Crypt_Rijndael
class AES extends Rijndael
{
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_Base::const_namespace
* @var String
* @access private
*/
var $const_namespace = 'AES';
/**
* Dummy function
*
* Since Crypt_AES extends Crypt_Rijndael, this function is, technically, available, but it doesn't do anything.
* Since \phpseclib\Crypt\AES extends \phpseclib\Crypt\Rijndael, this function is, technically, available, but it doesn't do anything.
*
* @see Crypt_Rijndael::setBlockLength()
* @see \phpseclib\Crypt\Rijndael::setBlockLength()
* @access public
* @param Integer $length
* @param int $length
*/
function setBlockLength($length)
{
@ -159,9 +78,9 @@ class Crypt_AES extends Crypt_Rijndael
* Valid key lengths are 128, 192, and 256. If the length is less than 128, it will be rounded up to
* 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
*
* @see Crypt_Rijndael:setKeyLength()
* @see \phpseclib\Crypt\Rijndael:setKeyLength()
* @access public
* @param Integer $length
* @param int $length
*/
function setKeyLength($length)
{
@ -180,10 +99,10 @@ class Crypt_AES extends Crypt_Rijndael
*
* Rijndael supports five different key lengths, AES only supports three.
*
* @see Crypt_Rijndael:setKey()
* @see \phpseclib\Crypt\Rijndael:setKey()
* @see setKeyLength()
* @access public
* @param String $key
* @param string $key
*/
function setKey($key)
{
@ -193,15 +112,15 @@ class Crypt_AES extends Crypt_Rijndael
$length = strlen($key);
switch (true) {
case $length <= 16:
$this->key_size = 16;
$this->key_length = 16;
break;
case $length <= 24:
$this->key_size = 24;
$this->key_length = 24;
break;
default:
$this->key_size = 32;
$this->key_length = 32;
}
$this->_setupEngine();
$this->_setEngine();
}
}
}

View file

@ -1,14 +1,14 @@
<?php
/**
* Base Class for all Crypt_* cipher classes
* Base Class for all \phpseclib\Crypt\* cipher classes
*
* PHP versions 4 and 5
* PHP version 5
*
* Internally for phpseclib developers:
* If you plan to add a new cipher class, please note following rules:
*
* - The new Crypt_* cipher class should extend Crypt_Base
* - The new \phpseclib\Crypt\* cipher class should extend \phpseclib\Crypt\Base
*
* - Following methods are then required to be overridden/overloaded:
*
@ -20,31 +20,13 @@
*
* - All other methods are optional to be overridden/overloaded
*
* - Look at the source code of the current ciphers how they extend Crypt_Base
* - Look at the source code of the current ciphers how they extend \phpseclib\Crypt\Base
* and take one of them as a start up for the new cipher class.
*
* - Please read all the other comments/notes/hints here also for each class var/method
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_Base
* @package Base
* @author Jim Wigginton <terrafrost@php.net>
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
* @copyright 2007 Jim Wigginton
@ -52,79 +34,92 @@
* @link http://phpseclib.sourceforge.net
*/
/**#@+
* @access public
* @see Crypt_Base::encrypt()
* @see Crypt_Base::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_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_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_MODE_CBC', 2);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/
define('CRYPT_MODE_CFB', 3);
/**
* Encrypt / decrypt using the Output Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/
define('CRYPT_MODE_OFB', 4);
/**
* Encrypt / decrypt using streaming mode.
*
*/
define('CRYPT_MODE_STREAM', 5);
/**#@-*/
/**#@+
* @access private
* @see Crypt_Base::Crypt_Base()
*/
/**
* Base value for the internal implementation $engine switch
*/
define('CRYPT_MODE_INTERNAL', 1);
/**
* Base value for the mcrypt implementation $engine switch
*/
define('CRYPT_MODE_MCRYPT', 2);
/**#@-*/
namespace phpseclib\Crypt;
/**
* Base Class for all Crypt_* cipher classes
* Base Class for all \phpseclib\Crypt\* cipher classes
*
* @package Crypt_Base
* @package Base
* @author Jim Wigginton <terrafrost@php.net>
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
* @access public
*/
class Crypt_Base
abstract class Base
{
/**#@+
* @access public
* @see \phpseclib\Crypt\Base::encrypt()
* @see \phpseclib\Crypt\Base::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
*/
const 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
*/
const 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
*/
const MODE_CBC = 2;
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/
const MODE_CFB = 3;
/**
* Encrypt / decrypt using the Output Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/
const MODE_OFB = 4;
/**
* Encrypt / decrypt using streaming mode.
*/
const MODE_STREAM = 5;
/**#@-*/
/**
* Whirlpool available flag
*
* @see \phpseclib\Crypt\Base::_hashInlineCryptFunction()
* @var bool
* @access private
*/
static $WHIRLPOOL_AVAILABLE;
/**#@+
* @access private
* @see \phpseclib\Crypt\Base::__construct()
*/
/**
* Base value for the internal implementation $engine switch
*/
const ENGINE_INTERNAL = 1;
/**
* Base value for the mcrypt implementation $engine switch
*/
const ENGINE_MCRYPT = 2;
/**
* Base value for the mcrypt implementation $engine switch
*/
const ENGINE_OPENSSL = 3;
/**#@-*/
/**
* The Encryption Mode
*
* @see Crypt_Base::Crypt_Base()
* @var Integer
* @see self::__construct()
* @var int
* @access private
*/
var $mode;
@ -132,7 +127,7 @@ class Crypt_Base
/**
* The Block Length of the block cipher
*
* @var Integer
* @var int
* @access private
*/
var $block_size = 16;
@ -140,8 +135,8 @@ class Crypt_Base
/**
* The Key
*
* @see Crypt_Base::setKey()
* @var String
* @see self::setKey()
* @var string
* @access private
*/
var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
@ -149,8 +144,8 @@ class Crypt_Base
/**
* The Initialization Vector
*
* @see Crypt_Base::setIV()
* @var String
* @see self::setIV()
* @var string
* @access private
*/
var $iv;
@ -158,9 +153,9 @@ class Crypt_Base
/**
* A "sliding" Initialization Vector
*
* @see Crypt_Base::enableContinuousBuffer()
* @see Crypt_Base::_clearBuffers()
* @var String
* @see self::enableContinuousBuffer()
* @see self::_clearBuffers()
* @var string
* @access private
*/
var $encryptIV;
@ -168,9 +163,9 @@ class Crypt_Base
/**
* A "sliding" Initialization Vector
*
* @see Crypt_Base::enableContinuousBuffer()
* @see Crypt_Base::_clearBuffers()
* @var String
* @see self::enableContinuousBuffer()
* @see self::_clearBuffers()
* @var string
* @access private
*/
var $decryptIV;
@ -178,8 +173,8 @@ class Crypt_Base
/**
* Continuous Buffer status
*
* @see Crypt_Base::enableContinuousBuffer()
* @var Boolean
* @see self::enableContinuousBuffer()
* @var bool
* @access private
*/
var $continuousBuffer = false;
@ -187,9 +182,9 @@ class Crypt_Base
/**
* Encryption buffer for CTR, OFB and CFB modes
*
* @see Crypt_Base::encrypt()
* @see Crypt_Base::_clearBuffers()
* @var Array
* @see self::encrypt()
* @see self::_clearBuffers()
* @var array
* @access private
*/
var $enbuffer;
@ -197,9 +192,9 @@ class Crypt_Base
/**
* Decryption buffer for CTR, OFB and CFB modes
*
* @see Crypt_Base::decrypt()
* @see Crypt_Base::_clearBuffers()
* @var Array
* @see self::decrypt()
* @see self::_clearBuffers()
* @var array
* @access private
*/
var $debuffer;
@ -210,8 +205,8 @@ class Crypt_Base
* 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_Base::encrypt()
* @var Resource
* @see self::encrypt()
* @var resource
* @access private
*/
var $enmcrypt;
@ -222,8 +217,8 @@ class Crypt_Base
* 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_Base::decrypt()
* @var Resource
* @see self::decrypt()
* @var resource
* @access private
*/
var $demcrypt;
@ -231,9 +226,9 @@ class Crypt_Base
/**
* Does the enmcrypt resource need to be (re)initialized?
*
* @see Crypt_Twofish::setKey()
* @see Crypt_Twofish::setIV()
* @var Boolean
* @see \phpseclib\Crypt\Twofish::setKey()
* @see \phpseclib\Crypt\Twofish::setIV()
* @var bool
* @access private
*/
var $enchanged = true;
@ -241,9 +236,9 @@ class Crypt_Base
/**
* Does the demcrypt resource need to be (re)initialized?
*
* @see Crypt_Twofish::setKey()
* @see Crypt_Twofish::setIV()
* @var Boolean
* @see \phpseclib\Crypt\Twofish::setKey()
* @see \phpseclib\Crypt\Twofish::setIV()
* @var bool
* @access private
*/
var $dechanged = true;
@ -259,10 +254,10 @@ class Crypt_Base
* use a separate ECB-mode mcrypt resource.
*
* @link http://phpseclib.sourceforge.net/cfb-demo.phps
* @see Crypt_Base::encrypt()
* @see Crypt_Base::decrypt()
* @see Crypt_Base::_setupMcrypt()
* @var Resource
* @see self::encrypt()
* @see self::decrypt()
* @see self::_setupMcrypt()
* @var resource
* @access private
*/
var $ecb;
@ -271,7 +266,7 @@ class Crypt_Base
* Optimizing value while CFB-encrypting
*
* Only relevant if $continuousBuffer enabled
* and $engine == CRYPT_MODE_MCRYPT
* and $engine == self::ENGINE_MCRYPT
*
* It's faster to re-init $enmcrypt if
* $buffer bytes > $cfb_init_len than
@ -283,8 +278,8 @@ class Crypt_Base
* which, typically, depends on the complexity
* on its internaly Key-expanding algorithm.
*
* @see Crypt_Base::encrypt()
* @var Integer
* @see self::encrypt()
* @var int
* @access private
*/
var $cfb_init_len = 600;
@ -292,10 +287,10 @@ class Crypt_Base
/**
* Does internal cipher state need to be (re)initialized?
*
* @see setKey()
* @see setIV()
* @see disableContinuousBuffer()
* @var Boolean
* @see self::setKey()
* @see self::setIV()
* @see self::disableContinuousBuffer()
* @var bool
* @access private
*/
var $changed = true;
@ -303,8 +298,8 @@ class Crypt_Base
/**
* Padding status
*
* @see Crypt_Base::enablePadding()
* @var Boolean
* @see self::enablePadding()
* @var bool
* @access private
*/
var $padding = true;
@ -312,8 +307,8 @@ class Crypt_Base
/**
* Is the mode one that is paddable?
*
* @see Crypt_Base::Crypt_Base()
* @var Boolean
* @see self::__construct()
* @var bool
* @access private
*/
var $paddable = false;
@ -323,86 +318,83 @@ class Crypt_Base
* which will be determined automatically on __construct()
*
* Currently available $engines are:
* - CRYPT_MODE_MCRYPT (fast, php-extension: mcrypt, extension_loaded('mcrypt') required)
* - CRYPT_MODE_INTERNAL (slower, pure php-engine, no php-extension required)
* - self::ENGINE_OPENSSL (very fast, php-extension: openssl, extension_loaded('openssl') required)
* - self::ENGINE_MCRYPT (fast, php-extension: mcrypt, extension_loaded('mcrypt') required)
* - self::ENGINE_INTERNAL (slower, pure php-engine, no php-extension required)
*
* In the pipeline... maybe. But currently not available:
* - CRYPT_MODE_OPENSSL (very fast, php-extension: openssl, extension_loaded('openssl') required)
*
* If possible, CRYPT_MODE_MCRYPT will be used for each cipher.
* Otherwise CRYPT_MODE_INTERNAL
*
* @see Crypt_Base::encrypt()
* @see Crypt_Base::decrypt()
* @var Integer
* @see self::_setEngine()
* @see self::encrypt()
* @see self::decrypt()
* @var int
* @access private
*/
var $engine;
/**
* Holds the preferred crypt engine
*
* @see self::_setEngine()
* @see self::setPreferredEngine()
* @var int
* @access private
*/
var $preferredEngine;
/**
* The mcrypt specific name of the cipher
*
* Only used if $engine == CRYPT_MODE_MCRYPT
* Only used if $engine == self::ENGINE_MCRYPT
*
* @link http://www.php.net/mcrypt_module_open
* @link http://www.php.net/mcrypt_list_algorithms
* @see Crypt_Base::_setupMcrypt()
* @var String
* @see self::_setupMcrypt()
* @var string
* @access private
*/
var $cipher_name_mcrypt;
/**
* The default password key_size used by setPassword()
* The openssl specific name of the cipher
*
* @see Crypt_Base::setPassword()
* @var Integer
* Only used if $engine == self::ENGINE_OPENSSL
*
* @link http://www.php.net/openssl-get-cipher-methods
* @var string
* @access private
*/
var $password_key_size = 32;
var $cipher_name_openssl;
/**
* The openssl specific name of the cipher in ECB mode
*
* If OpenSSL does not support the mode we're trying to use (CTR)
* it can still be emulated with ECB mode.
*
* @link http://www.php.net/openssl-get-cipher-methods
* @var string
* @access private
*/
var $cipher_name_openssl_ecb;
/**
* The default salt used by setPassword()
*
* @see Crypt_Base::setPassword()
* @var String
* @see self::setPassword()
* @var string
* @access private
*/
var $password_default_salt = 'phpseclib/salt';
/**
* The namespace used by the cipher for its constants.
*
* ie: AES.php is using CRYPT_AES_MODE_* for its constants
* so $const_namespace is AES
*
* DES.php is using CRYPT_DES_MODE_* for its constants
* so $const_namespace is DES... and so on
*
* All CRYPT_<$const_namespace>_MODE_* are aliases of
* the generic CRYPT_MODE_* constants, so both could be used
* for each cipher.
*
* Example:
* $aes = new Crypt_AES(CRYPT_AES_MODE_CFB); // $aes will operate in cfb mode
* $aes = new Crypt_AES(CRYPT_MODE_CFB); // identical
*
* @see Crypt_Base::Crypt_Base()
* @var String
* @access private
*/
var $const_namespace;
/**
* The name of the performance-optimized callback function
*
* Used by encrypt() / decrypt()
* only if $engine == CRYPT_MODE_INTERNAL
* only if $engine == self::ENGINE_INTERNAL
*
* @see Crypt_Base::encrypt()
* @see Crypt_Base::decrypt()
* @see Crypt_Base::_setupInlineCrypt()
* @see Crypt_Base::$use_inline_crypt
* @see self::encrypt()
* @see self::decrypt()
* @see self::_setupInlineCrypt()
* @see self::$use_inline_crypt
* @var Callback
* @access private
*/
@ -411,14 +403,50 @@ class Crypt_Base
/**
* Holds whether performance-optimized $inline_crypt() can/should be used.
*
* @see Crypt_Base::encrypt()
* @see Crypt_Base::decrypt()
* @see Crypt_Base::inline_crypt
* @see self::encrypt()
* @see self::decrypt()
* @see self::inline_crypt
* @var mixed
* @access private
*/
var $use_inline_crypt;
/**
* If OpenSSL can be used in ECB but not in CTR we can emulate CTR
*
* @see self::_openssl_ctr_process()
* @var bool
* @access private
*/
var $openssl_emulate_ctr = false;
/**
* Determines what options are passed to openssl_encrypt/decrypt
*
* @see self::isValidEngine()
* @var mixed
* @access private
*/
var $openssl_options;
/**
* Has the key length explicitly been set or should it be derived from the key, itself?
*
* @see self::setKeyLength()
* @var bool
* @access private
*/
var $explicit_key_length = false;
/**
* Don't truncate / null pad key
*
* @see self::_clearBuffers()
* @var bool
* @access private
*/
var $skip_key_adjustment = false;
/**
* Default Constructor.
*
@ -426,69 +454,43 @@ class Crypt_Base
*
* $mode could be:
*
* - CRYPT_MODE_ECB
* - self::MODE_ECB
*
* - CRYPT_MODE_CBC
* - self::MODE_CBC
*
* - CRYPT_MODE_CTR
* - self::MODE_CTR
*
* - CRYPT_MODE_CFB
* - self::MODE_CFB
*
* - CRYPT_MODE_OFB
* - self::MODE_OFB
*
* (or the alias constants of the chosen cipher, for example for AES: CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC ...)
* If not explicitly set, self::MODE_CBC will be used.
*
* If not explicitly set, CRYPT_MODE_CBC will be used.
*
* @param optional Integer $mode
* @param int $mode
* @access public
*/
function Crypt_Base($mode = CRYPT_MODE_CBC)
function __construct($mode = self::MODE_CBC)
{
$const_crypt_mode = 'CRYPT_' . $this->const_namespace . '_MODE';
// Determining the availibility of mcrypt support for the cipher
if (!defined($const_crypt_mode)) {
switch (true) {
case extension_loaded('mcrypt') && in_array($this->cipher_name_mcrypt, mcrypt_list_algorithms()):
define($const_crypt_mode, CRYPT_MODE_MCRYPT);
break;
default:
define($const_crypt_mode, CRYPT_MODE_INTERNAL);
}
}
// Determining which internal $engine should be used.
// The fastes possible first.
switch (true) {
case empty($this->cipher_name_mcrypt): // The cipher module has no mcrypt-engine support at all so we force CRYPT_MODE_INTERNAL
$this->engine = CRYPT_MODE_INTERNAL;
break;
case constant($const_crypt_mode) == CRYPT_MODE_MCRYPT:
$this->engine = CRYPT_MODE_MCRYPT;
break;
default:
$this->engine = CRYPT_MODE_INTERNAL;
}
// $mode dependent settings
switch ($mode) {
case CRYPT_MODE_ECB:
case self::MODE_ECB:
$this->paddable = true;
$this->mode = self::MODE_ECB;
break;
case self::MODE_CTR:
case self::MODE_CFB:
case self::MODE_OFB:
case self::MODE_STREAM:
$this->mode = $mode;
break;
case CRYPT_MODE_CTR:
case CRYPT_MODE_CFB:
case CRYPT_MODE_OFB:
case CRYPT_MODE_STREAM:
$this->mode = $mode;
break;
case CRYPT_MODE_CBC:
case self::MODE_CBC:
default:
$this->paddable = true;
$this->mode = CRYPT_MODE_CBC;
$this->mode = self::MODE_CBC;
}
$this->_setEngine();
// Determining whether inline crypting can be used by the cipher
if ($this->use_inline_crypt !== false && function_exists('create_function')) {
$this->use_inline_crypt = true;
@ -498,17 +500,16 @@ class Crypt_Base
/**
* Sets the initialization vector. (optional)
*
* SetIV is not required when CRYPT_MODE_ECB (or ie for AES: CRYPT_AES_MODE_ECB) is being used. If not explicitly set, it'll be assumed
* SetIV is not required when self::MODE_ECB (or ie for AES: \phpseclib\Crypt\AES::MODE_ECB) is being used. If not explicitly set, it'll be assumed
* to be all zero's.
*
* Note: Could, but not must, extend by the child Crypt_* class
*
* @access public
* @param String $iv
* @param string $iv
* @internal Can be overwritten by a sub class, but does not have to be
*/
function setIV($iv)
{
if ($this->mode == CRYPT_MODE_ECB) {
if ($this->mode == self::MODE_ECB) {
return;
}
@ -516,6 +517,43 @@ class Crypt_Base
$this->changed = true;
}
/**
* Sets the key length.
*
* Keys with explicitly set lengths need to be treated accordingly
*
* @access public
* @param int $length
*/
function setKeyLength($length)
{
$this->explicit_key_length = true;
$this->changed = true;
$this->_setEngine();
}
/**
* Returns the current key length in bits
*
* @access public
* @return int
*/
function getKeyLength()
{
return $this->key_length << 3;
}
/**
* Returns the current block length in bits
*
* @access public
* @return int
*/
function getBlockLength()
{
return $this->block_size << 3;
}
/**
* Sets the key.
*
@ -526,15 +564,20 @@ class Crypt_Base
*
* If the key is not explicitly set, it'll be assumed to be all null bytes.
*
* Note: Could, but not must, extend by the child Crypt_* class
*
* @access public
* @param String $key
* @param string $key
* @internal Could, but not must, extend by the child Crypt_* class
*/
function setKey($key)
{
if (!$this->explicit_key_length) {
$this->setKeyLength(strlen($key) << 3);
$this->explicit_key_length = false;
}
$this->key = $key;
$this->changed = true;
$this->_setEngine();
}
/**
@ -546,13 +589,12 @@ class Crypt_Base
*
* Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
*
* Note: Could, but not must, extend by the child Crypt_* class
*
* @see Crypt/Hash.php
* @param String $password
* @param optional String $method
* @return Boolean
* @param string $password
* @param string $method
* @return bool
* @access public
* @internal Could, but not must, extend by the child Crypt_* class
*/
function setPassword($password, $method = 'pbkdf2')
{
@ -576,15 +618,12 @@ class Crypt_Base
if (isset($func_args[5])) {
$dkLen = $func_args[5];
} else {
$dkLen = $method == 'pbkdf1' ? 2 * $this->password_key_size : $this->password_key_size;
$dkLen = $method == 'pbkdf1' ? 2 * $this->key_length : $this->key_length;
}
switch (true) {
case $method == 'pbkdf1':
if (!class_exists('Crypt_Hash')) {
include_once 'Crypt/Hash.php';
}
$hashObj = new Crypt_Hash();
$hashObj = new Hash();
$hashObj->setHash($hash);
if ($dkLen > $hashObj->getLength()) {
user_error('Derived key too long');
@ -604,12 +643,9 @@ class Crypt_Base
case !function_exists('hash_pbkdf2'):
case !function_exists('hash_algos'):
case !in_array($hash, hash_algos()):
if (!class_exists('Crypt_Hash')) {
include_once 'Crypt/Hash.php';
}
$i = 1;
while (strlen($key) < $dkLen) {
$hmac = new Crypt_Hash();
$hmac = new Hash();
$hmac->setHash($hash);
$hmac->setKey($password);
$f = $u = $hmac->hash($salt . pack('N', $i++));
@ -645,29 +681,107 @@ class Crypt_Base
* strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that
* length.
*
* Note: Could, but not must, extend by the child Crypt_* class
*
* @see Crypt_Base::decrypt()
* @see self::decrypt()
* @access public
* @param String $plaintext
* @return String $cipertext
* @param string $plaintext
* @return string $ciphertext
* @internal Could, but not must, extend by the child Crypt_* class
*/
function encrypt($plaintext)
{
if ($this->engine == CRYPT_MODE_MCRYPT) {
if ($this->paddable) {
$plaintext = $this->_pad($plaintext);
}
if ($this->engine === self::ENGINE_OPENSSL) {
if ($this->changed) {
$this->_clearBuffers();
$this->changed = false;
}
switch ($this->mode) {
case self::MODE_STREAM:
return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
case self::MODE_ECB:
$result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
return !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
case self::MODE_CBC:
$result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->encryptIV);
if (!defined('OPENSSL_RAW_DATA')) {
$result = substr($result, 0, -$this->block_size);
}
if ($this->continuousBuffer) {
$this->encryptIV = substr($result, -$this->block_size);
}
return $result;
case self::MODE_CTR:
return $this->_openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer);
case self::MODE_CFB:
// cfb loosely routines inspired by openssl's:
// {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
$ciphertext = '';
if ($this->continuousBuffer) {
$iv = &$this->encryptIV;
$pos = &$this->enbuffer['pos'];
} else {
$iv = $this->encryptIV;
$pos = 0;
}
$len = strlen($plaintext);
$i = 0;
if ($pos) {
$orig_pos = $pos;
$max = $this->block_size - $pos;
if ($len >= $max) {
$i = $max;
$len-= $max;
$pos = 0;
} else {
$i = $len;
$pos+= $len;
$len = 0;
}
// ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
$ciphertext = substr($iv, $orig_pos) ^ $plaintext;
$iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
$plaintext = substr($plaintext, $i);
}
$overflow = $len % $this->block_size;
if ($overflow) {
$ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
$iv = $this->_string_pop($ciphertext, $this->block_size);
$size = $len - $overflow;
$block = $iv ^ substr($plaintext, -$overflow);
$iv = substr_replace($iv, $block, 0, $overflow);
$ciphertext.= $block;
$pos = $overflow;
} elseif ($len) {
$ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
$iv = substr($ciphertext, -$this->block_size);
}
return $ciphertext;
case self::MODE_OFB:
return $this->_openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
}
}
if ($this->engine === self::ENGINE_MCRYPT) {
if ($this->changed) {
$this->_setupMcrypt();
$this->changed = false;
}
if ($this->enchanged) {
mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
@mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
$this->enchanged = false;
}
// re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
// using mcrypt's default handing of CFB the above would output two different things. using phpseclib's
// rewritten CFB implementation the above outputs the same thing twice.
if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) {
if ($this->mode == self::MODE_CFB && $this->continuousBuffer) {
$block_size = $this->block_size;
$iv = &$this->encryptIV;
$pos = &$this->enbuffer['pos'];
@ -693,15 +807,15 @@ class Crypt_Base
if ($len >= $block_size) {
if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) {
if ($this->enbuffer['enmcrypt_init'] === true) {
mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
@mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
$this->enbuffer['enmcrypt_init'] = false;
}
$ciphertext.= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size));
$ciphertext.= @mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size));
$iv = substr($ciphertext, -$block_size);
$len%= $block_size;
} else {
while ($len >= $block_size) {
$iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size);
$iv = @mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size);
$ciphertext.= $iv;
$len-= $block_size;
$i+= $block_size;
@ -710,7 +824,7 @@ class Crypt_Base
}
if ($len) {
$iv = mcrypt_generic($this->ecb, $iv);
$iv = @mcrypt_generic($this->ecb, $iv);
$block = $iv ^ substr($plaintext, -$len);
$iv = substr_replace($iv, $block, 0, $len);
$ciphertext.= $block;
@ -720,14 +834,10 @@ class Crypt_Base
return $ciphertext;
}
if ($this->paddable) {
$plaintext = $this->_pad($plaintext);
}
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
$ciphertext = @mcrypt_generic($this->enmcrypt, $plaintext);
if (!$this->continuousBuffer) {
mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
@mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
}
return $ciphertext;
@ -741,20 +851,17 @@ class Crypt_Base
$inline = $this->inline_crypt;
return $inline('encrypt', $this, $plaintext);
}
if ($this->paddable) {
$plaintext = $this->_pad($plaintext);
}
$buffer = &$this->enbuffer;
$block_size = $this->block_size;
$ciphertext = '';
switch ($this->mode) {
case CRYPT_MODE_ECB:
case self::MODE_ECB:
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
$ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $block_size));
}
break;
case CRYPT_MODE_CBC:
case self::MODE_CBC:
$xor = $this->encryptIV;
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
$block = substr($plaintext, $i, $block_size);
@ -766,32 +873,34 @@ class Crypt_Base
$this->encryptIV = $xor;
}
break;
case CRYPT_MODE_CTR:
case self::MODE_CTR:
$xor = $this->encryptIV;
if (strlen($buffer['encrypted'])) {
if (strlen($buffer['ciphertext'])) {
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
$block = substr($plaintext, $i, $block_size);
if (strlen($block) > strlen($buffer['encrypted'])) {
$buffer['encrypted'].= $this->_encryptBlock($this->_generateXor($xor, $block_size));
if (strlen($block) > strlen($buffer['ciphertext'])) {
$buffer['ciphertext'].= $this->_encryptBlock($xor);
}
$key = $this->_stringShift($buffer['encrypted'], $block_size);
$this->_increment_str($xor);
$key = $this->_string_shift($buffer['ciphertext'], $block_size);
$ciphertext.= $block ^ $key;
}
} else {
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
$block = substr($plaintext, $i, $block_size);
$key = $this->_encryptBlock($this->_generateXor($xor, $block_size));
$key = $this->_encryptBlock($xor);
$this->_increment_str($xor);
$ciphertext.= $block ^ $key;
}
}
if ($this->continuousBuffer) {
$this->encryptIV = $xor;
if ($start = strlen($plaintext) % $block_size) {
$buffer['encrypted'] = substr($key, $start) . $buffer['encrypted'];
$buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
}
}
break;
case CRYPT_MODE_CFB:
case self::MODE_CFB:
// cfb loosely routines inspired by openssl's:
// {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
if ($this->continuousBuffer) {
@ -833,7 +942,7 @@ class Crypt_Base
$pos = $len;
}
break;
case CRYPT_MODE_OFB:
case self::MODE_OFB:
$xor = $this->encryptIV;
if (strlen($buffer['xor'])) {
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
@ -842,7 +951,7 @@ class Crypt_Base
$xor = $this->_encryptBlock($xor);
$buffer['xor'].= $xor;
}
$key = $this->_stringShift($buffer['xor'], $block_size);
$key = $this->_string_shift($buffer['xor'], $block_size);
$ciphertext.= $block ^ $key;
}
} else {
@ -855,11 +964,11 @@ class Crypt_Base
if ($this->continuousBuffer) {
$this->encryptIV = $xor;
if ($start = strlen($plaintext) % $block_size) {
$buffer['xor'] = substr($key, $start) . $buffer['xor'];
$buffer['xor'] = substr($key, $start) . $buffer['xor'];
}
}
break;
case CRYPT_MODE_STREAM:
case self::MODE_STREAM:
$ciphertext = $this->_encryptBlock($plaintext);
break;
}
@ -873,27 +982,115 @@ class Crypt_Base
* If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
* it is.
*
* Note: Could, but not must, extend by the child Crypt_* class
*
* @see Crypt_Base::encrypt()
* @see self::encrypt()
* @access public
* @param String $ciphertext
* @return String $plaintext
* @param string $ciphertext
* @return string $plaintext
* @internal Could, but not must, extend by the child Crypt_* class
*/
function decrypt($ciphertext)
{
if ($this->engine == CRYPT_MODE_MCRYPT) {
if ($this->paddable) {
// we pad with chr(0) since that's what mcrypt_generic does. to quote from {@link http://www.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) + ($this->block_size - strlen($ciphertext) % $this->block_size) % $this->block_size, chr(0));
}
if ($this->engine === self::ENGINE_OPENSSL) {
if ($this->changed) {
$this->_clearBuffers();
$this->changed = false;
}
switch ($this->mode) {
case self::MODE_STREAM:
$plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
break;
case self::MODE_ECB:
if (!defined('OPENSSL_RAW_DATA')) {
$ciphertext.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $this->key, true);
}
$plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
break;
case self::MODE_CBC:
if (!defined('OPENSSL_RAW_DATA')) {
$padding = str_repeat(chr($this->block_size), $this->block_size) ^ substr($ciphertext, -$this->block_size);
$ciphertext.= substr(openssl_encrypt($padding, $this->cipher_name_openssl_ecb, $this->key, true), 0, $this->block_size);
$offset = 2 * $this->block_size;
} else {
$offset = $this->block_size;
}
$plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->decryptIV);
if ($this->continuousBuffer) {
$this->decryptIV = substr($ciphertext, -$offset, $this->block_size);
}
break;
case self::MODE_CTR:
$plaintext = $this->_openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer);
break;
case self::MODE_CFB:
// cfb loosely routines inspired by openssl's:
// {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
$plaintext = '';
if ($this->continuousBuffer) {
$iv = &$this->decryptIV;
$pos = &$this->buffer['pos'];
} else {
$iv = $this->decryptIV;
$pos = 0;
}
$len = strlen($ciphertext);
$i = 0;
if ($pos) {
$orig_pos = $pos;
$max = $this->block_size - $pos;
if ($len >= $max) {
$i = $max;
$len-= $max;
$pos = 0;
} else {
$i = $len;
$pos+= $len;
$len = 0;
}
// ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $this->blocksize
$plaintext = substr($iv, $orig_pos) ^ $ciphertext;
$iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
$ciphertext = substr($ciphertext, $i);
}
$overflow = $len % $this->block_size;
if ($overflow) {
$plaintext.= openssl_decrypt(substr($ciphertext, 0, -$overflow), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
if ($len - $overflow) {
$iv = substr($ciphertext, -$overflow - $this->block_size, -$overflow);
}
$iv = openssl_encrypt(str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
$plaintext.= $iv ^ substr($ciphertext, -$overflow);
$iv = substr_replace($iv, substr($ciphertext, -$overflow), 0, $overflow);
$pos = $overflow;
} elseif ($len) {
$plaintext.= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
$iv = substr($ciphertext, -$this->block_size);
}
break;
case self::MODE_OFB:
$plaintext = $this->_openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer);
}
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
}
if ($this->engine === self::ENGINE_MCRYPT) {
$block_size = $this->block_size;
if ($this->changed) {
$this->_setupMcrypt();
$this->changed = false;
}
if ($this->dechanged) {
mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
@mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
$this->dechanged = false;
}
if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) {
if ($this->mode == self::MODE_CFB && $this->continuousBuffer) {
$iv = &$this->decryptIV;
$pos = &$this->debuffer['pos'];
$len = strlen($ciphertext);
@ -917,12 +1114,12 @@ class Crypt_Base
}
if ($len >= $block_size) {
$cb = substr($ciphertext, $i, $len - $len % $block_size);
$plaintext.= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
$plaintext.= @mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
$iv = substr($cb, -$block_size);
$len%= $block_size;
}
if ($len) {
$iv = mcrypt_generic($this->ecb, $iv);
$iv = @mcrypt_generic($this->ecb, $iv);
$plaintext.= $iv ^ substr($ciphertext, -$len);
$iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
$pos = $len;
@ -931,16 +1128,10 @@ class Crypt_Base
return $plaintext;
}
if ($this->paddable) {
// we pad with chr(0) since that's what mcrypt_generic does. to quote from {@link http://www.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) + ($block_size - strlen($ciphertext) % $block_size) % $block_size, chr(0));
}
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
$plaintext = @mdecrypt_generic($this->demcrypt, $ciphertext);
if (!$this->continuousBuffer) {
mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
@mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
}
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
@ -956,20 +1147,16 @@ class Crypt_Base
}
$block_size = $this->block_size;
if ($this->paddable) {
// we pad with chr(0) since that's what mcrypt_generic does [...]
$ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($block_size - strlen($ciphertext) % $block_size) % $block_size, chr(0));
}
$buffer = &$this->debuffer;
$plaintext = '';
switch ($this->mode) {
case CRYPT_MODE_ECB:
case self::MODE_ECB:
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
$plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $block_size));
}
break;
case CRYPT_MODE_CBC:
case self::MODE_CBC:
$xor = $this->decryptIV;
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
$block = substr($ciphertext, $i, $block_size);
@ -980,21 +1167,23 @@ class Crypt_Base
$this->decryptIV = $xor;
}
break;
case CRYPT_MODE_CTR:
case self::MODE_CTR:
$xor = $this->decryptIV;
if (strlen($buffer['ciphertext'])) {
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
$block = substr($ciphertext, $i, $block_size);
if (strlen($block) > strlen($buffer['ciphertext'])) {
$buffer['ciphertext'].= $this->_encryptBlock($this->_generateXor($xor, $block_size));
$buffer['ciphertext'].= $this->_encryptBlock($xor);
$this->_increment_str($xor);
}
$key = $this->_stringShift($buffer['ciphertext'], $block_size);
$key = $this->_string_shift($buffer['ciphertext'], $block_size);
$plaintext.= $block ^ $key;
}
} else {
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
$block = substr($ciphertext, $i, $block_size);
$key = $this->_encryptBlock($this->_generateXor($xor, $block_size));
$key = $this->_encryptBlock($xor);
$this->_increment_str($xor);
$plaintext.= $block ^ $key;
}
}
@ -1005,7 +1194,7 @@ class Crypt_Base
}
}
break;
case CRYPT_MODE_CFB:
case self::MODE_CFB:
if ($this->continuousBuffer) {
$iv = &$this->decryptIV;
$pos = &$buffer['pos'];
@ -1046,7 +1235,7 @@ class Crypt_Base
$pos = $len;
}
break;
case CRYPT_MODE_OFB:
case self::MODE_OFB:
$xor = $this->decryptIV;
if (strlen($buffer['xor'])) {
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
@ -1055,7 +1244,7 @@ class Crypt_Base
$xor = $this->_encryptBlock($xor);
$buffer['xor'].= $xor;
}
$key = $this->_stringShift($buffer['xor'], $block_size);
$key = $this->_string_shift($buffer['xor'], $block_size);
$plaintext.= $block ^ $key;
}
} else {
@ -1068,17 +1257,189 @@ class Crypt_Base
if ($this->continuousBuffer) {
$this->decryptIV = $xor;
if ($start = strlen($ciphertext) % $block_size) {
$buffer['xor'] = substr($key, $start) . $buffer['xor'];
$buffer['xor'] = substr($key, $start) . $buffer['xor'];
}
}
break;
case CRYPT_MODE_STREAM:
case self::MODE_STREAM:
$plaintext = $this->_decryptBlock($ciphertext);
break;
}
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
}
/**
* OpenSSL CTR Processor
*
* PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
* for CTR is the same for both encrypting and decrypting this function is re-used by both Base::encrypt()
* and Base::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this
* function will emulate CTR with ECB when necessary.
*
* @see self::encrypt()
* @see self::decrypt()
* @param string $plaintext
* @param string $encryptIV
* @param array $buffer
* @return string
* @access private
*/
function _openssl_ctr_process($plaintext, &$encryptIV, &$buffer)
{
$ciphertext = '';
$block_size = $this->block_size;
$key = $this->key;
if ($this->openssl_emulate_ctr) {
$xor = $encryptIV;
if (strlen($buffer['ciphertext'])) {
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
$block = substr($plaintext, $i, $block_size);
if (strlen($block) > strlen($buffer['ciphertext'])) {
$result = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
$result = !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
$buffer['ciphertext'].= $result;
}
$this->_increment_str($xor);
$otp = $this->_string_shift($buffer['ciphertext'], $block_size);
$ciphertext.= $block ^ $otp;
}
} else {
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
$block = substr($plaintext, $i, $block_size);
$otp = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
$otp = !defined('OPENSSL_RAW_DATA') ? substr($otp, 0, -$this->block_size) : $otp;
$this->_increment_str($xor);
$ciphertext.= $block ^ $otp;
}
}
if ($this->continuousBuffer) {
$encryptIV = $xor;
if ($start = strlen($plaintext) % $block_size) {
$buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
}
}
return $ciphertext;
}
if (strlen($buffer['ciphertext'])) {
$ciphertext = $plaintext ^ $this->_string_shift($buffer['ciphertext'], strlen($plaintext));
$plaintext = substr($plaintext, strlen($ciphertext));
if (!strlen($plaintext)) {
return $ciphertext;
}
}
$overflow = strlen($plaintext) % $block_size;
if ($overflow) {
$plaintext2 = $this->_string_pop($plaintext, $overflow); // ie. trim $plaintext to a multiple of $block_size and put rest of $plaintext in $plaintext2
$encrypted = openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
$temp = $this->_string_pop($encrypted, $block_size);
$ciphertext.= $encrypted . ($plaintext2 ^ $temp);
if ($this->continuousBuffer) {
$buffer['ciphertext'] = substr($temp, $overflow);
$encryptIV = $temp;
}
} elseif (!strlen($buffer['ciphertext'])) {
$ciphertext.= openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
$temp = $this->_string_pop($ciphertext, $block_size);
if ($this->continuousBuffer) {
$encryptIV = $temp;
}
}
if ($this->continuousBuffer) {
if (!defined('OPENSSL_RAW_DATA')) {
$encryptIV.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
}
$encryptIV = openssl_decrypt($encryptIV, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
if ($overflow) {
$this->_increment_str($encryptIV);
}
}
return $ciphertext;
}
/**
* OpenSSL OFB Processor
*
* PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
* for OFB is the same for both encrypting and decrypting this function is re-used by both Base::encrypt()
* and Base::decrypt().
*
* @see self::encrypt()
* @see self::decrypt()
* @param string $plaintext
* @param string $encryptIV
* @param array $buffer
* @return string
* @access private
*/
function _openssl_ofb_process($plaintext, &$encryptIV, &$buffer)
{
if (strlen($buffer['xor'])) {
$ciphertext = $plaintext ^ $buffer['xor'];
$buffer['xor'] = substr($buffer['xor'], strlen($ciphertext));
$plaintext = substr($plaintext, strlen($ciphertext));
} else {
$ciphertext = '';
}
$block_size = $this->block_size;
$len = strlen($plaintext);
$key = $this->key;
$overflow = $len % $block_size;
if (strlen($plaintext)) {
if ($overflow) {
$ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
$xor = $this->_string_pop($ciphertext, $block_size);
if ($this->continuousBuffer) {
$encryptIV = $xor;
}
$ciphertext.= $this->_string_shift($xor, $overflow) ^ substr($plaintext, -$overflow);
if ($this->continuousBuffer) {
$buffer['xor'] = $xor;
}
} else {
$ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
if ($this->continuousBuffer) {
$encryptIV = substr($ciphertext, -$block_size) ^ substr($plaintext, -$block_size);
}
}
}
return $ciphertext;
}
/**
* phpseclib <-> OpenSSL Mode Mapper
*
* May need to be overwritten by classes extending this one in some cases
*
* @return int
* @access private
*/
function _openssl_translate_mode()
{
switch ($this->mode) {
case self::MODE_ECB:
return 'ecb';
case self::MODE_CBC:
return 'cbc';
case self::MODE_CTR:
return 'ctr';
case self::MODE_CFB:
return 'cfb';
case self::MODE_OFB:
return 'ofb';
}
}
/**
* Pad "packets".
*
@ -1091,7 +1452,7 @@ class Crypt_Base
* away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
* transmitted separately)
*
* @see Crypt_Base::disablePadding()
* @see self::disablePadding()
* @access public
*/
function enablePadding()
@ -1102,7 +1463,7 @@ class Crypt_Base
/**
* Do not pad packets.
*
* @see Crypt_Base::enablePadding()
* @see self::enablePadding()
* @access public
*/
function disablePadding()
@ -1139,23 +1500,24 @@ class Crypt_Base
* 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_*() object changes after each
* Put another way, when the continuous buffer is enabled, the state of the \phpseclib\Crypt\*() 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.
*
* Note: Could, but not must, extend by the child Crypt_* class
*
* @see Crypt_Base::disableContinuousBuffer()
* @see self::disableContinuousBuffer()
* @access public
* @internal Could, but not must, extend by the child Crypt_* class
*/
function enableContinuousBuffer()
{
if ($this->mode == CRYPT_MODE_ECB) {
if ($this->mode == self::MODE_ECB) {
return;
}
$this->continuousBuffer = true;
$this->_setEngine();
}
/**
@ -1163,14 +1525,13 @@ class Crypt_Base
*
* The default behavior.
*
* Note: Could, but not must, extend by the child Crypt_* class
*
* @see Crypt_Base::enableContinuousBuffer()
* @see self::enableContinuousBuffer()
* @access public
* @internal Could, but not must, extend by the child Crypt_* class
*/
function disableContinuousBuffer()
{
if ($this->mode == CRYPT_MODE_ECB) {
if ($this->mode == self::MODE_ECB) {
return;
}
if (!$this->continuousBuffer) {
@ -1179,56 +1540,191 @@ class Crypt_Base
$this->continuousBuffer = false;
$this->changed = true;
$this->_setEngine();
}
/**
* Test for engine validity
*
* @see self::__construct()
* @param int $engine
* @access public
* @return bool
*/
function isValidEngine($engine)
{
switch ($engine) {
case self::ENGINE_OPENSSL:
if ($this->mode == self::MODE_STREAM && $this->continuousBuffer) {
return false;
}
$this->openssl_emulate_ctr = false;
$result = $this->cipher_name_openssl &&
extension_loaded('openssl') &&
// PHP 5.3.0 - 5.3.2 did not let you set IV's
version_compare(PHP_VERSION, '5.3.3', '>=');
if (!$result) {
return false;
}
// prior to PHP 5.4.0 OPENSSL_RAW_DATA and OPENSSL_ZERO_PADDING were not defined. instead of expecting an integer
// $options openssl_encrypt expected a boolean $raw_data.
if (!defined('OPENSSL_RAW_DATA')) {
$this->openssl_options = true;
} else {
$this->openssl_options = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING;
}
$methods = openssl_get_cipher_methods();
if (in_array($this->cipher_name_openssl, $methods)) {
return true;
}
// not all of openssl's symmetric cipher's support ctr. for those
// that don't we'll emulate it
switch ($this->mode) {
case self::MODE_CTR:
if (in_array($this->cipher_name_openssl_ecb, $methods)) {
$this->openssl_emulate_ctr = true;
return true;
}
}
return false;
case self::ENGINE_MCRYPT:
return $this->cipher_name_mcrypt &&
extension_loaded('mcrypt') &&
in_array($this->cipher_name_mcrypt, @mcrypt_list_algorithms());
case self::ENGINE_INTERNAL:
return true;
}
return false;
}
/**
* Sets the preferred crypt engine
*
* Currently, $engine could be:
*
* - \phpseclib\Crypt\Base::ENGINE_OPENSSL [very fast]
*
* - \phpseclib\Crypt\Base::ENGINE_MCRYPT [fast]
*
* - \phpseclib\Crypt\Base::ENGINE_INTERNAL [slow]
*
* If the preferred crypt engine is not available the fastest available one will be used
*
* @see self::__construct()
* @param int $engine
* @access public
*/
function setPreferredEngine($engine)
{
switch ($engine) {
//case self::ENGINE_OPENSSL;
case self::ENGINE_MCRYPT:
case self::ENGINE_INTERNAL:
$this->preferredEngine = $engine;
break;
default:
$this->preferredEngine = self::ENGINE_OPENSSL;
}
$this->_setEngine();
}
/**
* Returns the engine currently being utilized
*
* @see self::_setEngine()
* @access public
*/
function getEngine()
{
return $this->engine;
}
/**
* Sets the engine as appropriate
*
* @see self::__construct()
* @access private
*/
function _setEngine()
{
$this->engine = null;
$candidateEngines = array(
$this->preferredEngine,
self::ENGINE_OPENSSL,
self::ENGINE_MCRYPT
);
foreach ($candidateEngines as $engine) {
if ($this->isValidEngine($engine)) {
$this->engine = $engine;
break;
}
}
if (!$this->engine) {
$this->engine = self::ENGINE_INTERNAL;
}
if ($this->engine != self::ENGINE_MCRYPT && $this->enmcrypt) {
// Closing the current mcrypt resource(s). _mcryptSetup() will, if needed,
// (re)open them with the module named in $this->cipher_name_mcrypt
@mcrypt_module_close($this->enmcrypt);
@mcrypt_module_close($this->demcrypt);
$this->enmcrypt = null;
$this->demcrypt = null;
if ($this->ecb) {
@mcrypt_module_close($this->ecb);
$this->ecb = null;
}
}
$this->changed = true;
}
/**
* Encrypts a block
*
* Note: Must extend by the child Crypt_* class
* Note: Must be extended by the child \phpseclib\Crypt\* class
*
* @access private
* @param String $in
* @return String
* @param string $in
* @return string
*/
function _encryptBlock($in)
{
user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
}
abstract function _encryptBlock($in);
/**
* Decrypts a block
*
* Note: Must extend by the child Crypt_* class
* Note: Must be extended by the child \phpseclib\Crypt\* class
*
* @access private
* @param String $in
* @return String
* @param string $in
* @return string
*/
function _decryptBlock($in)
{
user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
}
abstract function _decryptBlock($in);
/**
* Setup the key (expansion)
*
* Only used if $engine == CRYPT_MODE_INTERNAL
* Only used if $engine == self::ENGINE_INTERNAL
*
* Note: Must extend by the child Crypt_* class
* Note: Must extend by the child \phpseclib\Crypt\* class
*
* @see Crypt_Base::_setup()
* @see self::_setup()
* @access private
*/
function _setupKey()
{
user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
}
abstract function _setupKey();
/**
* Setup the CRYPT_MODE_INTERNAL $engine
* Setup the self::ENGINE_INTERNAL $engine
*
* (re)init, if necessary, the internal cipher $engine and flush all $buffers
* Used (only) if $engine == CRYPT_MODE_INTERNAL
* Used (only) if $engine == self::ENGINE_INTERNAL
*
* _setup() will be called each time if $changed === true
* typically this happens when using one or more of following public methods:
@ -1241,14 +1737,12 @@ class Crypt_Base
*
* - First run of encrypt() / decrypt() with no init-settings
*
* Internally: _setup() is called always before(!) en/decryption.
*
* Note: Could, but not must, extend by the child Crypt_* class
*
* @see setKey()
* @see setIV()
* @see disableContinuousBuffer()
* @see self::setKey()
* @see self::setIV()
* @see self::disableContinuousBuffer()
* @access private
* @internal _setup() is always called before en/decryption.
* @internal Could, but not must, extend by the child Crypt_* class
*/
function _setup()
{
@ -1261,10 +1755,10 @@ class Crypt_Base
}
/**
* Setup the CRYPT_MODE_MCRYPT $engine
* Setup the self::ENGINE_MCRYPT $engine
*
* (re)init, if necessary, the (ext)mcrypt resources and flush all $buffers
* Used (only) if $engine = CRYPT_MODE_MCRYPT
* Used (only) if $engine = self::ENGINE_MCRYPT
*
* _setupMcrypt() will be called each time if $changed === true
* typically this happens when using one or more of following public methods:
@ -1277,13 +1771,11 @@ class Crypt_Base
*
* - First run of encrypt() / decrypt()
*
*
* Note: Could, but not must, extend by the child Crypt_* class
*
* @see setKey()
* @see setIV()
* @see disableContinuousBuffer()
* @see self::setKey()
* @see self::setIV()
* @see self::disableContinuousBuffer()
* @access private
* @internal Could, but not must, extend by the child Crypt_* class
*/
function _setupMcrypt()
{
@ -1292,28 +1784,27 @@ class Crypt_Base
if (!isset($this->enmcrypt)) {
static $mcrypt_modes = array(
CRYPT_MODE_CTR => 'ctr',
CRYPT_MODE_ECB => MCRYPT_MODE_ECB,
CRYPT_MODE_CBC => MCRYPT_MODE_CBC,
CRYPT_MODE_CFB => 'ncfb',
CRYPT_MODE_OFB => MCRYPT_MODE_NOFB,
CRYPT_MODE_STREAM => MCRYPT_MODE_STREAM,
self::MODE_CTR => 'ctr',
self::MODE_ECB => MCRYPT_MODE_ECB,
self::MODE_CBC => MCRYPT_MODE_CBC,
self::MODE_CFB => 'ncfb',
self::MODE_OFB => MCRYPT_MODE_NOFB,
self::MODE_STREAM => MCRYPT_MODE_STREAM,
);
$this->demcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
$this->enmcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
$this->demcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
$this->enmcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
// we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer()
// to workaround mcrypt's broken ncfb implementation in buffered mode
// see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
if ($this->mode == CRYPT_MODE_CFB) {
$this->ecb = mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
if ($this->mode == self::MODE_CFB) {
$this->ecb = @mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
}
} // else should mcrypt_generic_deinit be called?
if ($this->mode == CRYPT_MODE_CFB) {
mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size));
if ($this->mode == self::MODE_CFB) {
@mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size));
}
}
@ -1327,10 +1818,10 @@ class Crypt_Base
* 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_Base::_unpad()
* @param String $text
* @see self::_unpad()
* @param string $text
* @access private
* @return String
* @return string
*/
function _pad($text)
{
@ -1356,10 +1847,10 @@ class Crypt_Base
* 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_Base::_pad()
* @param String $text
* @see self::_pad()
* @param string $text
* @access private
* @return String
* @return string
*/
function _unpad($text)
{
@ -1383,18 +1874,20 @@ class Crypt_Base
* after disableContinuousBuffer() or on cipher $engine (re)init
* ie after setKey() or setIV()
*
* Note: Could, but not must, extend by the child Crypt_* class
*
* @access public
* @internal Could, but not must, extend by the child Crypt_* class
*/
function _clearBuffers()
{
$this->enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
$this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'demcrypt_init' => true);
$this->enbuffer = $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
// mcrypt's handling of invalid's $iv:
// $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size);
$this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0");
if (!$this->skip_key_adjustment) {
$this->key = str_pad(substr($this->key, 0, $this->key_length), $this->key_length, "\0");
}
}
/**
@ -1402,12 +1895,12 @@ class Crypt_Base
*
* Inspired by array_shift
*
* @param String $string
* @param optional Integer $index
* @param string $string
* @param int $index
* @access private
* @return String
* @return string
*/
function _stringShift(&$string, $index = 1)
function _string_shift(&$string, $index = 1)
{
$substr = substr($string, 0, $index);
$string = substr($string, $index);
@ -1415,43 +1908,57 @@ class Crypt_Base
}
/**
* Generate CTR XOR encryption key
* String Pop
*
* Encrypt the output of this and XOR it against the ciphertext / plaintext to get the
* plaintext / ciphertext in CTR mode.
* Inspired by array_pop
*
* @see Crypt_Base::decrypt()
* @see Crypt_Base::encrypt()
* @param String $iv
* @param Integer $length
* @param string $string
* @param int $index
* @access private
* @return String $xor
* @return string
*/
function _generateXor(&$iv, $length)
function _string_pop(&$string, $index = 1)
{
$xor = '';
$block_size = $this->block_size;
$num_blocks = floor(($length + ($block_size - 1)) / $block_size);
for ($i = 0; $i < $num_blocks; $i++) {
$xor.= $iv;
for ($j = 4; $j <= $block_size; $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;
}
$substr = substr($string, -$index);
$string = substr($string, 0, -$index);
return $substr;
}
/**
* Increment the current string
*
* @see self::decrypt()
* @see self::encrypt()
* @param string $var
* @access private
*/
function _increment_str(&$var)
{
for ($i = 4; $i <= strlen($var); $i+= 4) {
$temp = substr($var, -$i, 4);
switch ($temp) {
case "\xFF\xFF\xFF\xFF":
$var = substr_replace($var, "\x00\x00\x00\x00", -$i, 4);
break;
case "\x7F\xFF\xFF\xFF":
$var = substr_replace($var, "\x80\x00\x00\x00", -$i, 4);
return;
default:
$temp = unpack('Nnum', $temp);
$var = substr_replace($var, pack('N', $temp['num'] + 1), -$i, 4);
return;
}
}
return $xor;
$remainder = strlen($var) % 4;
if ($remainder == 0) {
return;
}
$temp = unpack('Nnum', str_pad(substr($var, 0, $remainder), 4, "\0", STR_PAD_LEFT));
$temp = substr(pack('N', $temp['num'] + 1), -$remainder);
$var = substr_replace($var, $temp, 0, $remainder);
}
/**
@ -1464,7 +1971,7 @@ class Crypt_Base
*
* _setupInlineCrypt() would be called only if:
*
* - $engine == CRYPT_MODE_INTERNAL and
* - $engine == self::ENGINE_INTERNAL and
*
* - $use_inline_crypt === true
*
@ -1499,7 +2006,7 @@ class Crypt_Base
* - short (as good as possible)
*
* Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code.
* - In case of using inline crypting, _setupInlineCrypt() must extend by the child Crypt_* class.
* - In case of using inline crypting, _setupInlineCrypt() must extend by the child \phpseclib\Crypt\* class.
* - The following variable names are reserved:
* - $_* (all variable names prefixed with an underscore)
* - $self (object reference to it self. Do not use $this, but $self instead)
@ -1507,19 +2014,18 @@ class Crypt_Base
* - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only
*
*
* @see Crypt_Base::_setup()
* @see Crypt_Base::_createInlineCryptFunction()
* @see Crypt_Base::encrypt()
* @see Crypt_Base::decrypt()
* @see self::_setup()
* @see self::_createInlineCryptFunction()
* @see self::encrypt()
* @see self::decrypt()
* @access private
* @internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()
*/
function _setupInlineCrypt()
{
// If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()
// If, for any reason, an extending Crypt_Base() Crypt_* class
// If, for any reason, an extending \phpseclib\Crypt\Base() \phpseclib\Crypt\* class
// not using inline crypting then it must be ensured that: $this->use_inline_crypt = false
// ie in the class var declaration of $use_inline_crypt in general for the Crypt_* class,
// ie in the class var declaration of $use_inline_crypt in general for the \phpseclib\Crypt\* class,
// in the constructor at object instance-time
// or, if it's runtime-specific, at runtime
@ -1616,7 +2122,7 @@ class Crypt_Base
* +----------------------------------------------------------------------------------------------+
* </code>
*
* See also the Crypt_*::_setupInlineCrypt()'s for
* See also the \phpseclib\Crypt\*::_setupInlineCrypt()'s for
* productive inline $cipher_code's how they works.
*
* Structure of:
@ -1630,12 +2136,12 @@ class Crypt_Base
* );
* </code>
*
* @see Crypt_Base::_setupInlineCrypt()
* @see Crypt_Base::encrypt()
* @see Crypt_Base::decrypt()
* @param Array $cipher_code
* @see self::_setupInlineCrypt()
* @see self::encrypt()
* @see self::decrypt()
* @param array $cipher_code
* @access private
* @return String (the name of the created callback function)
* @return string (the name of the created callback function)
*/
function _createInlineCryptFunction($cipher_code)
{
@ -1653,10 +2159,9 @@ class Crypt_Base
// merged with the $cipher_code algorithm
// for encrypt- and decryption.
switch ($this->mode) {
case CRYPT_MODE_ECB:
case self::MODE_ECB:
$encrypt = $init_encrypt . '
$_ciphertext = "";
$_text = $self->_pad($_text);
$_plaintext_len = strlen($_text);
for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
@ -1682,29 +2187,30 @@ class Crypt_Base
return $self->_unpad($_plaintext);
';
break;
case CRYPT_MODE_CTR:
case self::MODE_CTR:
$encrypt = $init_encrypt . '
$_ciphertext = "";
$_plaintext_len = strlen($_text);
$_xor = $self->encryptIV;
$_buffer = &$self->enbuffer;
if (strlen($_buffer["encrypted"])) {
if (strlen($_buffer["ciphertext"])) {
for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
$_block = substr($_text, $_i, '.$block_size.');
if (strlen($_block) > strlen($_buffer["encrypted"])) {
$in = $self->_generateXor($_xor, '.$block_size.');
if (strlen($_block) > strlen($_buffer["ciphertext"])) {
$in = $_xor;
'.$encrypt_block.'
$_buffer["encrypted"].= $in;
$self->_increment_str($_xor);
$_buffer["ciphertext"].= $in;
}
$_key = $self->_stringShift($_buffer["encrypted"], '.$block_size.');
$_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
$_ciphertext.= $_block ^ $_key;
}
} else {
for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
$_block = substr($_text, $_i, '.$block_size.');
$in = $self->_generateXor($_xor, '.$block_size.');
$in = $_xor;
'.$encrypt_block.'
$self->_increment_str($_xor);
$_key = $in;
$_ciphertext.= $_block ^ $_key;
}
@ -1712,7 +2218,7 @@ class Crypt_Base
if ($self->continuousBuffer) {
$self->encryptIV = $_xor;
if ($_start = $_plaintext_len % '.$block_size.') {
$_buffer["encrypted"] = substr($_key, $_start) . $_buffer["encrypted"];
$_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
}
}
@ -1729,18 +2235,20 @@ class Crypt_Base
for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
$_block = substr($_text, $_i, '.$block_size.');
if (strlen($_block) > strlen($_buffer["ciphertext"])) {
$in = $self->_generateXor($_xor, '.$block_size.');
$in = $_xor;
'.$encrypt_block.'
$self->_increment_str($_xor);
$_buffer["ciphertext"].= $in;
}
$_key = $self->_stringShift($_buffer["ciphertext"], '.$block_size.');
$_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
$_plaintext.= $_block ^ $_key;
}
} else {
for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
$_block = substr($_text, $_i, '.$block_size.');
$in = $self->_generateXor($_xor, '.$block_size.');
$in = $_xor;
'.$encrypt_block.'
$self->_increment_str($_xor);
$_key = $in;
$_plaintext.= $_block ^ $_key;
}
@ -1755,7 +2263,7 @@ class Crypt_Base
return $_plaintext;
';
break;
case CRYPT_MODE_CFB:
case self::MODE_CFB:
$encrypt = $init_encrypt . '
$_ciphertext = "";
$_buffer = &$self->enbuffer;
@ -1854,7 +2362,7 @@ class Crypt_Base
return $_plaintext;
';
break;
case CRYPT_MODE_OFB:
case self::MODE_OFB:
$encrypt = $init_encrypt . '
$_ciphertext = "";
$_plaintext_len = strlen($_text);
@ -1870,7 +2378,7 @@ class Crypt_Base
$_xor = $in;
$_buffer["xor"].= $_xor;
}
$_key = $self->_stringShift($_buffer["xor"], '.$block_size.');
$_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
$_ciphertext.= $_block ^ $_key;
}
} else {
@ -1906,7 +2414,7 @@ class Crypt_Base
$_xor = $in;
$_buffer["xor"].= $_xor;
}
$_key = $self->_stringShift($_buffer["xor"], '.$block_size.');
$_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
$_plaintext.= $_block ^ $_key;
}
} else {
@ -1927,7 +2435,7 @@ class Crypt_Base
return $_plaintext;
';
break;
case CRYPT_MODE_STREAM:
case self::MODE_STREAM:
$encrypt = $init_encrypt . '
$_ciphertext = "";
'.$encrypt_block.'
@ -1939,11 +2447,10 @@ class Crypt_Base
return $_plaintext;
';
break;
// case CRYPT_MODE_CBC:
// case self::MODE_CBC:
default:
$encrypt = $init_encrypt . '
$_ciphertext = "";
$_text = $self->_pad($_text);
$_plaintext_len = strlen($_text);
$in = $self->encryptIV;
@ -1996,16 +2503,51 @@ class Crypt_Base
* is stored, classwide (!), here for reusing.
*
* The string-based index of $function is a classwide
* uniqe value representing, at least, the $mode of
* unique value representing, at least, the $mode of
* operation (or more... depends of the optimizing level)
* for which $mode the lambda function was created.
*
* @access private
* @return &Array
* @return array &$functions
*/
function &_getLambdaFunctions()
{
static $functions = array();
return $functions;
}
/**
* Generates a digest from $bytes
*
* @see self::_setupInlineCrypt()
* @access private
* @param $bytes
* @return string
*/
function _hashInlineCryptFunction($bytes)
{
if (!isset(self::$WHIRLPOOL_AVAILABLE)) {
self::$WHIRLPOOL_AVAILABLE = extension_loaded('hash') && in_array('whirlpool', hash_algos());
}
$result = '';
$hash = $bytes;
switch (true) {
case self::$WHIRLPOOL_AVAILABLE:
foreach (str_split($bytes, 64) as $t) {
$hash = hash('whirlpool', $hash, true);
$result .= $t ^ $hash;
}
return $result . hash('whirlpool', $hash, true);
default:
$len = strlen($bytes);
for ($i = 0; $i < $len; $i+=20) {
$t = substr($bytes, $i, 20);
$hash = pack('H*', sha1($hash));
$result .= $t ^ $hash;
}
return $result . pack('H*', sha1($hash));
}
}
}

View file

@ -5,7 +5,7 @@
*
* Uses mcrypt, if available, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
* PHP version 5
*
* Useful resources are as follows:
*
@ -14,9 +14,9 @@
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/Blowfish.php';
* include 'vendor/autoload.php';
*
* $blowfish = new Crypt_Blowfish();
* $blowfish = new \phpseclib\Crypt\Blowfish();
*
* $blowfish->setKey('12345678901234567890123456789012');
*
@ -26,26 +26,8 @@
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_Blowfish
* @package Blowfish
* @author Jim Wigginton <terrafrost@php.net>
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
* @copyright 2007 Jim Wigginton
@ -53,111 +35,32 @@
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Base
*
* Base cipher class
*/
if (!class_exists('Crypt_Base')) {
include_once 'Base.php';
}
/**#@+
* @access public
* @see Crypt_Blowfish::encrypt()
* @see Crypt_Blowfish::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_BLOWFISH_MODE_CTR', CRYPT_MODE_CTR);
/**
* 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_BLOWFISH_MODE_ECB', CRYPT_MODE_ECB);
/**
* 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_BLOWFISH_MODE_CBC', CRYPT_MODE_CBC);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/
define('CRYPT_BLOWFISH_MODE_CFB', CRYPT_MODE_CFB);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/
define('CRYPT_BLOWFISH_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/
/**#@+
* @access private
* @see Crypt_Base::Crypt_Base()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_BLOWFISH_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_BLOWFISH_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
namespace phpseclib\Crypt;
/**
* Pure-PHP implementation of Blowfish.
*
* @package Crypt_Blowfish
* @package Blowfish
* @author Jim Wigginton <terrafrost@php.net>
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
* @access public
*/
class Crypt_Blowfish extends Crypt_Base
class Blowfish extends Base
{
/**
* Block Length of the cipher
*
* @see Crypt_Base::block_size
* @var Integer
* @see \phpseclib\Crypt\Base::block_size
* @var int
* @access private
*/
var $block_size = 8;
/**
* The default password key_size used by setPassword()
*
* @see Crypt_Base::password_key_size
* @see Crypt_Base::setPassword()
* @var Integer
* @access private
*/
var $password_key_size = 56;
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_Base::const_namespace
* @var String
* @access private
*/
var $const_namespace = 'BLOWFISH';
/**
* The mcrypt specific name of the cipher
*
* @see Crypt_Base::cipher_name_mcrypt
* @var String
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt
* @var string
* @access private
*/
var $cipher_name_mcrypt = 'blowfish';
@ -165,8 +68,8 @@ class Crypt_Blowfish extends Crypt_Base
/**
* Optimizing value while CFB-encrypting
*
* @see Crypt_Base::cfb_init_len
* @var Integer
* @see \phpseclib\Crypt\Base::cfb_init_len
* @var int
* @access private
*/
var $cfb_init_len = 500;
@ -174,12 +77,12 @@ class Crypt_Blowfish extends Crypt_Base
/**
* The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each
*
* S-Box 1
* S-Box 0
*
* @access private
* @var array
*/
var $sbox0 = array (
var $sbox0 = array(
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
@ -340,7 +243,7 @@ class Crypt_Blowfish extends Crypt_Base
/**
* P-Array consists of 18 32-bit subkeys
*
* @var array $parray
* @var array
* @access private
*/
var $parray = array(
@ -354,7 +257,7 @@ class Crypt_Blowfish extends Crypt_Base
*
* Holds the expanded key [p] and the key-depended s-boxes [sb]
*
* @var array $bctx
* @var array
* @access private
*/
var $bctx;
@ -362,43 +265,72 @@ class Crypt_Blowfish extends Crypt_Base
/**
* Holds the last used key
*
* @var Array
* @var array
* @access private
*/
var $kl;
/**
* Sets the key.
* The Key Length (in bytes)
*
* Keys can be of any length. Blowfish, itself, requires the use of a key between 32 and max. 448-bits long.
* If the key is less than 32-bits we NOT fill the key to 32bit but let the key as it is to be compatible
* with mcrypt because mcrypt act this way with blowfish key's < 32 bits.
* @see \phpseclib\Crypt\Base::setKeyLength()
* @var int
* @access private
* @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
* because the encryption / decryption / key schedule creation requires this number and not $key_length. We could
* derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
* of that, we'll just precompute it once.
*/
var $key_length = 16;
/**
* Sets the key length.
*
* If the key is more than 448-bits, we trim the excess bits.
*
* If the key is not explicitly set, or empty, it'll be assumed a 128 bits key to be all null bytes.
* Key lengths can be between 32 and 448 bits.
*
* @access public
* @see Crypt_Base::setKey()
* @param String $key
* @param int $length
*/
function setKey($key)
function setKeyLength($length)
{
$keylength = strlen($key);
if (!$keylength) {
$key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
} elseif ($keylength > 56) {
$key = substr($key, 0, 56);
if ($length < 32) {
$this->key_length = 7;
} elseif ($length > 448) {
$this->key_length = 56;
} else {
$this->key_length = $length >> 3;
}
parent::setKey($key);
parent::setKeyLength($length);
}
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
*
* @see \phpseclib\Crypt\Base::isValidEngine()
* @param int $engine
* @access public
* @return bool
*/
function isValidEngine($engine)
{
if ($engine == self::ENGINE_OPENSSL) {
if ($this->key_length != 16) {
return false;
}
$this->cipher_name_openssl_ecb = 'bf-ecb';
$this->cipher_name_openssl = 'bf-' . $this->_openssl_translate_mode();
}
return parent::isValidEngine($engine);
}
/**
* Setup the key (expansion)
*
* @see Crypt_Base::_setupKey()
* @see \phpseclib\Crypt\Base::_setupKey()
* @access private
*/
function _setupKey()
@ -455,8 +387,8 @@ class Crypt_Blowfish extends Crypt_Base
* Encrypts a block
*
* @access private
* @param String $in
* @return String
* @param string $in
* @return string
*/
function _encryptBlock($in)
{
@ -472,17 +404,17 @@ class Crypt_Blowfish extends Crypt_Base
$r = $in[2];
for ($i = 0; $i < 16; $i+= 2) {
$l^= $p[$i];
$r^= ($sb_0[$l >> 24 & 0xff] +
$sb_1[$l >> 16 & 0xff] ^
$sb_2[$l >> 8 & 0xff]) +
$sb_3[$l & 0xff];
$l^= $p[$i];
$r^= ($sb_0[$l >> 24 & 0xff] +
$sb_1[$l >> 16 & 0xff] ^
$sb_2[$l >> 8 & 0xff]) +
$sb_3[$l & 0xff];
$r^= $p[$i + 1];
$l^= ($sb_0[$r >> 24 & 0xff] +
$sb_1[$r >> 16 & 0xff] ^
$sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff];
$r^= $p[$i + 1];
$l^= ($sb_0[$r >> 24 & 0xff] +
$sb_1[$r >> 16 & 0xff] ^
$sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff];
}
return pack("N*", $r ^ $p[17], $l ^ $p[16]);
}
@ -491,8 +423,8 @@ class Crypt_Blowfish extends Crypt_Base
* Decrypts a block
*
* @access private
* @param String $in
* @return String
* @param string $in
* @return string
*/
function _decryptBlock($in)
{
@ -519,30 +451,28 @@ class Crypt_Blowfish extends Crypt_Base
$sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff];
}
return pack("N*", $r ^ $p[0], $l ^ $p[1]);
}
/**
* Setup the performance-optimized function for de/encrypt()
*
* @see Crypt_Base::_setupInlineCrypt()
* @see \phpseclib\Crypt\Base::_setupInlineCrypt()
* @access private
*/
function _setupInlineCrypt()
{
$lambda_functions =& Crypt_Blowfish::_getLambdaFunctions();
$lambda_functions =& self::_getLambdaFunctions();
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
// (Currently, for Blowfish, one generated $lambda_function cost on php5.5@32bit ~100kb unfreeable mem and ~180kb on php5.5@64bit)
// After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10);
$gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
switch (true) {
case $gen_hi_opt_code:
$code_hash = md5(str_pad("Crypt_Blowfish, {$this->mode}, ", 32, "\0") . $this->key);
break;
default:
$code_hash = "Crypt_Blowfish, {$this->mode}";
// Generation of a unique hash for our generated code
$code_hash = "Crypt_Blowfish, {$this->mode}";
if ($gen_hi_opt_code) {
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
}
if (!isset($lambda_functions[$code_hash])) {

View file

@ -5,7 +5,7 @@
*
* Uses mcrypt, if available, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
* PHP version 5
*
* Useful resources are as follows:
*
@ -16,9 +16,9 @@
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/DES.php';
* include 'vendor/autoload.php';
*
* $des = new Crypt_DES();
* $des = new \phpseclib\Crypt\DES();
*
* $des->setKey('abcdefgh');
*
@ -32,170 +32,87 @@
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_DES
* @package DES
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Base
*
* Base cipher class
*/
if (!class_exists('Crypt_Base')) {
include_once 'Base.php';
}
/**#@+
* @access private
* @see Crypt_DES::_setupKey()
* @see Crypt_DES::_processBlock()
*/
/**
* Contains $keys[CRYPT_DES_ENCRYPT]
*/
define('CRYPT_DES_ENCRYPT', 0);
/**
* Contains $keys[CRYPT_DES_DECRYPT]
*/
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', CRYPT_MODE_CTR);
/**
* 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', CRYPT_MODE_ECB);
/**
* 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', CRYPT_MODE_CBC);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/
define('CRYPT_DES_MODE_CFB', CRYPT_MODE_CFB);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/
define('CRYPT_DES_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/
/**#@+
* @access private
* @see Crypt_Base::Crypt_Base()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_DES_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_DES_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
namespace phpseclib\Crypt;
/**
* Pure-PHP implementation of DES.
*
* @package Crypt_DES
* @package DES
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Crypt_DES extends Crypt_Base
class DES extends Base
{
/**#@+
* @access private
* @see \phpseclib\Crypt\DES::_setupKey()
* @see \phpseclib\Crypt\DES::_processBlock()
*/
/**
* Contains $keys[self::ENCRYPT]
*/
const ENCRYPT = 0;
/**
* Contains $keys[self::DECRYPT]
*/
const DECRYPT = 1;
/**#@-*/
/**
* Block Length of the cipher
*
* @see Crypt_Base::block_size
* @var Integer
* @see \phpseclib\Crypt\Base::block_size
* @var int
* @access private
*/
var $block_size = 8;
/**
* The Key
* Key Length (in bytes)
*
* @see Crypt_Base::key
* @see setKey()
* @var String
* @see \phpseclib\Crypt\Base::setKeyLength()
* @var int
* @access private
*/
var $key = "\0\0\0\0\0\0\0\0";
/**
* The default password key_size used by setPassword()
*
* @see Crypt_Base::password_key_size
* @see Crypt_Base::setPassword()
* @var Integer
* @access private
*/
var $password_key_size = 8;
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_Base::const_namespace
* @var String
* @access private
*/
var $const_namespace = 'DES';
var $key_length = 8;
/**
* The mcrypt specific name of the cipher
*
* @see Crypt_Base::cipher_name_mcrypt
* @var String
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt
* @var string
* @access private
*/
var $cipher_name_mcrypt = 'des';
/**
* The OpenSSL names of the cipher / modes
*
* @see \phpseclib\Crypt\Base::openssl_mode_names
* @var array
* @access private
*/
var $openssl_mode_names = array(
self::MODE_ECB => 'des-ecb',
self::MODE_CBC => 'des-cbc',
self::MODE_CFB => 'des-cfb',
self::MODE_OFB => 'des-ofb'
// self::MODE_CTR is undefined for DES
);
/**
* Optimizing value while CFB-encrypting
*
* @see Crypt_Base::cfb_init_len
* @var Integer
* @see \phpseclib\Crypt\Base::cfb_init_len
* @var int
* @access private
*/
var $cfb_init_len = 500;
@ -203,11 +120,11 @@ class Crypt_DES extends Crypt_Base
/**
* Switch for DES/3DES encryption
*
* Used only if $engine == CRYPT_DES_MODE_INTERNAL
* Used only if $engine == self::ENGINE_INTERNAL
*
* @see Crypt_DES::_setupKey()
* @see Crypt_DES::_processBlock()
* @var Integer
* @see self::_setupKey()
* @see self::_processBlock()
* @var int
* @access private
*/
var $des_rounds = 1;
@ -215,17 +132,17 @@ class Crypt_DES extends Crypt_Base
/**
* max possible size of $key
*
* @see Crypt_DES::setKey()
* @var String
* @see self::setKey()
* @var string
* @access private
*/
var $key_size_max = 8;
var $key_length_max = 8;
/**
* The Key Schedule
*
* @see Crypt_DES::_setupKey()
* @var Array
* @see self::_setupKey()
* @var array
* @access private
*/
var $keys;
@ -237,9 +154,9 @@ class Crypt_DES extends Crypt_Base
* with each byte containing all bits in the same state as the
* corresponding bit in the index value.
*
* @see Crypt_DES::_processBlock()
* @see Crypt_DES::_setupKey()
* @var Array
* @see self::_processBlock()
* @see self::_setupKey()
* @var array
* @access private
*/
var $shuffle = array(
@ -378,7 +295,7 @@ class Crypt_DES extends Crypt_Base
*
* Indexing this table with each source byte performs the initial bit permutation.
*
* @var Array
* @var array
* @access private
*/
var $ipmap = array(
@ -420,7 +337,7 @@ class Crypt_DES extends Crypt_Base
* Inverse IP mapping helper table.
* Indexing this table with a byte value reverses the bit order.
*
* @var Array
* @var array
* @access private
*/
var $invipmap = array(
@ -464,7 +381,7 @@ class Crypt_DES extends Crypt_Base
* Each box ($sbox1-$sbox8) has been vectorized, then each value pre-permuted using the
* P table: concatenation can then be replaced by exclusive ORs.
*
* @var Array
* @var array
* @access private
*/
var $sbox1 = array(
@ -489,7 +406,7 @@ class Crypt_DES extends Crypt_Base
/**
* Pre-permuted S-box2
*
* @var Array
* @var array
* @access private
*/
var $sbox2 = array(
@ -514,7 +431,7 @@ class Crypt_DES extends Crypt_Base
/**
* Pre-permuted S-box3
*
* @var Array
* @var array
* @access private
*/
var $sbox3 = array(
@ -539,7 +456,7 @@ class Crypt_DES extends Crypt_Base
/**
* Pre-permuted S-box4
*
* @var Array
* @var array
* @access private
*/
var $sbox4 = array(
@ -564,7 +481,7 @@ class Crypt_DES extends Crypt_Base
/**
* Pre-permuted S-box5
*
* @var Array
* @var array
* @access private
*/
var $sbox5 = array(
@ -589,7 +506,7 @@ class Crypt_DES extends Crypt_Base
/**
* Pre-permuted S-box6
*
* @var Array
* @var array
* @access private
*/
var $sbox6 = array(
@ -614,7 +531,7 @@ class Crypt_DES extends Crypt_Base
/**
* Pre-permuted S-box7
*
* @var Array
* @var array
* @access private
*/
var $sbox7 = array(
@ -639,7 +556,7 @@ class Crypt_DES extends Crypt_Base
/**
* Pre-permuted S-box8
*
* @var Array
* @var array
* @access private
*/
var $sbox8 = array(
@ -661,6 +578,28 @@ class Crypt_DES extends Crypt_Base
0x00000820, 0x00020020, 0x08000000, 0x08020800
);
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
*
* @see \phpseclib\Crypt\Base::isValidEngine()
* @param int $engine
* @access public
* @return bool
*/
function isValidEngine($engine)
{
if ($this->key_length_max == 8) {
if ($engine == self::ENGINE_OPENSSL) {
$this->cipher_name_openssl_ecb = 'des-ecb';
$this->cipher_name_openssl = 'des-' . $this->_openssl_translate_mode();
}
}
return parent::isValidEngine($engine);
}
/**
* Sets the key.
*
@ -672,16 +611,16 @@ class Crypt_DES extends Crypt_Base
*
* If the key is not explicitly set, it'll be assumed to be all zero's.
*
* @see Crypt_Base::setKey()
* @see \phpseclib\Crypt\Base::setKey()
* @access public
* @param String $key
* @param string $key
*/
function setKey($key)
{
// We check/cut here only up to max length of the key.
// Key padding to the proper length will be done in _setupKey()
if (strlen($key) > $this->key_size_max) {
$key = substr($key, 0, $this->key_size_max);
if (strlen($key) > $this->key_length_max) {
$key = substr($key, 0, $this->key_length_max);
}
// Sets the key
@ -691,46 +630,46 @@ class Crypt_DES extends Crypt_Base
/**
* Encrypts a block
*
* @see Crypt_Base::_encryptBlock()
* @see Crypt_Base::encrypt()
* @see Crypt_DES::encrypt()
* @see \phpseclib\Crypt\Base::_encryptBlock()
* @see \phpseclib\Crypt\Base::encrypt()
* @see self::encrypt()
* @access private
* @param String $in
* @return String
* @param string $in
* @return string
*/
function _encryptBlock($in)
{
return $this->_processBlock($in, CRYPT_DES_ENCRYPT);
return $this->_processBlock($in, self::ENCRYPT);
}
/**
* Decrypts a block
*
* @see Crypt_Base::_decryptBlock()
* @see Crypt_Base::decrypt()
* @see Crypt_DES::decrypt()
* @see \phpseclib\Crypt\Base::_decryptBlock()
* @see \phpseclib\Crypt\Base::decrypt()
* @see self::decrypt()
* @access private
* @param String $in
* @return String
* @param string $in
* @return string
*/
function _decryptBlock($in)
{
return $this->_processBlock($in, CRYPT_DES_DECRYPT);
return $this->_processBlock($in, self::DECRYPT);
}
/**
* Encrypts or decrypts a 64-bit block
*
* $mode should be either CRYPT_DES_ENCRYPT or CRYPT_DES_DECRYPT. See
* $mode should be either self::ENCRYPT or self::DECRYPT. See
* {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general
* idea of what this function does.
*
* @see Crypt_DES::_encryptBlock()
* @see Crypt_DES::_decryptBlock()
* @see self::_encryptBlock()
* @see self::_decryptBlock()
* @access private
* @param String $block
* @param Integer $mode
* @return String
* @param string $block
* @param int $mode
* @return string
*/
function _processBlock($block, $mode)
{
@ -810,7 +749,7 @@ class Crypt_DES extends Crypt_Base
/**
* Creates the key schedule
*
* @see Crypt_Base::_setupKey()
* @see \phpseclib\Crypt\Base::_setupKey()
* @access private
*/
function _setupKey()
@ -1291,8 +1230,8 @@ class Crypt_DES extends Crypt_Base
$d = (($key['d'] >> 4) & 0x0FFFFFF0) | ($key['c'] & 0x0F);
$keys[$des_round] = array(
CRYPT_DES_ENCRYPT => array(),
CRYPT_DES_DECRYPT => array_fill(0, 32, 0)
self::ENCRYPT => array(),
self::DECRYPT => array_fill(0, 32, 0)
);
for ($i = 0, $ki = 31; $i < 16; ++$i, $ki-= 2) {
$c <<= $shifts[$i];
@ -1311,33 +1250,33 @@ class Crypt_DES extends Crypt_Base
(($dp >> 16) & 0x0000FF00) | (($dp >> 8) & 0x000000FF);
$val2 = (($cp << 8) & 0xFF000000) | (($cp << 16) & 0x00FF0000) |
(($dp >> 8) & 0x0000FF00) | ( $dp & 0x000000FF);
$keys[$des_round][CRYPT_DES_ENCRYPT][ ] = $val1;
$keys[$des_round][CRYPT_DES_DECRYPT][$ki - 1] = $val1;
$keys[$des_round][CRYPT_DES_ENCRYPT][ ] = $val2;
$keys[$des_round][CRYPT_DES_DECRYPT][$ki ] = $val2;
$keys[$des_round][self::ENCRYPT][ ] = $val1;
$keys[$des_round][self::DECRYPT][$ki - 1] = $val1;
$keys[$des_round][self::ENCRYPT][ ] = $val2;
$keys[$des_round][self::DECRYPT][$ki ] = $val2;
}
}
switch ($this->des_rounds) {
case 3: // 3DES keys
$this->keys = array(
CRYPT_DES_ENCRYPT => array_merge(
$keys[0][CRYPT_DES_ENCRYPT],
$keys[1][CRYPT_DES_DECRYPT],
$keys[2][CRYPT_DES_ENCRYPT]
self::ENCRYPT => array_merge(
$keys[0][self::ENCRYPT],
$keys[1][self::DECRYPT],
$keys[2][self::ENCRYPT]
),
CRYPT_DES_DECRYPT => array_merge(
$keys[2][CRYPT_DES_DECRYPT],
$keys[1][CRYPT_DES_ENCRYPT],
$keys[0][CRYPT_DES_DECRYPT]
self::DECRYPT => array_merge(
$keys[2][self::DECRYPT],
$keys[1][self::ENCRYPT],
$keys[0][self::DECRYPT]
)
);
break;
// case 1: // DES keys
default:
$this->keys = array(
CRYPT_DES_ENCRYPT => $keys[0][CRYPT_DES_ENCRYPT],
CRYPT_DES_DECRYPT => $keys[0][CRYPT_DES_DECRYPT]
self::ENCRYPT => $keys[0][self::ENCRYPT],
self::DECRYPT => $keys[0][self::DECRYPT]
);
}
}
@ -1345,12 +1284,12 @@ class Crypt_DES extends Crypt_Base
/**
* Setup the performance-optimized function for de/encrypt()
*
* @see Crypt_Base::_setupInlineCrypt()
* @see \phpseclib\Crypt\Base::_setupInlineCrypt()
* @access private
*/
function _setupInlineCrypt()
{
$lambda_functions =& Crypt_DES::_getLambdaFunctions();
$lambda_functions =& self::_getLambdaFunctions();
// Engine configuration for:
// - DES ($des_rounds == 1) or
@ -1358,21 +1297,20 @@ class Crypt_DES extends Crypt_Base
$des_rounds = $this->des_rounds;
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
// (Currently, for DES, one generated $lambda_function cost on php5.5@32bit ~135kb unfreeable mem and ~230kb on php5.5@64bit)
// (Currently, for TripleDES, one generated $lambda_function cost on php5.5@32bit ~240kb unfreeable mem and ~340kb on php5.5@64bit)
// After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
// Generation of a uniqe hash for our generated code
switch (true) {
case $gen_hi_opt_code:
// For hi-optimized code, we create for each combination of
// $mode, $des_rounds and $this->key its own encrypt/decrypt function.
$code_hash = md5(str_pad("Crypt_DES, $des_rounds, {$this->mode}, ", 32, "\0") . $this->key);
break;
default:
// After max 10 hi-optimized functions, we create generic
// (still very fast.. but not ultra) functions for each $mode/$des_rounds
// Currently 2 * 5 generic functions will be then max. possible.
$code_hash = "Crypt_DES, $des_rounds, {$this->mode}";
// Generation of a unique hash for our generated code
$code_hash = "Crypt_DES, $des_rounds, {$this->mode}";
if ($gen_hi_opt_code) {
// For hi-optimized code, we create for each combination of
// $mode, $des_rounds and $this->key its own encrypt/decrypt function.
// After max 10 hi-optimized functions, we create generic
// (still very fast.. but not ultra) functions for each $mode/$des_rounds
// Currently 2 * 5 generic functions will be then max. possible.
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
}
// Is there a re-usable $lambda_functions in there? If not, we have to create it.
@ -1402,8 +1340,8 @@ class Crypt_DES extends Crypt_Base
// No futher initialisation of the $keys schedule is necessary.
// That is the extra performance boost.
$k = array(
CRYPT_DES_ENCRYPT => $this->keys[CRYPT_DES_ENCRYPT],
CRYPT_DES_DECRYPT => $this->keys[CRYPT_DES_DECRYPT]
self::ENCRYPT => $this->keys[self::ENCRYPT],
self::DECRYPT => $this->keys[self::DECRYPT]
);
$init_encrypt = '';
$init_decrypt = '';
@ -1412,22 +1350,21 @@ class Crypt_DES extends Crypt_Base
// In generic optimized code mode, we have to use, as the best compromise [currently],
// our key schedule as $ke/$kd arrays. (with hardcoded indexes...)
$k = array(
CRYPT_DES_ENCRYPT => array(),
CRYPT_DES_DECRYPT => array()
self::ENCRYPT => array(),
self::DECRYPT => array()
);
for ($i = 0, $c = count($this->keys[CRYPT_DES_ENCRYPT]); $i < $c; ++$i) {
$k[CRYPT_DES_ENCRYPT][$i] = '$ke[' . $i . ']';
$k[CRYPT_DES_DECRYPT][$i] = '$kd[' . $i . ']';
for ($i = 0, $c = count($this->keys[self::ENCRYPT]); $i < $c; ++$i) {
$k[self::ENCRYPT][$i] = '$ke[' . $i . ']';
$k[self::DECRYPT][$i] = '$kd[' . $i . ']';
}
$init_encrypt = '$ke = $self->keys[CRYPT_DES_ENCRYPT];';
$init_decrypt = '$kd = $self->keys[CRYPT_DES_DECRYPT];';
$init_encrypt = '$ke = $self->keys[self::ENCRYPT];';
$init_decrypt = '$kd = $self->keys[self::DECRYPT];';
break;
}
// Creating code for en- and decryption.
$crypt_block = array();
foreach (array(CRYPT_DES_ENCRYPT, CRYPT_DES_DECRYPT) as $c) {
foreach (array(self::ENCRYPT, self::DECRYPT) as $c) {
/* Do the initial IP permutation. */
$crypt_block[$c] = '
$in = unpack("N*", $in);
@ -1494,8 +1431,8 @@ class Crypt_DES extends Crypt_Base
'init_crypt' => $init_crypt,
'init_encrypt' => $init_encrypt,
'init_decrypt' => $init_decrypt,
'encrypt_block' => $crypt_block[CRYPT_DES_ENCRYPT],
'decrypt_block' => $crypt_block[CRYPT_DES_DECRYPT]
'encrypt_block' => $crypt_block[self::ENCRYPT],
'decrypt_block' => $crypt_block[self::DECRYPT]
)
);
}

View file

@ -7,10 +7,10 @@
*
* md2, md5, md5-96, sha1, sha1-96, sha256, sha256-96, sha384, and sha512, sha512-96
*
* If {@link Crypt_Hash::setKey() setKey()} is called, {@link Crypt_Hash::hash() hash()} will return the HMAC as opposed to
* If {@link self::setKey() setKey()} is called, {@link self::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
* PHP version 5
*
* {@internal The variable names are the same as those in
* {@link http://tools.ietf.org/html/rfc2104#section-2 RFC2104}.}}
@ -18,9 +18,9 @@
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/Hash.php';
* include 'vendor/autoload.php';
*
* $hash = new Crypt_Hash('sha1');
* $hash = new \phpseclib\Crypt\Hash('sha1');
*
* $hash->setKey('abcdefg');
*
@ -28,64 +28,50 @@
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_Hash
* @package Hash
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @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);
/**#@-*/
namespace phpseclib\Crypt;
use phpseclib\Math\BigInteger;
/**
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
*
* @package Crypt_Hash
* @package Hash
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Crypt_Hash
class Hash
{
/**#@+
* @access private
* @see \phpseclib\Crypt\Hash::__construct()
*/
/**
* Toggles the internal implementation
*/
const MODE_INTERNAL = 1;
/**
* Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+.
*/
const MODE_MHASH = 2;
/**
* Toggles the hash() implementation, which works on PHP 5.1.2+.
*/
const MODE_HASH = 3;
/**#@-*/
/**
* Hash Parameter
*
* @see Crypt_Hash::setHash()
* @var Integer
* @see self::setHash()
* @var int
* @access private
*/
var $hashParam;
@ -93,8 +79,8 @@ class Crypt_Hash
/**
* Byte-length of compression blocks / key (Internal HMAC)
*
* @see Crypt_Hash::setAlgorithm()
* @var Integer
* @see self::setAlgorithm()
* @var int
* @access private
*/
var $b;
@ -102,8 +88,8 @@ class Crypt_Hash
/**
* Byte-length of hash output (Internal HMAC)
*
* @see Crypt_Hash::setHash()
* @var Integer
* @see self::setHash()
* @var int
* @access private
*/
var $l = false;
@ -111,8 +97,8 @@ class Crypt_Hash
/**
* Hash Algorithm
*
* @see Crypt_Hash::setHash()
* @var String
* @see self::setHash()
* @var string
* @access private
*/
var $hash;
@ -120,8 +106,8 @@ class Crypt_Hash
/**
* Key
*
* @see Crypt_Hash::setKey()
* @var String
* @see self::setKey()
* @var string
* @access private
*/
var $key = false;
@ -129,8 +115,8 @@ class Crypt_Hash
/**
* Outer XOR (Internal HMAC)
*
* @see Crypt_Hash::setKey()
* @var String
* @see self::setKey()
* @var string
* @access private
*/
var $opad;
@ -138,8 +124,8 @@ class Crypt_Hash
/**
* Inner XOR (Internal HMAC)
*
* @see Crypt_Hash::setKey()
* @var String
* @see self::setKey()
* @var string
* @access private
*/
var $ipad;
@ -147,22 +133,22 @@ class Crypt_Hash
/**
* Default Constructor.
*
* @param optional String $hash
* @return Crypt_Hash
* @param string $hash
* @return \phpseclib\Crypt\Hash
* @access public
*/
function Crypt_Hash($hash = 'sha1')
function __construct($hash = 'sha1')
{
if ( !defined('CRYPT_HASH_MODE') ) {
if (!defined('CRYPT_HASH_MODE')) {
switch (true) {
case extension_loaded('hash'):
define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH);
define('CRYPT_HASH_MODE', self::MODE_HASH);
break;
case extension_loaded('mhash'):
define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_MHASH);
define('CRYPT_HASH_MODE', self::MODE_MHASH);
break;
default:
define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_INTERNAL);
define('CRYPT_HASH_MODE', self::MODE_INTERNAL);
}
}
@ -175,7 +161,7 @@ class Crypt_Hash
* Keys can be of any length.
*
* @access public
* @param optional String $key
* @param string $key
*/
function setKey($key = false)
{
@ -188,7 +174,7 @@ class Crypt_Hash
* As set by the constructor or by the setHash() method.
*
* @access public
* @return String
* @return string
*/
function getHash()
{
@ -199,7 +185,7 @@ class Crypt_Hash
* Sets the hash function.
*
* @access public
* @param String $hash
* @param string $hash
*/
function setHash($hash)
{
@ -231,19 +217,19 @@ class Crypt_Hash
switch ($hash) {
case 'md2':
$mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_HASH && in_array('md2', hash_algos()) ?
CRYPT_HASH_MODE_HASH : CRYPT_HASH_MODE_INTERNAL;
$mode = CRYPT_HASH_MODE == self::MODE_HASH && in_array('md2', hash_algos()) ?
self::MODE_HASH : self::MODE_INTERNAL;
break;
case 'sha384':
case 'sha512':
$mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_MHASH ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
$mode = CRYPT_HASH_MODE == self::MODE_MHASH ? self::MODE_INTERNAL : CRYPT_HASH_MODE;
break;
default:
$mode = CRYPT_HASH_MODE;
}
switch ( $mode ) {
case CRYPT_HASH_MODE_MHASH:
switch ($mode) {
case self::MODE_MHASH:
switch ($hash) {
case 'md5':
$this->hash = MHASH_MD5;
@ -256,7 +242,7 @@ class Crypt_Hash
$this->hash = MHASH_SHA1;
}
return;
case CRYPT_HASH_MODE_HASH:
case self::MODE_HASH:
switch ($hash) {
case 'md5':
$this->hash = 'md5';
@ -276,26 +262,26 @@ class Crypt_Hash
switch ($hash) {
case 'md2':
$this->b = 16;
$this->hash = array($this, '_md2');
break;
$this->b = 16;
$this->hash = array($this, '_md2');
break;
case 'md5':
$this->b = 64;
$this->hash = array($this, '_md5');
break;
$this->b = 64;
$this->hash = array($this, '_md5');
break;
case 'sha256':
$this->b = 64;
$this->hash = array($this, '_sha256');
break;
$this->b = 64;
$this->hash = array($this, '_sha256');
break;
case 'sha384':
case 'sha512':
$this->b = 128;
$this->hash = array($this, '_sha512');
break;
$this->b = 128;
$this->hash = array($this, '_sha512');
break;
case 'sha1':
default:
$this->b = 64;
$this->hash = array($this, '_sha1');
$this->b = 64;
$this->hash = array($this, '_sha1');
}
$this->ipad = str_repeat(chr(0x36), $this->b);
@ -306,22 +292,22 @@ class Crypt_Hash
* Compute the HMAC.
*
* @access public
* @param String $text
* @return String
* @param string $text
* @return string
*/
function hash($text)
{
$mode = is_array($this->hash) ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
$mode = is_array($this->hash) ? self::MODE_INTERNAL : CRYPT_HASH_MODE;
if (!empty($this->key) || is_string($this->key)) {
switch ( $mode ) {
case CRYPT_HASH_MODE_MHASH:
switch ($mode) {
case self::MODE_MHASH:
$output = mhash($this->hash, $text, $this->key);
break;
case CRYPT_HASH_MODE_HASH:
case self::MODE_HASH:
$output = hash_hmac($this->hash, $text, $this->key, true);
break;
case CRYPT_HASH_MODE_INTERNAL:
case self::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."
@ -337,14 +323,14 @@ class Crypt_Hash
$output = call_user_func($this->hash, $output); // step 7
}
} else {
switch ( $mode ) {
case CRYPT_HASH_MODE_MHASH:
switch ($mode) {
case self::MODE_MHASH:
$output = mhash($this->hash, $text);
break;
case CRYPT_HASH_MODE_HASH:
case self::MODE_HASH:
$output = hash($this->hash, $text, true);
break;
case CRYPT_HASH_MODE_INTERNAL:
case self::MODE_INTERNAL:
$output = call_user_func($this->hash, $text);
}
}
@ -356,7 +342,7 @@ class Crypt_Hash
* Returns the hash length (in bytes)
*
* @access public
* @return Integer
* @return int
*/
function getLength()
{
@ -367,7 +353,7 @@ class Crypt_Hash
* Wrapper for MD5
*
* @access private
* @param String $m
* @param string $m
*/
function _md5($m)
{
@ -378,7 +364,7 @@ class Crypt_Hash
* Wrapper for SHA1
*
* @access private
* @param String $m
* @param string $m
*/
function _sha1($m)
{
@ -391,7 +377,7 @@ class Crypt_Hash
* See {@link http://tools.ietf.org/html/rfc1319 RFC1319}.
*
* @access private
* @param String $m
* @param string $m
*/
function _md2($m)
{
@ -467,7 +453,7 @@ class Crypt_Hash
* 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 $m
* @param string $m
*/
function _sha256($m)
{
@ -511,14 +497,15 @@ class Crypt_Hash
// Extend the sixteen 32-bit words into sixty-four 32-bit words
for ($i = 16; $i < 64; $i++) {
// @codingStandardsIgnoreStart
$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);
// @codingStandardsIgnoreEnd
$w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1);
}
// Initialize hash value for this chunk
@ -572,14 +559,10 @@ class Crypt_Hash
* Pure-PHP implementation of SHA384 and SHA512
*
* @access private
* @param String $m
* @param string $m
*/
function _sha512($m)
{
if (!class_exists('Math_BigInteger')) {
include_once 'Math/BigInteger.php';
}
static $init384, $init512, $k;
if (!isset($k)) {
@ -594,9 +577,9 @@ class Crypt_Hash
);
for ($i = 0; $i < 8; $i++) {
$init384[$i] = new Math_BigInteger($init384[$i], 16);
$init384[$i] = new BigInteger($init384[$i], 16);
$init384[$i]->setPrecision(64);
$init512[$i] = new Math_BigInteger($init512[$i], 16);
$init512[$i] = new BigInteger($init512[$i], 16);
$init512[$i]->setPrecision(64);
}
@ -626,7 +609,7 @@ class Crypt_Hash
);
for ($i = 0; $i < 80; $i++) {
$k[$i] = new Math_BigInteger($k[$i], 16);
$k[$i] = new BigInteger($k[$i], 16);
}
}
@ -645,7 +628,7 @@ class Crypt_Hash
foreach ($chunks as $chunk) {
$w = array();
for ($i = 0; $i < 16; $i++) {
$temp = new Math_BigInteger($this->_string_shift($chunk, 8), 256);
$temp = new BigInteger($this->_string_shift($chunk, 8), 256);
$temp->setPrecision(64);
$w[] = $temp;
}
@ -741,7 +724,7 @@ class Crypt_Hash
}
// 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)
// (\phpseclib\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) {
@ -755,10 +738,10 @@ class Crypt_Hash
* Right Rotate
*
* @access private
* @param Integer $int
* @param Integer $amt
* @see _sha256()
* @return Integer
* @param int $int
* @param int $amt
* @see self::_sha256()
* @return int
*/
function _rightRotate($int, $amt)
{
@ -771,10 +754,10 @@ class Crypt_Hash
* Right Shift
*
* @access private
* @param Integer $int
* @param Integer $amt
* @see _sha256()
* @return Integer
* @param int $int
* @param int $amt
* @see self::_sha256()
* @return int
*/
function _rightShift($int, $amt)
{
@ -786,9 +769,9 @@ class Crypt_Hash
* Not
*
* @access private
* @param Integer $int
* @see _sha256()
* @return Integer
* @param int $int
* @see self::_sha256()
* @return int
*/
function _not($int)
{
@ -799,11 +782,11 @@ class Crypt_Hash
* 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.
* possibility of overflow exists, care has to be taken. BigInteger could be used but this should be faster.
*
* @param Integer $...
* @return Integer
* @see _sha256()
* @param int $...
* @return int
* @see self::_sha256()
* @access private
*/
function _add()
@ -827,9 +810,9 @@ class Crypt_Hash
*
* Inspired by array_shift
*
* @param String $string
* @param optional Integer $index
* @return String
* @param string $string
* @param int $index
* @return string
* @access private
*/
function _string_shift(&$string, $index = 1)

View file

@ -5,7 +5,7 @@
*
* Uses mcrypt, if available, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
* PHP version 5
*
* Useful resources are as follows:
*
@ -14,9 +14,9 @@
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/RC2.php';
* include 'vendor/autoload.php';
*
* $rc2 = new Crypt_RC2();
* $rc2 = new \phpseclib\Crypt\RC2();
*
* $rc2->setKey('abcdefgh');
*
@ -26,106 +26,28 @@
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_RC2
* @package RC2
* @author Patrick Monnerat <pm@datasphere.ch>
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Base
*
* Base cipher class
*/
if (!class_exists('Crypt_Base')) {
include_once 'Base.php';
}
/**#@+
* @access public
* @see Crypt_RC2::encrypt()
* @see Crypt_RC2::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_RC2_MODE_CTR', CRYPT_MODE_CTR);
/**
* 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_RC2_MODE_ECB', CRYPT_MODE_ECB);
/**
* 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_RC2_MODE_CBC', CRYPT_MODE_CBC);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/
define('CRYPT_RC2_MODE_CFB', CRYPT_MODE_CFB);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/
define('CRYPT_RC2_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/
/**#@+
* @access private
* @see Crypt_RC2::Crypt_RC2()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_RC2_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_RC2_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
namespace phpseclib\Crypt;
/**
* Pure-PHP implementation of RC2.
*
* @package Crypt_RC2
* @package RC2
* @access public
*/
class Crypt_RC2 extends Crypt_Base
class RC2 extends Base
{
/**
* Block Length of the cipher
*
* @see Crypt_Base::block_size
* @var Integer
* @see \phpseclib\Crypt\Base::block_size
* @var int
* @access private
*/
var $block_size = 8;
@ -133,37 +55,48 @@ class Crypt_RC2 extends Crypt_Base
/**
* The Key
*
* @see Crypt_Base::key
* @see setKey()
* @var String
* @see \phpseclib\Crypt\Base::key
* @see self::setKey()
* @var string
* @access private
*/
var $key = "\0";
var $key;
/**
* The default password key_size used by setPassword()
* The Original (unpadded) Key
*
* @see Crypt_Base::password_key_size
* @see Crypt_Base::setPassword()
* @var Integer
* @see \phpseclib\Crypt\Base::key
* @see self::setKey()
* @see self::encrypt()
* @see self::decrypt()
* @var string
* @access private
*/
var $password_key_size = 16; // = 128 bits
var $orig_key;
/**
* The namespace used by the cipher for its constants.
* Don't truncate / null pad key
*
* @see Crypt_Base::const_namespace
* @var String
* @see \phpseclib\Crypt\Base::_clearBuffers()
* @var bool
* @access private
*/
var $const_namespace = 'RC2';
var $skip_key_adjustment = true;
/**
* Key Length (in bytes)
*
* @see \phpseclib\Crypt\RC2::setKeyLength()
* @var int
* @access private
*/
var $key_length = 16; // = 128 bits
/**
* The mcrypt specific name of the cipher
*
* @see Crypt_Base::cipher_name_mcrypt
* @var String
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt
* @var string
* @access private
*/
var $cipher_name_mcrypt = 'rc2';
@ -171,8 +104,8 @@ class Crypt_RC2 extends Crypt_Base
/**
* Optimizing value while CFB-encrypting
*
* @see Crypt_Base::cfb_init_len
* @var Integer
* @see \phpseclib\Crypt\Base::cfb_init_len
* @var int
* @access private
*/
var $cfb_init_len = 500;
@ -180,20 +113,31 @@ class Crypt_RC2 extends Crypt_Base
/**
* The key length in bits.
*
* @see Crypt_RC2::setKeyLength()
* @see Crypt_RC2::setKey()
* @var Integer
* @see self::setKeyLength()
* @see self::setKey()
* @var int
* @access private
* @internal Should be in range [1..1024].
* @internal Changing this value after setting the key has no effect.
*/
var $default_key_length = 1024;
/**
* The key length in bits.
*
* @see self::isValidEnine()
* @see self::setKey()
* @var int
* @access private
* @internal Should be in range [1..1024].
*/
var $current_key_length;
/**
* The Key Schedule
*
* @see Crypt_RC2::_setupKey()
* @var Array
* @see self::_setupKey()
* @var array
* @access private
*/
var $keys;
@ -202,8 +146,8 @@ class Crypt_RC2 extends Crypt_Base
* Key expansion randomization table.
* Twice the same 256-value sequence to save a modulus in key expansion.
*
* @see Crypt_RC2::setKey()
* @var Array
* @see self::setKey()
* @var array
* @access private
*/
var $pitable = array(
@ -276,8 +220,8 @@ class Crypt_RC2 extends Crypt_Base
/**
* Inverse key expansion randomization table.
*
* @see Crypt_RC2::setKey()
* @var Array
* @see self::setKey()
* @var array
* @access private
*/
var $invpitable = array(
@ -316,55 +260,68 @@ class Crypt_RC2 extends Crypt_Base
);
/**
* Default Constructor.
* Test for engine validity
*
* Determines whether or not the mcrypt extension should be used.
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
*
* $mode could be:
*
* - CRYPT_RC2_MODE_ECB
*
* - CRYPT_RC2_MODE_CBC
*
* - CRYPT_RC2_MODE_CTR
*
* - CRYPT_RC2_MODE_CFB
*
* - CRYPT_RC2_MODE_OFB
*
* If not explicitly set, CRYPT_RC2_MODE_CBC will be used.
*
* @see Crypt_Base::Crypt_Base()
* @param optional Integer $mode
* @see \phpseclib\Crypt\Base::__construct()
* @param int $engine
* @access public
* @return bool
*/
function Crypt_RC2($mode = CRYPT_RC2_MODE_CBC)
function isValidEngine($engine)
{
parent::Crypt_Base($mode);
$this->setKey('');
switch ($engine) {
case self::ENGINE_OPENSSL:
if ($this->current_key_length != 128 || strlen($this->orig_key) < 16) {
return false;
}
$this->cipher_name_openssl_ecb = 'rc2-ecb';
$this->cipher_name_openssl = 'rc2-' . $this->_openssl_translate_mode();
}
return parent::isValidEngine($engine);
}
/**
* Sets the key length
* Sets the key length.
*
* Valid key lengths are 1 to 1024.
* Valid key lengths are 8 to 1024.
* Calling this function after setting the key has no effect until the next
* Crypt_RC2::setKey() call.
* \phpseclib\Crypt\RC2::setKey() call.
*
* @access public
* @param Integer $length in bits
* @param int $length in bits
*/
function setKeyLength($length)
{
if ($length >= 1 && $length <= 1024) {
if ($length < 8) {
$this->default_key_length = 8;
} elseif ($length > 1024) {
$this->default_key_length = 128;
} else {
$this->default_key_length = $length;
}
$this->current_key_length = $this->default_key_length;
parent::setKeyLength($length);
}
/**
* Returns the current key length
*
* @access public
* @return int
*/
function getKeyLength()
{
return $this->current_key_length;
}
/**
* Sets the key.
*
* Keys can be of any length. RC2, itself, uses 1 to 1024 bit keys (eg.
* Keys can be of any length. RC2, itself, uses 8 to 1024 bit keys (eg.
* strlen($key) <= 128), however, we only use the first 128 bytes if $key
* has more then 128 bytes in it, and set $key to a single null byte if
* it is empty.
@ -372,18 +329,21 @@ class Crypt_RC2 extends Crypt_Base
* If the key is not explicitly set, it'll be assumed to be a single
* null byte.
*
* @see Crypt_Base::setKey()
* @see \phpseclib\Crypt\Base::setKey()
* @access public
* @param String $key
* @param Integer $t1 optional Effective key length in bits.
* @param string $key
* @param int $t1 optional Effective key length in bits.
*/
function setKey($key, $t1 = 0)
{
$this->orig_key = $key;
if ($t1 <= 0) {
$t1 = $this->default_key_length;
} else if ($t1 > 1024) {
} elseif ($t1 > 1024) {
$t1 = 1024;
}
$this->current_key_length = $t1;
// Key byte count should be 1..128.
$key = strlen($key) ? substr($key, 0, 128) : "\x00";
$t = strlen($key);
@ -413,17 +373,64 @@ class Crypt_RC2 extends Crypt_Base
// Prepare the key for mcrypt.
$l[0] = $this->invpitable[$l[0]];
array_unshift($l, 'C*');
parent::setKey(call_user_func_array('pack', $l));
}
/**
* Encrypts a message.
*
* Mostly a wrapper for \phpseclib\Crypt\Base::encrypt, with some additional OpenSSL handling code
*
* @see self::decrypt()
* @access public
* @param string $plaintext
* @return string $ciphertext
*/
function encrypt($plaintext)
{
if ($this->engine == self::ENGINE_OPENSSL) {
$temp = $this->key;
$this->key = $this->orig_key;
$result = parent::encrypt($plaintext);
$this->key = $temp;
return $result;
}
return parent::encrypt($plaintext);
}
/**
* Decrypts a message.
*
* Mostly a wrapper for \phpseclib\Crypt\Base::decrypt, with some additional OpenSSL handling code
*
* @see self::encrypt()
* @access public
* @param string $ciphertext
* @return string $plaintext
*/
function decrypt($ciphertext)
{
if ($this->engine == self::ENGINE_OPENSSL) {
$temp = $this->key;
$this->key = $this->orig_key;
$result = parent::decrypt($ciphertext);
$this->key = $temp;
return $result;
}
return parent::decrypt($ciphertext);
}
/**
* Encrypts a block
*
* @see Crypt_Base::_encryptBlock()
* @see Crypt_Base::encrypt()
* @see \phpseclib\Crypt\Base::_encryptBlock()
* @see \phpseclib\Crypt\Base::encrypt()
* @access private
* @param String $in
* @return String
* @param string $in
* @return string
*/
function _encryptBlock($in)
{
@ -464,11 +471,11 @@ class Crypt_RC2 extends Crypt_Base
/**
* Decrypts a block
*
* @see Crypt_Base::_decryptBlock()
* @see Crypt_Base::decrypt()
* @see \phpseclib\Crypt\Base::_decryptBlock()
* @see \phpseclib\Crypt\Base::decrypt()
* @access private
* @param String $in
* @return String
* @param string $in
* @return string
*/
function _decryptBlock($in)
{
@ -506,15 +513,34 @@ class Crypt_RC2 extends Crypt_Base
return pack('vvvv', $r0, $r1, $r2, $r3);
}
/**
* Setup the \phpseclib\Crypt\Base::ENGINE_MCRYPT $engine
*
* @see \phpseclib\Crypt\Base::_setupMcrypt()
* @access private
*/
function _setupMcrypt()
{
if (!isset($this->key)) {
$this->setKey('');
}
parent::_setupMcrypt();
}
/**
* Creates the key schedule
*
* @see Crypt_Base::_setupKey()
* @see \phpseclib\Crypt\Base::_setupKey()
* @access private
*/
function _setupKey()
{
// Key has already been expanded in Crypt_RC2::setKey():
if (!isset($this->key)) {
$this->setKey('');
}
// Key has already been expanded in \phpseclib\Crypt\RC2::setKey():
// Only the first value must be altered.
$l = unpack('Ca/Cb/v*', $this->key);
array_unshift($l, $this->pitable[$l['a']] | ($l['b'] << 8));
@ -526,24 +552,24 @@ class Crypt_RC2 extends Crypt_Base
/**
* Setup the performance-optimized function for de/encrypt()
*
* @see Crypt_Base::_setupInlineCrypt()
* @see \phpseclib\Crypt\Base::_setupInlineCrypt()
* @access private
*/
function _setupInlineCrypt()
{
$lambda_functions = &Crypt_RC2::_getLambdaFunctions();
$lambda_functions =& self::_getLambdaFunctions();
// The first 10 generated $lambda_functions will use the $keys hardcoded as integers
// for the mixing rounds, for better inline crypt performance [~20% faster].
// But for memory reason we have to limit those ultra-optimized $lambda_functions to an amount of 10.
$keys = $this->keys;
if (count($lambda_functions) >= 10) {
foreach ($this->keys as $k => $v) {
$keys[$k] = '$keys[' . $k . ']';
}
}
// (Currently, for Crypt_RC2, one generated $lambda_function cost on php5.5@32bit ~60kb unfreeable mem and ~100kb on php5.5@64bit)
$gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
$code_hash = md5(str_pad("Crypt_RC2, {$this->mode}, ", 32, "\0") . implode(',', $keys));
// Generation of a unique hash for our generated code
$code_hash = "Crypt_RC2, {$this->mode}";
if ($gen_hi_opt_code) {
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
}
// Is there a re-usable $lambda_functions in there?
// If not, we have to create it.
@ -551,6 +577,16 @@ class Crypt_RC2 extends Crypt_Base
// Init code for both, encrypt and decrypt.
$init_crypt = '$keys = $self->keys;';
switch (true) {
case $gen_hi_opt_code:
$keys = $this->keys;
default:
$keys = array();
foreach ($this->keys as $k => $v) {
$keys[$k] = '$keys[' . $k . ']';
}
}
// $in is the current 8 bytes block which has to be en/decrypt
$encrypt_block = $decrypt_block = '
$in = unpack("v4", $in);

View file

@ -5,7 +5,7 @@
*
* Uses mcrypt, if available, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
* PHP version 5
*
* Useful resources are as follows:
*
@ -18,9 +18,9 @@
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/RC4.php';
* include 'vendor/autoload.php';
*
* $rc4 = new Crypt_RC4();
* $rc4 = new \phpseclib\Crypt\RC4();
*
* $rc4->setKey('abcdefgh');
*
@ -34,108 +34,59 @@
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_RC4
* @package RC4
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Base
*
* Base cipher class
*/
if (!class_exists('Crypt_Base')) {
include_once 'Base.php';
}
/**#@+
* @access private
* @see Crypt_RC4::Crypt_RC4()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_RC4_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_RC4_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
/**#@+
* @access private
* @see Crypt_RC4::_crypt()
*/
define('CRYPT_RC4_ENCRYPT', 0);
define('CRYPT_RC4_DECRYPT', 1);
/**#@-*/
namespace phpseclib\Crypt;
/**
* Pure-PHP implementation of RC4.
*
* @package Crypt_RC4
* @package RC4
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Crypt_RC4 extends Crypt_Base
class RC4 extends Base
{
/**#@+
* @access private
* @see \phpseclib\Crypt\RC4::_crypt()
*/
const ENCRYPT = 0;
const DECRYPT = 1;
/**#@-*/
/**
* Block Length of the cipher
*
* RC4 is a stream cipher
* so we the block_size to 0
*
* @see Crypt_Base::block_size
* @var Integer
* @see \phpseclib\Crypt\Base::block_size
* @var int
* @access private
*/
var $block_size = 0;
/**
* The default password key_size used by setPassword()
* Key Length (in bytes)
*
* @see Crypt_Base::password_key_size
* @see Crypt_Base::setPassword()
* @var Integer
* @see \phpseclib\Crypt\RC4::setKeyLength()
* @var int
* @access private
*/
var $password_key_size = 128; // = 1024 bits
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_Base::const_namespace
* @var String
* @access private
*/
var $const_namespace = 'RC4';
var $key_length = 128; // = 1024 bits
/**
* The mcrypt specific name of the cipher
*
* @see Crypt_Base::cipher_name_mcrypt
* @var String
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt
* @var string
* @access private
*/
var $cipher_name_mcrypt = 'arcfour';
@ -143,7 +94,7 @@ class Crypt_RC4 extends Crypt_Base
/**
* Holds whether performance-optimized $inline_crypt() can/should be used.
*
* @see Crypt_Base::inline_crypt
* @see \phpseclib\Crypt\Base::inline_crypt
* @var mixed
* @access private
*/
@ -152,8 +103,8 @@ class Crypt_RC4 extends Crypt_Base
/**
* The Key
*
* @see Crypt_RC4::setKey()
* @var String
* @see self::setKey()
* @var string
* @access private
*/
var $key = "\0";
@ -161,8 +112,8 @@ class Crypt_RC4 extends Crypt_Base
/**
* The Key Stream for decryption and encryption
*
* @see Crypt_RC4::setKey()
* @var Array
* @see self::setKey()
* @var array
* @access private
*/
var $stream;
@ -172,13 +123,45 @@ class Crypt_RC4 extends Crypt_Base
*
* Determines whether or not the mcrypt extension should be used.
*
* @see Crypt_Base::Crypt_Base()
* @return Crypt_RC4
* @see \phpseclib\Crypt\Base::__construct()
* @return \phpseclib\Crypt\RC4
* @access public
*/
function Crypt_RC4()
function __construct()
{
parent::Crypt_Base(CRYPT_MODE_STREAM);
parent::__construct(Base::MODE_STREAM);
}
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
*
* @see \phpseclib\Crypt\Base::__construct()
* @param int $engine
* @access public
* @return bool
*/
function isValidEngine($engine)
{
switch ($engine) {
case Base::ENGINE_OPENSSL:
switch (strlen($this->key)) {
case 5:
$this->cipher_name_openssl = 'rc4-40';
break;
case 8:
$this->cipher_name_openssl = 'rc4-64';
break;
case 16:
$this->cipher_name_openssl = 'rc4';
break;
default:
return false;
}
}
return parent::isValidEngine($engine);
}
/**
@ -196,8 +179,8 @@ class Crypt_RC4 extends Crypt_Base
* {@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()
* @param string $iv
* @see self::setKey()
* @access public
*/
function setIV($iv)
@ -205,35 +188,41 @@ class Crypt_RC4 extends Crypt_Base
}
/**
* Sets the key.
* Sets the key length
*
* 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.
* Keys can be between 1 and 256 bytes long.
*
* @access public
* @see Crypt_Base::setKey()
* @param String $key
* @param int $length
*/
function setKey($key)
function setKeyLength($length)
{
parent::setKey(substr($key, 0, 256));
if ($length < 8) {
$this->key_length = 1;
} elseif ($length > 2048) {
$this->key_length = 256;
} else {
$this->key_length = $length >> 3;
}
parent::setKeyLength($length);
}
/**
* Encrypts a message.
*
* @see Crypt_Base::decrypt()
* @see Crypt_RC4::_crypt()
* @see \phpseclib\Crypt\Base::decrypt()
* @see self::_crypt()
* @access public
* @param String $plaintext
* @return String $ciphertext
* @param string $plaintext
* @return string $ciphertext
*/
function encrypt($plaintext)
{
if ($this->engine == CRYPT_MODE_MCRYPT) {
if ($this->engine != Base::ENGINE_INTERNAL) {
return parent::encrypt($plaintext);
}
return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT);
return $this->_crypt($plaintext, self::ENCRYPT);
}
/**
@ -242,25 +231,46 @@ class Crypt_RC4 extends Crypt_Base
* $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
* At least if the continuous buffer is disabled.
*
* @see Crypt_Base::encrypt()
* @see Crypt_RC4::_crypt()
* @see \phpseclib\Crypt\Base::encrypt()
* @see self::_crypt()
* @access public
* @param String $ciphertext
* @return String $plaintext
* @param string $ciphertext
* @return string $plaintext
*/
function decrypt($ciphertext)
{
if ($this->engine == CRYPT_MODE_MCRYPT) {
if ($this->engine != Base::ENGINE_INTERNAL) {
return parent::decrypt($ciphertext);
}
return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT);
return $this->_crypt($ciphertext, self::DECRYPT);
}
/**
* Encrypts a block
*
* @access private
* @param string $in
*/
function _encryptBlock($in)
{
// RC4 does not utilize this method
}
/**
* Decrypts a block
*
* @access private
* @param string $in
*/
function _decryptBlock($in)
{
// RC4 does not utilize this method
}
/**
* Setup the key (expansion)
*
* @see Crypt_Base::_setupKey()
* @see \phpseclib\Crypt\Base::_setupKey()
* @access private
*/
function _setupKey()
@ -277,7 +287,7 @@ class Crypt_RC4 extends Crypt_Base
}
$this->stream = array();
$this->stream[CRYPT_RC4_DECRYPT] = $this->stream[CRYPT_RC4_ENCRYPT] = array(
$this->stream[self::DECRYPT] = $this->stream[self::ENCRYPT] = array(
0, // index $i
0, // index $j
$keyStream
@ -287,12 +297,12 @@ class Crypt_RC4 extends Crypt_Base
/**
* Encrypts or decrypts a message.
*
* @see Crypt_RC4::encrypt()
* @see Crypt_RC4::decrypt()
* @see self::encrypt()
* @see self::decrypt()
* @access private
* @param String $text
* @param Integer $mode
* @return String $text
* @param string $text
* @param int $mode
* @return string $text
*/
function _crypt($text, $mode)
{

View file

@ -3,14 +3,14 @@
/**
* Pure-PHP PKCS#1 (v2.1) compliant implementation of RSA.
*
* PHP versions 4 and 5
* PHP version 5
*
* Here's an example of how to encrypt and decrypt text with this library:
* <code>
* <?php
* include 'Crypt/RSA.php';
* include 'vendor/autoload.php';
*
* $rsa = new Crypt_RSA();
* $rsa = new \phpseclib\Crypt\RSA();
* extract($rsa->createKey());
*
* $plaintext = 'terrafrost';
@ -26,9 +26,9 @@
* Here's an example of how to create signatures and verify signatures with this library:
* <code>
* <?php
* include 'Crypt/RSA.php';
* include 'vendor/autoload.php';
*
* $rsa = new Crypt_RSA();
* $rsa = new \phpseclib\Crypt\RSA();
* extract($rsa->createKey());
*
* $plaintext = 'terrafrost';
@ -41,241 +41,211 @@
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_RSA
* @package RSA
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2009 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Random
*/
// the class_exists() will only be called if the crypt_random_string function hasn't been defined and
// will trigger a call to __autoload() if you're wanting to auto-load classes
// call function_exists() a second time to stop the include_once from being called outside
// of the auto loader
if (!function_exists('crypt_random_string')) {
include_once 'Random.php';
}
namespace phpseclib\Crypt;
/**
* Include Crypt_Hash
*/
if (!class_exists('Crypt_Hash')) {
include_once 'Hash.php';
}
/**#@+
* @access public
* @see Crypt_RSA::encrypt()
* @see Crypt_RSA::decrypt()
*/
/**
* Use {@link http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding Optimal Asymmetric Encryption Padding}
* (OAEP) for encryption / decryption.
*
* Uses sha1 by default.
*
* @see Crypt_RSA::setHash()
* @see Crypt_RSA::setMGFHash()
*/
define('CRYPT_RSA_ENCRYPTION_OAEP', 1);
/**
* Use PKCS#1 padding.
*
* Although CRYPT_RSA_ENCRYPTION_OAEP offers more security, including PKCS#1 padding is necessary for purposes of backwards
* compatibility with protocols (like SSH-1) written before OAEP's introduction.
*/
define('CRYPT_RSA_ENCRYPTION_PKCS1', 2);
/**#@-*/
/**#@+
* @access public
* @see Crypt_RSA::sign()
* @see Crypt_RSA::verify()
* @see Crypt_RSA::setHash()
*/
/**
* Use the Probabilistic Signature Scheme for signing
*
* Uses sha1 by default.
*
* @see Crypt_RSA::setSaltLength()
* @see Crypt_RSA::setMGFHash()
*/
define('CRYPT_RSA_SIGNATURE_PSS', 1);
/**
* Use the PKCS#1 scheme by default.
*
* Although CRYPT_RSA_SIGNATURE_PSS offers more security, including PKCS#1 signing is necessary for purposes of backwards
* compatibility with protocols (like SSH-2) written before PSS's introduction.
*/
define('CRYPT_RSA_SIGNATURE_PKCS1', 2);
/**#@-*/
/**#@+
* @access private
* @see Crypt_RSA::createKey()
*/
/**
* ASN1 Integer
*/
define('CRYPT_RSA_ASN1_INTEGER', 2);
/**
* ASN1 Bit String
*/
define('CRYPT_RSA_ASN1_BITSTRING', 3);
/**
* ASN1 Octet String
*/
define('CRYPT_RSA_ASN1_OCTETSTRING', 4);
/**
* ASN1 Object Identifier
*/
define('CRYPT_RSA_ASN1_OBJECT', 6);
/**
* ASN1 Sequence (with the constucted bit set)
*/
define('CRYPT_RSA_ASN1_SEQUENCE', 48);
/**#@-*/
/**#@+
* @access private
* @see Crypt_RSA::Crypt_RSA()
*/
/**
* To use the pure-PHP implementation
*/
define('CRYPT_RSA_MODE_INTERNAL', 1);
/**
* To use the OpenSSL library
*
* (if enabled; otherwise, the internal implementation will be used)
*/
define('CRYPT_RSA_MODE_OPENSSL', 2);
/**#@-*/
/**
* Default openSSL configuration file.
*/
define('CRYPT_RSA_OPENSSL_CONFIG', dirname(__FILE__) . '/../openssl.cnf');
/**#@+
* @access public
* @see Crypt_RSA::createKey()
* @see Crypt_RSA::setPrivateKeyFormat()
*/
/**
* PKCS#1 formatted private key
*
* Used by OpenSSH
*/
define('CRYPT_RSA_PRIVATE_FORMAT_PKCS1', 0);
/**
* PuTTY formatted private key
*/
define('CRYPT_RSA_PRIVATE_FORMAT_PUTTY', 1);
/**
* XML formatted private key
*/
define('CRYPT_RSA_PRIVATE_FORMAT_XML', 2);
/**
* PKCS#8 formatted private key
*/
define('CRYPT_RSA_PRIVATE_FORMAT_PKCS8', 3);
/**#@-*/
/**#@+
* @access public
* @see Crypt_RSA::createKey()
* @see Crypt_RSA::setPublicKeyFormat()
*/
/**
* Raw public key
*
* An array containing two Math_BigInteger objects.
*
* The exponent can be indexed with any of the following:
*
* 0, e, exponent, publicExponent
*
* The modulus can be indexed with any of the following:
*
* 1, n, modulo, modulus
*/
define('CRYPT_RSA_PUBLIC_FORMAT_RAW', 3);
/**
* PKCS#1 formatted public key (raw)
*
* Used by File/X509.php
*
* Has the following header:
*
* -----BEGIN RSA PUBLIC KEY-----
*
* Analogous to ssh-keygen's pem format (as specified by -m)
*/
define('CRYPT_RSA_PUBLIC_FORMAT_PKCS1', 4);
define('CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW', 4);
/**
* XML formatted public key
*/
define('CRYPT_RSA_PUBLIC_FORMAT_XML', 5);
/**
* OpenSSH formatted public key
*
* Place in $HOME/.ssh/authorized_keys
*/
define('CRYPT_RSA_PUBLIC_FORMAT_OPENSSH', 6);
/**
* PKCS#1 formatted public key (encapsulated)
*
* Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set)
*
* Has the following header:
*
* -----BEGIN PUBLIC KEY-----
*
* Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8
* is specific to private keys it's basically creating a DER-encoded wrapper
* for keys. This just extends that same concept to public keys (much like ssh-keygen)
*/
define('CRYPT_RSA_PUBLIC_FORMAT_PKCS8', 7);
/**#@-*/
use phpseclib\Math\BigInteger;
/**
* Pure-PHP PKCS#1 compliant implementation of RSA.
*
* @package Crypt_RSA
* @package RSA
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Crypt_RSA
class RSA
{
/**#@+
* @access public
* @see self::encrypt()
* @see self::decrypt()
*/
/**
* Use {@link http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding Optimal Asymmetric Encryption Padding}
* (OAEP) for encryption / decryption.
*
* Uses sha1 by default.
*
* @see self::setHash()
* @see self::setMGFHash()
*/
const ENCRYPTION_OAEP = 1;
/**
* Use PKCS#1 padding.
*
* Although self::ENCRYPTION_OAEP offers more security, including PKCS#1 padding is necessary for purposes of backwards
* compatibility with protocols (like SSH-1) written before OAEP's introduction.
*/
const ENCRYPTION_PKCS1 = 2;
/**
* Do not use any padding
*
* Although this method is not recommended it can none-the-less sometimes be useful if you're trying to decrypt some legacy
* stuff, if you're trying to diagnose why an encrypted message isn't decrypting, etc.
*/
const ENCRYPTION_NONE = 3;
/**#@-*/
/**#@+
* @access public
* @see self::sign()
* @see self::verify()
* @see self::setHash()
*/
/**
* Use the Probabilistic Signature Scheme for signing
*
* Uses sha1 by default.
*
* @see self::setSaltLength()
* @see self::setMGFHash()
*/
const SIGNATURE_PSS = 1;
/**
* Use the PKCS#1 scheme by default.
*
* Although self::SIGNATURE_PSS offers more security, including PKCS#1 signing is necessary for purposes of backwards
* compatibility with protocols (like SSH-2) written before PSS's introduction.
*/
const SIGNATURE_PKCS1 = 2;
/**#@-*/
/**#@+
* @access private
* @see \phpseclib\Crypt\RSA::createKey()
*/
/**
* ASN1 Integer
*/
const ASN1_INTEGER = 2;
/**
* ASN1 Bit String
*/
const ASN1_BITSTRING = 3;
/**
* ASN1 Octet String
*/
const ASN1_OCTETSTRING = 4;
/**
* ASN1 Object Identifier
*/
const ASN1_OBJECT = 6;
/**
* ASN1 Sequence (with the constucted bit set)
*/
const ASN1_SEQUENCE = 48;
/**#@-*/
/**#@+
* @access private
* @see \phpseclib\Crypt\RSA::__construct()
*/
/**
* To use the pure-PHP implementation
*/
const MODE_INTERNAL = 1;
/**
* To use the OpenSSL library
*
* (if enabled; otherwise, the internal implementation will be used)
*/
const MODE_OPENSSL = 2;
/**#@-*/
/**#@+
* @access public
* @see \phpseclib\Crypt\RSA::createKey()
* @see \phpseclib\Crypt\RSA::setPrivateKeyFormat()
*/
/**
* PKCS#1 formatted private key
*
* Used by OpenSSH
*/
const PRIVATE_FORMAT_PKCS1 = 0;
/**
* PuTTY formatted private key
*/
const PRIVATE_FORMAT_PUTTY = 1;
/**
* XML formatted private key
*/
const PRIVATE_FORMAT_XML = 2;
/**
* PKCS#8 formatted private key
*/
const PRIVATE_FORMAT_PKCS8 = 8;
/**#@-*/
/**#@+
* @access public
* @see \phpseclib\Crypt\RSA::createKey()
* @see \phpseclib\Crypt\RSA::setPublicKeyFormat()
*/
/**
* Raw public key
*
* An array containing two \phpseclib\Math\BigInteger objects.
*
* The exponent can be indexed with any of the following:
*
* 0, e, exponent, publicExponent
*
* The modulus can be indexed with any of the following:
*
* 1, n, modulo, modulus
*/
const PUBLIC_FORMAT_RAW = 3;
/**
* PKCS#1 formatted public key (raw)
*
* Used by File/X509.php
*
* Has the following header:
*
* -----BEGIN RSA PUBLIC KEY-----
*
* Analogous to ssh-keygen's pem format (as specified by -m)
*/
const PUBLIC_FORMAT_PKCS1 = 4;
const PUBLIC_FORMAT_PKCS1_RAW = 4;
/**
* XML formatted public key
*/
const PUBLIC_FORMAT_XML = 5;
/**
* OpenSSH formatted public key
*
* Place in $HOME/.ssh/authorized_keys
*/
const PUBLIC_FORMAT_OPENSSH = 6;
/**
* PKCS#1 formatted public key (encapsulated)
*
* Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set)
*
* Has the following header:
*
* -----BEGIN PUBLIC KEY-----
*
* Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8
* is specific to private keys it's basically creating a DER-encoded wrapper
* for keys. This just extends that same concept to public keys (much like ssh-keygen)
*/
const PUBLIC_FORMAT_PKCS8 = 7;
/**#@-*/
/**
* Precomputed Zero
*
* @var Array
* @var \phpseclib\Math\BigInteger
* @access private
*/
var $zero;
@ -283,7 +253,7 @@ class Crypt_RSA
/**
* Precomputed One
*
* @var Array
* @var \phpseclib\Math\BigInteger
* @access private
*/
var $one;
@ -291,23 +261,23 @@ class Crypt_RSA
/**
* Private Key Format
*
* @var Integer
* @var int
* @access private
*/
var $privateKeyFormat = CRYPT_RSA_PRIVATE_FORMAT_PKCS1;
var $privateKeyFormat = self::PRIVATE_FORMAT_PKCS1;
/**
* Public Key Format
*
* @var Integer
* @var int
* @access public
*/
var $publicKeyFormat = CRYPT_RSA_PUBLIC_FORMAT_PKCS8;
var $publicKeyFormat = self::PUBLIC_FORMAT_PKCS8;
/**
* Modulus (ie. n)
*
* @var Math_BigInteger
* @var \phpseclib\Math\BigInteger
* @access private
*/
var $modulus;
@ -315,7 +285,7 @@ class Crypt_RSA
/**
* Modulus length
*
* @var Math_BigInteger
* @var \phpseclib\Math\BigInteger
* @access private
*/
var $k;
@ -323,7 +293,7 @@ class Crypt_RSA
/**
* Exponent (ie. e or d)
*
* @var Math_BigInteger
* @var \phpseclib\Math\BigInteger
* @access private
*/
var $exponent;
@ -331,7 +301,7 @@ class Crypt_RSA
/**
* Primes for Chinese Remainder Theorem (ie. p and q)
*
* @var Array
* @var array
* @access private
*/
var $primes;
@ -339,7 +309,7 @@ class Crypt_RSA
/**
* Exponents for Chinese Remainder Theorem (ie. dP and dQ)
*
* @var Array
* @var array
* @access private
*/
var $exponents;
@ -347,7 +317,7 @@ class Crypt_RSA
/**
* Coefficients for Chinese Remainder Theorem (ie. qInv)
*
* @var Array
* @var array
* @access private
*/
var $coefficients;
@ -355,7 +325,7 @@ class Crypt_RSA
/**
* Hash name
*
* @var String
* @var string
* @access private
*/
var $hashName;
@ -363,7 +333,7 @@ class Crypt_RSA
/**
* Hash function
*
* @var Crypt_Hash
* @var \phpseclib\Crypt\Hash
* @access private
*/
var $hash;
@ -371,7 +341,7 @@ class Crypt_RSA
/**
* Length of hash function output
*
* @var Integer
* @var int
* @access private
*/
var $hLen;
@ -379,7 +349,7 @@ class Crypt_RSA
/**
* Length of salt
*
* @var Integer
* @var int
* @access private
*/
var $sLen;
@ -387,7 +357,7 @@ class Crypt_RSA
/**
* Hash function for the Mask Generation Function
*
* @var Crypt_Hash
* @var \phpseclib\Crypt\Hash
* @access private
*/
var $mgfHash;
@ -395,7 +365,7 @@ class Crypt_RSA
/**
* Length of MGF hash function output
*
* @var Integer
* @var int
* @access private
*/
var $mgfHLen;
@ -403,23 +373,23 @@ class Crypt_RSA
/**
* Encryption mode
*
* @var Integer
* @var int
* @access private
*/
var $encryptionMode = CRYPT_RSA_ENCRYPTION_OAEP;
var $encryptionMode = self::ENCRYPTION_OAEP;
/**
* Signature mode
*
* @var Integer
* @var int
* @access private
*/
var $signatureMode = CRYPT_RSA_SIGNATURE_PSS;
var $signatureMode = self::SIGNATURE_PSS;
/**
* Public Exponent
*
* @var Mixed
* @var mixed
* @access private
*/
var $publicExponent = false;
@ -427,7 +397,7 @@ class Crypt_RSA
/**
* Password
*
* @var String
* @var string
* @access private
*/
var $password = false;
@ -438,8 +408,8 @@ class Crypt_RSA
* For use with parsing XML formatted keys. PHP's XML Parser functions use utilized - instead of PHP's DOM functions -
* because PHP's XML Parser functions work on PHP4 whereas PHP's DOM functions - although surperior - don't.
*
* @see Crypt_RSA::_start_element_handler()
* @var Array
* @see self::_start_element_handler()
* @var array
* @access private
*/
var $components = array();
@ -449,9 +419,9 @@ class Crypt_RSA
*
* For use with parsing XML formatted keys.
*
* @see Crypt_RSA::_character_handler()
* @see Crypt_RSA::_stop_element_handler()
* @var Mixed
* @see self::_character_handler()
* @see self::_stop_element_handler()
* @var mixed
* @access private
*/
var $current;
@ -460,8 +430,8 @@ class Crypt_RSA
* OpenSSL configuration file name.
*
* Set to null to use system configuration file.
* @see Crypt_RSA::createKey()
* @var Mixed
* @see self::createKey()
* @var mixed
* @Access public
*/
var $configFile;
@ -469,7 +439,7 @@ class Crypt_RSA
/**
* Public key comment field.
*
* @var String
* @var string
* @access private
*/
var $comment = 'phpseclib-generated-key';
@ -478,33 +448,25 @@ class Crypt_RSA
* The constructor
*
* If you want to make use of the openssl extension, you'll need to set the mode manually, yourself. The reason
* Crypt_RSA doesn't do it is because OpenSSL doesn't fail gracefully. openssl_pkey_new(), in particular, requires
* \phpseclib\Crypt\RSA doesn't do it is because OpenSSL doesn't fail gracefully. openssl_pkey_new(), in particular, requires
* openssl.cnf be present somewhere and, unfortunately, the only real way to find out is too late.
*
* @return Crypt_RSA
* @return \phpseclib\Crypt\RSA
* @access public
*/
function Crypt_RSA()
function __construct()
{
if (!class_exists('Math_BigInteger')) {
include_once 'Math/BigInteger.php';
}
$this->configFile = dirname(__FILE__) . '/../openssl.cnf';
$this->configFile = CRYPT_RSA_OPENSSL_CONFIG;
if ( !defined('CRYPT_RSA_MODE') ) {
if (!defined('CRYPT_RSA_MODE')) {
switch (true) {
// Math/BigInteger's openssl requirements are a little less stringent than Crypt/RSA's. in particular,
// Math/BigInteger doesn't require an openssl.cfg file whereas Crypt/RSA does. so if Math/BigInteger
// can't use OpenSSL it can be pretty trivially assumed, then, that Crypt/RSA can't either.
case defined('MATH_BIGINTEGER_OPENSSL_DISABLE'):
define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
define('CRYPT_RSA_MODE', self::MODE_INTERNAL);
break;
// openssl_pkey_get_details - which is used in the only place Crypt/RSA.php uses OpenSSL - was introduced in PHP 5.2.0
case !function_exists('openssl_pkey_get_details'):
define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
break;
case extension_loaded('openssl') && version_compare(PHP_VERSION, '4.2.0', '>=') && file_exists($this->configFile):
case extension_loaded('openssl') && file_exists($this->configFile):
// some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
ob_start();
@phpinfo();
@ -532,25 +494,26 @@ class Crypt_RSA
case !isset($versions['Header']):
case !isset($versions['Library']):
case $versions['Header'] == $versions['Library']:
define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_OPENSSL);
case version_compare($versions['Header'], '1.0.0') >= 0 && version_compare($versions['Library'], '1.0.0') >= 0:
define('CRYPT_RSA_MODE', self::MODE_OPENSSL);
break;
default:
define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
define('CRYPT_RSA_MODE', self::MODE_INTERNAL);
define('MATH_BIGINTEGER_OPENSSL_DISABLE', true);
}
break;
default:
define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
define('CRYPT_RSA_MODE', self::MODE_INTERNAL);
}
}
$this->zero = new Math_BigInteger();
$this->one = new Math_BigInteger(1);
$this->zero = new BigInteger();
$this->one = new BigInteger(1);
$this->hash = new Crypt_Hash('sha1');
$this->hash = new Hash('sha1');
$this->hLen = $this->hash->getLength();
$this->hashName = 'sha1';
$this->mgfHash = new Crypt_Hash('sha1');
$this->mgfHash = new Hash('sha1');
$this->mgfHLen = $this->mgfHash->getLength();
}
@ -561,12 +524,12 @@ class Crypt_RSA
* - 'privatekey': The private key.
* - 'publickey': The public key.
* - 'partialkey': A partially computed key (if the execution time exceeded $timeout).
* Will need to be passed back to Crypt_RSA::createKey() as the third parameter for further processing.
* Will need to be passed back to \phpseclib\Crypt\RSA::createKey() as the third parameter for further processing.
*
* @access public
* @param optional Integer $bits
* @param optional Integer $timeout
* @param optional Math_BigInteger $p
* @param int $bits
* @param int $timeout
* @param array $p
*/
function createKey($bits = 1024, $timeout = false, $partial = array())
{
@ -577,7 +540,7 @@ class Crypt_RSA
// per <http://cseweb.ucsd.edu/~hovav/dist/survey.pdf#page=5>, this number ought not result in primes smaller
// than 256 bits. as a consequence if the key you're trying to create is 1024 bits and you've set CRYPT_RSA_SMALLEST_PRIME
// to 384 bits then you're going to get a 384 bit prime and a 640 bit prime (384 + 1024 % 384). at least if
// CRYPT_RSA_MODE is set to CRYPT_RSA_MODE_INTERNAL. if CRYPT_RSA_MODE is set to CRYPT_RSA_MODE_OPENSSL then
// CRYPT_RSA_MODE is set to self::MODE_INTERNAL. if CRYPT_RSA_MODE is set to self::MODE_OPENSSL then
// CRYPT_RSA_SMALLEST_PRIME is ignored (ie. multi-prime RSA support is more intended as a way to speed up RSA key
// generation when there's a chance neither gmp nor OpenSSL are installed)
if (!defined('CRYPT_RSA_SMALLEST_PRIME')) {
@ -585,7 +548,7 @@ class Crypt_RSA
}
// OpenSSL uses 65537 as the exponent and requires RSA keys be 384 bits minimum
if ( CRYPT_RSA_MODE == CRYPT_RSA_MODE_OPENSSL && $bits >= 384 && CRYPT_RSA_EXPONENT == 65537) {
if (CRYPT_RSA_MODE == self::MODE_OPENSSL && $bits >= 384 && CRYPT_RSA_EXPONENT == 65537) {
$config = array();
if (isset($this->configFile)) {
$config['config'] = $this->configFile;
@ -595,11 +558,12 @@ class Crypt_RSA
$publickey = openssl_pkey_get_details($rsa);
$publickey = $publickey['key'];
$privatekey = call_user_func_array(array($this, '_convertPrivateKey'), array_values($this->_parseKey($privatekey, CRYPT_RSA_PRIVATE_FORMAT_PKCS1)));
$publickey = call_user_func_array(array($this, '_convertPublicKey'), array_values($this->_parseKey($publickey, CRYPT_RSA_PUBLIC_FORMAT_PKCS1)));
$privatekey = call_user_func_array(array($this, '_convertPrivateKey'), array_values($this->_parseKey($privatekey, self::PRIVATE_FORMAT_PKCS1)));
$publickey = call_user_func_array(array($this, '_convertPublicKey'), array_values($this->_parseKey($publickey, self::PUBLIC_FORMAT_PKCS1)));
// clear the buffer of error strings stemming from a minimalistic openssl.cnf
while (openssl_error_string() !== false);
while (openssl_error_string() !== false) {
}
return array(
'privatekey' => $privatekey,
@ -610,7 +574,7 @@ class Crypt_RSA
static $e;
if (!isset($e)) {
$e = new Math_BigInteger(CRYPT_RSA_EXPONENT);
$e = new BigInteger(CRYPT_RSA_EXPONENT);
}
extract($this->_generateMinMax($bits));
@ -626,7 +590,7 @@ class Crypt_RSA
$finalMax = $max;
extract($this->_generateMinMax($temp));
$generator = new Math_BigInteger();
$generator = new BigInteger();
$n = $this->one->copy();
if (!empty($partial)) {
@ -743,13 +707,13 @@ class Crypt_RSA
* Convert a private key to the appropriate format.
*
* @access private
* @see setPrivateKeyFormat()
* @param String $RSAPrivateKey
* @return String
* @see self::setPrivateKeyFormat()
* @param string $RSAPrivateKey
* @return string
*/
function _convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients)
{
$signed = $this->privateKeyFormat != CRYPT_RSA_PRIVATE_FORMAT_XML;
$signed = $this->privateKeyFormat != self::PRIVATE_FORMAT_XML;
$num_primes = count($primes);
$raw = array(
'version' => $num_primes == 2 ? chr(0) : chr(1), // two-prime vs. multi
@ -766,7 +730,7 @@ class Crypt_RSA
// if the format in question does not support multi-prime rsa and multi-prime rsa was used,
// call _convertPublicKey() instead.
switch ($this->privateKeyFormat) {
case CRYPT_RSA_PRIVATE_FORMAT_XML:
case self::PRIVATE_FORMAT_XML:
if ($num_primes != 2) {
return false;
}
@ -781,7 +745,7 @@ class Crypt_RSA
' <D>' . base64_encode($raw['privateExponent']) . "</D>\r\n" .
'</RSAKeyValue>';
break;
case CRYPT_RSA_PRIVATE_FORMAT_PUTTY:
case self::PRIVATE_FORMAT_PUTTY:
if ($num_primes != 2) {
return false;
}
@ -789,29 +753,46 @@ class Crypt_RSA
$encryption = (!empty($this->password) || is_string($this->password)) ? 'aes256-cbc' : 'none';
$key.= $encryption;
$key.= "\r\nComment: " . $this->comment . "\r\n";
$public = pack('Na*Na*Na*',
strlen('ssh-rsa'), 'ssh-rsa', strlen($raw['publicExponent']), $raw['publicExponent'], strlen($raw['modulus']), $raw['modulus']
$public = pack(
'Na*Na*Na*',
strlen('ssh-rsa'),
'ssh-rsa',
strlen($raw['publicExponent']),
$raw['publicExponent'],
strlen($raw['modulus']),
$raw['modulus']
);
$source = pack('Na*Na*Na*Na*',
strlen('ssh-rsa'), 'ssh-rsa', strlen($encryption), $encryption,
strlen($this->comment), $this->comment, strlen($public), $public
$source = pack(
'Na*Na*Na*Na*',
strlen('ssh-rsa'),
'ssh-rsa',
strlen($encryption),
$encryption,
strlen($this->comment),
$this->comment,
strlen($public),
$public
);
$public = base64_encode($public);
$key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n";
$key.= chunk_split($public, 64);
$private = pack('Na*Na*Na*Na*',
strlen($raw['privateExponent']), $raw['privateExponent'], strlen($raw['prime1']), $raw['prime1'],
strlen($raw['prime2']), $raw['prime2'], strlen($raw['coefficient']), $raw['coefficient']
$private = pack(
'Na*Na*Na*Na*',
strlen($raw['privateExponent']),
$raw['privateExponent'],
strlen($raw['prime1']),
$raw['prime1'],
strlen($raw['prime2']),
$raw['prime2'],
strlen($raw['coefficient']),
$raw['coefficient']
);
if (empty($this->password) && !is_string($this->password)) {
$source.= pack('Na*', strlen($private), $private);
$hashkey = 'putty-private-key-file-mac-key';
} else {
$private.= crypt_random_string(16 - (strlen($private) & 15));
$private.= Random::string(16 - (strlen($private) & 15));
$source.= pack('Na*', strlen($private), $private);
if (!class_exists('Crypt_AES')) {
include_once 'Crypt/AES.php';
}
$sequence = 0;
$symkey = '';
while (strlen($symkey) < 32) {
@ -819,7 +800,7 @@ class Crypt_RSA
$symkey.= pack('H*', sha1($temp));
}
$symkey = substr($symkey, 0, 32);
$crypto = new Crypt_AES();
$crypto = new AES();
$crypto->setKey($symkey);
$crypto->disablePadding();
@ -830,18 +811,15 @@ class Crypt_RSA
$private = base64_encode($private);
$key.= 'Private-Lines: ' . ((strlen($private) + 63) >> 6) . "\r\n";
$key.= chunk_split($private, 64);
if (!class_exists('Crypt_Hash')) {
include_once 'Crypt/Hash.php';
}
$hash = new Crypt_Hash('sha1');
$hash = new Hash('sha1');
$hash->setKey(pack('H*', sha1($hashkey)));
$key.= 'Private-MAC: ' . bin2hex($hash->hash($source)) . "\r\n";
return $key;
default: // eg. CRYPT_RSA_PRIVATE_FORMAT_PKCS1
default: // eg. self::PRIVATE_FORMAT_PKCS1
$components = array();
foreach ($raw as $name => $value) {
$components[$name] = pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($value)), $value);
$components[$name] = pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($value)), $value);
}
$RSAPrivateKey = implode('', $components);
@ -856,50 +834,68 @@ class Crypt_RSA
// exponent INTEGER, -- di
// coefficient INTEGER -- ti
// }
$OtherPrimeInfo = pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($primes[$i]->toBytes(true))), $primes[$i]->toBytes(true));
$OtherPrimeInfo.= pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($exponents[$i]->toBytes(true))), $exponents[$i]->toBytes(true));
$OtherPrimeInfo.= pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($coefficients[$i]->toBytes(true))), $coefficients[$i]->toBytes(true));
$OtherPrimeInfos.= pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($OtherPrimeInfo)), $OtherPrimeInfo);
$OtherPrimeInfo = pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($primes[$i]->toBytes(true))), $primes[$i]->toBytes(true));
$OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($exponents[$i]->toBytes(true))), $exponents[$i]->toBytes(true));
$OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($coefficients[$i]->toBytes(true))), $coefficients[$i]->toBytes(true));
$OtherPrimeInfos.= pack('Ca*a*', self::ASN1_SEQUENCE, $this->_encodeLength(strlen($OtherPrimeInfo)), $OtherPrimeInfo);
}
$RSAPrivateKey.= pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($OtherPrimeInfos)), $OtherPrimeInfos);
$RSAPrivateKey.= pack('Ca*a*', self::ASN1_SEQUENCE, $this->_encodeLength(strlen($OtherPrimeInfos)), $OtherPrimeInfos);
}
$RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
$RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
if ($this->privateKeyFormat == CRYPT_RSA_PRIVATE_FORMAT_PKCS8) {
if ($this->privateKeyFormat == self::PRIVATE_FORMAT_PKCS8) {
$rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
$RSAPrivateKey = pack('Ca*a*Ca*a*',
CRYPT_RSA_ASN1_INTEGER, "\01\00", $rsaOID, 4, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey
$RSAPrivateKey = pack(
'Ca*a*Ca*a*',
self::ASN1_INTEGER,
"\01\00",
$rsaOID,
4,
$this->_encodeLength(strlen($RSAPrivateKey)),
$RSAPrivateKey
);
$RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
$RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
if (!empty($this->password) || is_string($this->password)) {
$salt = crypt_random_string(8);
$salt = Random::string(8);
$iterationCount = 2048;
if (!class_exists('Crypt_DES')) {
include_once 'Crypt/DES.php';
}
$crypto = new Crypt_DES();
$crypto = new DES();
$crypto->setPassword($this->password, 'pbkdf1', 'md5', $salt, $iterationCount);
$RSAPrivateKey = $crypto->encrypt($RSAPrivateKey);
$parameters = pack('Ca*a*Ca*N',
CRYPT_RSA_ASN1_OCTETSTRING, $this->_encodeLength(strlen($salt)), $salt,
CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(4), $iterationCount
$parameters = pack(
'Ca*a*Ca*N',
self::ASN1_OCTETSTRING,
$this->_encodeLength(strlen($salt)),
$salt,
self::ASN1_INTEGER,
$this->_encodeLength(4),
$iterationCount
);
$pbeWithMD5AndDES_CBC = "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03";
$encryptionAlgorithm = pack('Ca*a*Ca*a*',
CRYPT_RSA_ASN1_OBJECT, $this->_encodeLength(strlen($pbeWithMD5AndDES_CBC)), $pbeWithMD5AndDES_CBC,
CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($parameters)), $parameters
$encryptionAlgorithm = pack(
'Ca*a*Ca*a*',
self::ASN1_OBJECT,
$this->_encodeLength(strlen($pbeWithMD5AndDES_CBC)),
$pbeWithMD5AndDES_CBC,
self::ASN1_SEQUENCE,
$this->_encodeLength(strlen($parameters)),
$parameters
);
$RSAPrivateKey = pack('Ca*a*Ca*a*',
CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($encryptionAlgorithm)), $encryptionAlgorithm,
CRYPT_RSA_ASN1_OCTETSTRING, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey
$RSAPrivateKey = pack(
'Ca*a*Ca*a*',
self::ASN1_SEQUENCE,
$this->_encodeLength(strlen($encryptionAlgorithm)),
$encryptionAlgorithm,
self::ASN1_OCTETSTRING,
$this->_encodeLength(strlen($RSAPrivateKey)),
$RSAPrivateKey
);
$RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
$RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
$RSAPrivateKey = "-----BEGIN ENCRYPTED PRIVATE KEY-----\r\n" .
chunk_split(base64_encode($RSAPrivateKey), 64) .
@ -913,13 +909,10 @@ class Crypt_RSA
}
if (!empty($this->password) || is_string($this->password)) {
$iv = crypt_random_string(8);
$iv = Random::string(8);
$symkey = pack('H*', md5($this->password . $iv)); // symkey is short for symmetric key
$symkey.= substr(pack('H*', md5($symkey . $this->password . $iv)), 0, 8);
if (!class_exists('Crypt_TripleDES')) {
include_once 'Crypt/TripleDES.php';
}
$des = new Crypt_TripleDES();
$des = new TripleDES();
$des->setKey($symkey);
$des->setIV($iv);
$iv = strtoupper(bin2hex($iv));
@ -943,27 +936,27 @@ class Crypt_RSA
* Convert a public key to the appropriate format
*
* @access private
* @see setPublicKeyFormat()
* @param String $RSAPrivateKey
* @return String
* @see self::setPublicKeyFormat()
* @param string $RSAPrivateKey
* @return string
*/
function _convertPublicKey($n, $e)
{
$signed = $this->publicKeyFormat != CRYPT_RSA_PUBLIC_FORMAT_XML;
$signed = $this->publicKeyFormat != self::PUBLIC_FORMAT_XML;
$modulus = $n->toBytes($signed);
$publicExponent = $e->toBytes($signed);
switch ($this->publicKeyFormat) {
case CRYPT_RSA_PUBLIC_FORMAT_RAW:
case self::PUBLIC_FORMAT_RAW:
return array('e' => $e->copy(), 'n' => $n->copy());
case CRYPT_RSA_PUBLIC_FORMAT_XML:
case self::PUBLIC_FORMAT_XML:
return "<RSAKeyValue>\r\n" .
' <Modulus>' . base64_encode($modulus) . "</Modulus>\r\n" .
' <Exponent>' . base64_encode($publicExponent) . "</Exponent>\r\n" .
'</RSAKeyValue>';
break;
case CRYPT_RSA_PUBLIC_FORMAT_OPENSSH:
case self::PUBLIC_FORMAT_OPENSSH:
// from <http://tools.ietf.org/html/rfc4253#page-15>:
// string "ssh-rsa"
// mpint e
@ -972,23 +965,26 @@ class Crypt_RSA
$RSAPublicKey = 'ssh-rsa ' . base64_encode($RSAPublicKey) . ' ' . $this->comment;
return $RSAPublicKey;
default: // eg. CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW or CRYPT_RSA_PUBLIC_FORMAT_PKCS1
default: // eg. self::PUBLIC_FORMAT_PKCS1_RAW or self::PUBLIC_FORMAT_PKCS1
// from <http://tools.ietf.org/html/rfc3447#appendix-A.1.1>:
// RSAPublicKey ::= SEQUENCE {
// modulus INTEGER, -- n
// publicExponent INTEGER -- e
// }
$components = array(
'modulus' => pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($modulus)), $modulus),
'publicExponent' => pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($publicExponent)), $publicExponent)
'modulus' => pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($modulus)), $modulus),
'publicExponent' => pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($publicExponent)), $publicExponent)
);
$RSAPublicKey = pack('Ca*a*a*',
CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])),
$components['modulus'], $components['publicExponent']
$RSAPublicKey = pack(
'Ca*a*a*',
self::ASN1_SEQUENCE,
$this->_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])),
$components['modulus'],
$components['publicExponent']
);
if ($this->publicKeyFormat == CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW) {
if ($this->publicKeyFormat == self::PUBLIC_FORMAT_PKCS1_RAW) {
$RSAPublicKey = "-----BEGIN RSA PUBLIC KEY-----\r\n" .
chunk_split(base64_encode($RSAPublicKey), 64) .
'-----END RSA PUBLIC KEY-----';
@ -998,8 +994,11 @@ class Crypt_RSA
$RSAPublicKey = chr(0) . $RSAPublicKey;
$RSAPublicKey = chr(3) . $this->_encodeLength(strlen($RSAPublicKey)) . $RSAPublicKey;
$RSAPublicKey = pack('Ca*a*',
CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey
$RSAPublicKey = pack(
'Ca*a*',
self::ASN1_SEQUENCE,
$this->_encodeLength(strlen($rsaOID . $RSAPublicKey)),
$rsaOID . $RSAPublicKey
);
$RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
@ -1015,20 +1014,20 @@ class Crypt_RSA
* Break a public or private key down into its constituant components
*
* @access private
* @see _convertPublicKey()
* @see _convertPrivateKey()
* @param String $key
* @param Integer $type
* @return Array
* @see self::_convertPublicKey()
* @see self::_convertPrivateKey()
* @param string $key
* @param int $type
* @return array
*/
function _parseKey($key, $type)
{
if ($type != CRYPT_RSA_PUBLIC_FORMAT_RAW && !is_string($key)) {
if ($type != self::PUBLIC_FORMAT_RAW && !is_string($key)) {
return false;
}
switch ($type) {
case CRYPT_RSA_PUBLIC_FORMAT_RAW:
case self::PUBLIC_FORMAT_RAW:
if (!is_array($key)) {
return false;
}
@ -1060,9 +1059,9 @@ class Crypt_RSA
$components['modulus'] = $key[1]->copy();
}
return isset($components['modulus']) && isset($components['publicExponent']) ? $components : false;
case CRYPT_RSA_PRIVATE_FORMAT_PKCS1:
case CRYPT_RSA_PRIVATE_FORMAT_PKCS8:
case CRYPT_RSA_PUBLIC_FORMAT_PKCS1:
case self::PRIVATE_FORMAT_PKCS1:
case self::PRIVATE_FORMAT_PKCS8:
case self::PUBLIC_FORMAT_PKCS1:
/* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is
"outside the scope" of PKCS#1. PKCS#1 then refers you to PKCS#12 and PKCS#15 if you're wanting to
protect private keys, however, that's not what OpenSSL* does. OpenSSL protects private keys by adding
@ -1090,36 +1089,21 @@ class Crypt_RSA
}
switch ($matches[1]) {
case 'AES-256-CBC':
if (!class_exists('Crypt_AES')) {
include_once 'Crypt/AES.php';
}
$crypto = new Crypt_AES();
$crypto = new AES();
break;
case 'AES-128-CBC':
if (!class_exists('Crypt_AES')) {
include_once 'Crypt/AES.php';
}
$symkey = substr($symkey, 0, 16);
$crypto = new Crypt_AES();
$crypto = new AES();
break;
case 'DES-EDE3-CFB':
if (!class_exists('Crypt_TripleDES')) {
include_once 'Crypt/TripleDES.php';
}
$crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CFB);
$crypto = new TripleDES(Base::MODE_CFB);
break;
case 'DES-EDE3-CBC':
if (!class_exists('Crypt_TripleDES')) {
include_once 'Crypt/TripleDES.php';
}
$symkey = substr($symkey, 0, 24);
$crypto = new Crypt_TripleDES();
$crypto = new TripleDES();
break;
case 'DES-CBC':
if (!class_exists('Crypt_DES')) {
include_once 'Crypt/DES.php';
}
$crypto = new Crypt_DES();
$crypto = new DES();
break;
default:
return false;
@ -1137,7 +1121,7 @@ class Crypt_RSA
$components = array();
if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) {
if (ord($this->_string_shift($key)) != self::ASN1_SEQUENCE) {
return false;
}
if ($this->_decodeLength($key) != strlen($key)) {
@ -1156,14 +1140,14 @@ class Crypt_RSA
ie. PKCS8 keys*/
if ($tag == CRYPT_RSA_ASN1_INTEGER && substr($key, 0, 3) == "\x01\x00\x30") {
if ($tag == self::ASN1_INTEGER && substr($key, 0, 3) == "\x01\x00\x30") {
$this->_string_shift($key, 3);
$tag = CRYPT_RSA_ASN1_SEQUENCE;
$tag = self::ASN1_SEQUENCE;
}
if ($tag == CRYPT_RSA_ASN1_SEQUENCE) {
if ($tag == self::ASN1_SEQUENCE) {
$temp = $this->_string_shift($key, $this->_decodeLength($key));
if (ord($this->_string_shift($temp)) != CRYPT_RSA_ASN1_OBJECT) {
if (ord($this->_string_shift($temp)) != self::ASN1_OBJECT) {
return false;
}
$length = $this->_decodeLength($temp);
@ -1176,7 +1160,7 @@ class Crypt_RSA
salt OCTET STRING (SIZE(8)),
iterationCount INTEGER }
*/
if (ord($this->_string_shift($temp)) != CRYPT_RSA_ASN1_SEQUENCE) {
if (ord($this->_string_shift($temp)) != self::ASN1_SEQUENCE) {
return false;
}
if ($this->_decodeLength($temp) != strlen($temp)) {
@ -1184,7 +1168,7 @@ class Crypt_RSA
}
$this->_string_shift($temp); // assume it's an octet string
$salt = $this->_string_shift($temp, $this->_decodeLength($temp));
if (ord($this->_string_shift($temp)) != CRYPT_RSA_ASN1_INTEGER) {
if (ord($this->_string_shift($temp)) != self::ASN1_INTEGER) {
return false;
}
$this->_decodeLength($temp);
@ -1195,16 +1179,13 @@ class Crypt_RSA
return false;
}
if (!class_exists('Crypt_DES')) {
include_once 'Crypt/DES.php';
}
$crypto = new Crypt_DES();
$crypto = new DES();
$crypto->setPassword($this->password, 'pbkdf1', 'md5', $salt, $iterationCount);
$key = $crypto->decrypt($key);
if ($key === false) {
return false;
}
return $this->_parseKey($key, CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
return $this->_parseKey($key, self::PRIVATE_FORMAT_PKCS1);
default:
return false;
}
@ -1220,10 +1201,10 @@ class Crypt_RSA
// "The initial octet shall encode, as an unsigned binary integer wtih bit 1 as the least significant bit, the number of
// unused bits in the final subsequent octet. The number shall be in the range zero to seven."
// -- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf (section 8.6.2.2)
if ($tag == CRYPT_RSA_ASN1_BITSTRING) {
if ($tag == self::ASN1_BITSTRING) {
$this->_string_shift($key);
}
if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) {
if (ord($this->_string_shift($key)) != self::ASN1_SEQUENCE) {
return false;
}
if ($this->_decodeLength($key) != strlen($key)) {
@ -1231,71 +1212,71 @@ class Crypt_RSA
}
$tag = ord($this->_string_shift($key));
}
if ($tag != CRYPT_RSA_ASN1_INTEGER) {
if ($tag != self::ASN1_INTEGER) {
return false;
}
$length = $this->_decodeLength($key);
$temp = $this->_string_shift($key, $length);
if (strlen($temp) != 1 || ord($temp) > 2) {
$components['modulus'] = new Math_BigInteger($temp, 256);
$this->_string_shift($key); // skip over CRYPT_RSA_ASN1_INTEGER
$components['modulus'] = new BigInteger($temp, 256);
$this->_string_shift($key); // skip over self::ASN1_INTEGER
$length = $this->_decodeLength($key);
$components[$type == CRYPT_RSA_PUBLIC_FORMAT_PKCS1 ? 'publicExponent' : 'privateExponent'] = new Math_BigInteger($this->_string_shift($key, $length), 256);
$components[$type == self::PUBLIC_FORMAT_PKCS1 ? 'publicExponent' : 'privateExponent'] = new BigInteger($this->_string_shift($key, $length), 256);
return $components;
}
if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_INTEGER) {
if (ord($this->_string_shift($key)) != self::ASN1_INTEGER) {
return false;
}
$length = $this->_decodeLength($key);
$components['modulus'] = new Math_BigInteger($this->_string_shift($key, $length), 256);
$components['modulus'] = new BigInteger($this->_string_shift($key, $length), 256);
$this->_string_shift($key);
$length = $this->_decodeLength($key);
$components['publicExponent'] = new Math_BigInteger($this->_string_shift($key, $length), 256);
$components['publicExponent'] = new BigInteger($this->_string_shift($key, $length), 256);
$this->_string_shift($key);
$length = $this->_decodeLength($key);
$components['privateExponent'] = new Math_BigInteger($this->_string_shift($key, $length), 256);
$components['privateExponent'] = new BigInteger($this->_string_shift($key, $length), 256);
$this->_string_shift($key);
$length = $this->_decodeLength($key);
$components['primes'] = array(1 => new Math_BigInteger($this->_string_shift($key, $length), 256));
$components['primes'] = array(1 => new BigInteger($this->_string_shift($key, $length), 256));
$this->_string_shift($key);
$length = $this->_decodeLength($key);
$components['primes'][] = new Math_BigInteger($this->_string_shift($key, $length), 256);
$components['primes'][] = new BigInteger($this->_string_shift($key, $length), 256);
$this->_string_shift($key);
$length = $this->_decodeLength($key);
$components['exponents'] = array(1 => new Math_BigInteger($this->_string_shift($key, $length), 256));
$components['exponents'] = array(1 => new BigInteger($this->_string_shift($key, $length), 256));
$this->_string_shift($key);
$length = $this->_decodeLength($key);
$components['exponents'][] = new Math_BigInteger($this->_string_shift($key, $length), 256);
$components['exponents'][] = new BigInteger($this->_string_shift($key, $length), 256);
$this->_string_shift($key);
$length = $this->_decodeLength($key);
$components['coefficients'] = array(2 => new Math_BigInteger($this->_string_shift($key, $length), 256));
$components['coefficients'] = array(2 => new BigInteger($this->_string_shift($key, $length), 256));
if (!empty($key)) {
if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) {
if (ord($this->_string_shift($key)) != self::ASN1_SEQUENCE) {
return false;
}
$this->_decodeLength($key);
while (!empty($key)) {
if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) {
if (ord($this->_string_shift($key)) != self::ASN1_SEQUENCE) {
return false;
}
$this->_decodeLength($key);
$key = substr($key, 1);
$length = $this->_decodeLength($key);
$components['primes'][] = new Math_BigInteger($this->_string_shift($key, $length), 256);
$components['primes'][] = new BigInteger($this->_string_shift($key, $length), 256);
$this->_string_shift($key);
$length = $this->_decodeLength($key);
$components['exponents'][] = new Math_BigInteger($this->_string_shift($key, $length), 256);
$components['exponents'][] = new BigInteger($this->_string_shift($key, $length), 256);
$this->_string_shift($key);
$length = $this->_decodeLength($key);
$components['coefficients'][] = new Math_BigInteger($this->_string_shift($key, $length), 256);
$components['coefficients'][] = new BigInteger($this->_string_shift($key, $length), 256);
}
}
return $components;
case CRYPT_RSA_PUBLIC_FORMAT_OPENSSH:
case self::PUBLIC_FORMAT_OPENSSH:
$parts = explode(' ', $key, 3);
$key = isset($parts[1]) ? base64_decode($parts[1]) : false;
@ -1311,19 +1292,19 @@ class Crypt_RSA
return false;
}
extract(unpack('Nlength', $this->_string_shift($key, 4)));
$publicExponent = new Math_BigInteger($this->_string_shift($key, $length), -256);
$publicExponent = new BigInteger($this->_string_shift($key, $length), -256);
if (strlen($key) <= 4) {
return false;
}
extract(unpack('Nlength', $this->_string_shift($key, 4)));
$modulus = new Math_BigInteger($this->_string_shift($key, $length), -256);
$modulus = new BigInteger($this->_string_shift($key, $length), -256);
if ($cleanup && strlen($key)) {
if (strlen($key) <= 4) {
return false;
}
extract(unpack('Nlength', $this->_string_shift($key, 4)));
$realModulus = new Math_BigInteger($this->_string_shift($key, $length), -256);
$realModulus = new BigInteger($this->_string_shift($key, $length), -256);
return strlen($key) ? false : array(
'modulus' => $realModulus,
'publicExponent' => $modulus,
@ -1338,8 +1319,8 @@ class Crypt_RSA
}
// http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue
// http://en.wikipedia.org/wiki/XML_Signature
case CRYPT_RSA_PRIVATE_FORMAT_XML:
case CRYPT_RSA_PUBLIC_FORMAT_XML:
case self::PRIVATE_FORMAT_XML:
case self::PUBLIC_FORMAT_XML:
$this->components = array();
$xml = xml_parser_create('UTF-8');
@ -1353,7 +1334,7 @@ class Crypt_RSA
return isset($this->components['modulus']) && isset($this->components['publicExponent']) ? $this->components : false;
// from PuTTY's SSHPUBK.C
case CRYPT_RSA_PRIVATE_FORMAT_PUTTY:
case self::PRIVATE_FORMAT_PUTTY:
$components = array();
$key = preg_split('#\r\n|\r|\n#', $key);
$type = trim(preg_replace('#PuTTY-User-Key-File-2: (.+)#', '$1', $key[0]));
@ -1367,18 +1348,15 @@ class Crypt_RSA
$public = base64_decode(implode('', array_map('trim', array_slice($key, 4, $publicLength))));
$public = substr($public, 11);
extract(unpack('Nlength', $this->_string_shift($public, 4)));
$components['publicExponent'] = new Math_BigInteger($this->_string_shift($public, $length), -256);
$components['publicExponent'] = new BigInteger($this->_string_shift($public, $length), -256);
extract(unpack('Nlength', $this->_string_shift($public, 4)));
$components['modulus'] = new Math_BigInteger($this->_string_shift($public, $length), -256);
$components['modulus'] = new BigInteger($this->_string_shift($public, $length), -256);
$privateLength = trim(preg_replace('#Private-Lines: (\d+)#', '$1', $key[$publicLength + 4]));
$private = base64_decode(implode('', array_map('trim', array_slice($key, $publicLength + 5, $privateLength))));
switch ($encryption) {
case 'aes256-cbc':
if (!class_exists('Crypt_AES')) {
include_once 'Crypt/AES.php';
}
$symkey = '';
$sequence = 0;
while (strlen($symkey) < 32) {
@ -1386,7 +1364,7 @@ class Crypt_RSA
$symkey.= pack('H*', sha1($temp));
}
$symkey = substr($symkey, 0, 32);
$crypto = new Crypt_AES();
$crypto = new AES();
}
if ($encryption != 'none') {
@ -1402,17 +1380,17 @@ class Crypt_RSA
if (strlen($private) < $length) {
return false;
}
$components['privateExponent'] = new Math_BigInteger($this->_string_shift($private, $length), -256);
$components['privateExponent'] = new BigInteger($this->_string_shift($private, $length), -256);
extract(unpack('Nlength', $this->_string_shift($private, 4)));
if (strlen($private) < $length) {
return false;
}
$components['primes'] = array(1 => new Math_BigInteger($this->_string_shift($private, $length), -256));
$components['primes'] = array(1 => new BigInteger($this->_string_shift($private, $length), -256));
extract(unpack('Nlength', $this->_string_shift($private, 4)));
if (strlen($private) < $length) {
return false;
}
$components['primes'][] = new Math_BigInteger($this->_string_shift($private, $length), -256);
$components['primes'][] = new BigInteger($this->_string_shift($private, $length), -256);
$temp = $components['primes'][1]->subtract($this->one);
$components['exponents'] = array(1 => $components['publicExponent']->modInverse($temp));
@ -1423,7 +1401,7 @@ class Crypt_RSA
if (strlen($private) < $length) {
return false;
}
$components['coefficients'] = array(2 => new Math_BigInteger($this->_string_shift($private, $length), -256));
$components['coefficients'] = array(2 => new BigInteger($this->_string_shift($private, $length), -256));
return $components;
}
@ -1435,7 +1413,7 @@ class Crypt_RSA
* More specifically, this returns the size of the modulo in bits.
*
* @access public
* @return Integer
* @return int
*/
function getSize()
{
@ -1448,9 +1426,9 @@ class Crypt_RSA
* Called by xml_set_element_handler()
*
* @access private
* @param Resource $parser
* @param String $name
* @param Array $attribs
* @param resource $parser
* @param string $name
* @param array $attribs
*/
function _start_element_handler($parser, $name, $attribs)
{
@ -1489,13 +1467,13 @@ class Crypt_RSA
* Called by xml_set_element_handler()
*
* @access private
* @param Resource $parser
* @param String $name
* @param resource $parser
* @param string $name
*/
function _stop_element_handler($parser, $name)
{
if (isset($this->current)) {
$this->current = new Math_BigInteger(base64_decode($this->current), 256);
$this->current = new BigInteger(base64_decode($this->current), 256);
unset($this->current);
}
}
@ -1506,8 +1484,8 @@ class Crypt_RSA
* Called by xml_set_character_data_handler()
*
* @access private
* @param Resource $parser
* @param String $data
* @param resource $parser
* @param string $data
*/
function _data_handler($parser, $data)
{
@ -1523,12 +1501,12 @@ class Crypt_RSA
* Returns true on success and false on failure (ie. an incorrect password was provided or the key was malformed)
*
* @access public
* @param String $key
* @param Integer $type optional
* @param string $key
* @param int $type optional
*/
function loadKey($key, $type = false)
{
if (is_object($key) && strtolower(get_class($key)) == 'crypt_rsa') {
if ($key instanceof RSA) {
$this->privateKeyFormat = $key->privateKeyFormat;
$this->publicKeyFormat = $key->publicKeyFormat;
$this->k = $key->k;
@ -1542,10 +1520,10 @@ class Crypt_RSA
$this->comment = $key->comment;
if (is_object($key->hash)) {
$this->hash = new Crypt_Hash($key->hash->getHash());
$this->hash = new Hash($key->hash->getHash());
}
if (is_object($key->mgfHash)) {
$this->mgfHash = new Crypt_Hash($key->mgfHash->getHash());
$this->mgfHash = new Hash($key->mgfHash->getHash());
}
if (is_object($key->modulus)) {
@ -1577,11 +1555,11 @@ class Crypt_RSA
if ($type === false) {
$types = array(
CRYPT_RSA_PUBLIC_FORMAT_RAW,
CRYPT_RSA_PRIVATE_FORMAT_PKCS1,
CRYPT_RSA_PRIVATE_FORMAT_XML,
CRYPT_RSA_PRIVATE_FORMAT_PUTTY,
CRYPT_RSA_PUBLIC_FORMAT_OPENSSH
self::PUBLIC_FORMAT_RAW,
self::PRIVATE_FORMAT_PKCS1,
self::PRIVATE_FORMAT_XML,
self::PRIVATE_FORMAT_PUTTY,
self::PUBLIC_FORMAT_OPENSSH
);
foreach ($types as $type) {
$components = $this->_parseKey($key, $type);
@ -1589,7 +1567,6 @@ class Crypt_RSA
break;
}
}
} else {
$components = $this->_parseKey($key, $type);
}
@ -1617,11 +1594,11 @@ class Crypt_RSA
}
switch ($type) {
case CRYPT_RSA_PUBLIC_FORMAT_OPENSSH:
case CRYPT_RSA_PUBLIC_FORMAT_RAW:
case self::PUBLIC_FORMAT_OPENSSH:
case self::PUBLIC_FORMAT_RAW:
$this->setPublicKey();
break;
case CRYPT_RSA_PRIVATE_FORMAT_PKCS1:
case self::PRIVATE_FORMAT_PKCS1:
switch (true) {
case strpos($key, '-BEGIN PUBLIC KEY-') !== false:
case strpos($key, '-BEGIN RSA PUBLIC KEY-') !== false:
@ -1638,10 +1615,10 @@ class Crypt_RSA
* Private keys can be encrypted with a password. To unset the password, pass in the empty string or false.
* Or rather, pass in $password such that empty($password) && !is_string($password) is true.
*
* @see createKey()
* @see loadKey()
* @see self::createKey()
* @see self::loadKey()
* @access public
* @param String $password
* @param string $password
*/
function setPassword($password = false)
{
@ -1663,11 +1640,11 @@ class Crypt_RSA
*
* Returns true on success, false on failure
*
* @see getPublicKey()
* @see self::getPublicKey()
* @access public
* @param String $key optional
* @param Integer $type optional
* @return Boolean
* @param string $key optional
* @param int $type optional
* @return bool
*/
function setPublicKey($key = false, $type = false)
{
@ -1683,10 +1660,10 @@ class Crypt_RSA
if ($type === false) {
$types = array(
CRYPT_RSA_PUBLIC_FORMAT_RAW,
CRYPT_RSA_PUBLIC_FORMAT_PKCS1,
CRYPT_RSA_PUBLIC_FORMAT_XML,
CRYPT_RSA_PUBLIC_FORMAT_OPENSSH
self::PUBLIC_FORMAT_RAW,
self::PUBLIC_FORMAT_PKCS1,
self::PUBLIC_FORMAT_XML,
self::PUBLIC_FORMAT_OPENSSH
);
foreach ($types as $type) {
$components = $this->_parseKey($key, $type);
@ -1723,24 +1700,24 @@ class Crypt_RSA
*
* Returns true on success, false on failure
*
* @see getPublicKey()
* @see self::getPublicKey()
* @access public
* @param String $key optional
* @param Integer $type optional
* @return Boolean
* @param string $key optional
* @param int $type optional
* @return bool
*/
function setPrivateKey($key = false, $type = false)
{
if ($key === false && !empty($this->publicExponent)) {
unset($this->publicExponent);
$this->publicExponent = false;
return true;
}
$rsa = new Crypt_RSA();
$rsa = new RSA();
if (!$rsa->loadKey($key, $type)) {
return false;
}
unset($rsa->publicExponent);
$rsa->publicExponent = false;
// don't overwrite the old key if the new key is invalid
$this->loadKey($rsa);
@ -1754,12 +1731,12 @@ class Crypt_RSA
* or if the public key was set via setPublicKey(). If the currently loaded key is supposed to be the public key this
* function won't return it since this library, for the most part, doesn't distinguish between public and private keys.
*
* @see getPublicKey()
* @see self::getPublicKey()
* @access public
* @param String $key
* @param Integer $type optional
* @param string $key
* @param int $type optional
*/
function getPublicKey($type = CRYPT_RSA_PUBLIC_FORMAT_PKCS8)
function getPublicKey($type = self::PUBLIC_FORMAT_PKCS8)
{
if (empty($this->modulus) || empty($this->publicExponent)) {
return false;
@ -1772,17 +1749,53 @@ class Crypt_RSA
return $temp;
}
/**
* Returns the public key's fingerprint
*
* The public key's fingerprint is returned, which is equivalent to running `ssh-keygen -lf rsa.pub`. If there is
* no public key currently loaded, false is returned.
* Example output (md5): "c1:b1:30:29:d7:b8:de:6c:97:77:10:d7:46:41:63:87" (as specified by RFC 4716)
*
* @access public
* @param string $algorithm The hashing algorithm to be used. Valid options are 'md5' and 'sha256'. False is returned
* for invalid values.
* @return mixed
*/
function getPublicKeyFingerprint($algorithm = 'md5')
{
if (empty($this->modulus) || empty($this->publicExponent)) {
return false;
}
$modulus = $this->modulus->toBytes(true);
$publicExponent = $this->publicExponent->toBytes(true);
$RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus);
switch ($algorithm) {
case 'sha256':
$hash = new Hash('sha256');
$base = base64_encode($hash->hash($RSAPublicKey));
return substr($base, 0, strlen($base) - 1);
case 'md5':
return substr(chunk_split(md5($RSAPublicKey), 2, ':'), 0, -1);
default:
return false;
}
}
/**
* Returns the private key
*
* The private key is only returned if the currently loaded key contains the constituent prime numbers.
*
* @see getPublicKey()
* @see self::getPublicKey()
* @access public
* @param String $key
* @param Integer $type optional
* @param string $key
* @param int $type optional
* @return mixed
*/
function getPrivateKey($type = CRYPT_RSA_PUBLIC_FORMAT_PKCS1)
function getPrivateKey($type = self::PUBLIC_FORMAT_PKCS1)
{
if (empty($this->primes)) {
return false;
@ -1801,12 +1814,12 @@ class Crypt_RSA
* Returns the private key without the prime number constituants. Structurally identical to a public key that
* hasn't been set as the public key
*
* @see getPrivateKey()
* @see self::getPrivateKey()
* @access private
* @param String $key
* @param Integer $type optional
* @param string $key
* @param int $type optional
*/
function _getPrivatePublicKey($mode = CRYPT_RSA_PUBLIC_FORMAT_PKCS8)
function _getPrivatePublicKey($mode = self::PUBLIC_FORMAT_PKCS8)
{
if (empty($this->modulus) || empty($this->exponent)) {
return false;
@ -1823,6 +1836,7 @@ class Crypt_RSA
* __toString() magic method
*
* @access public
* @return string
*/
function __toString()
{
@ -1838,10 +1852,11 @@ class Crypt_RSA
* __clone() magic method
*
* @access public
* @return Crypt_RSA
*/
function __clone()
{
$key = new Crypt_RSA();
$key = new RSA();
$key->loadKey($this);
return $key;
}
@ -1850,8 +1865,8 @@ class Crypt_RSA
* Generates the smallest and largest numbers requiring $bits bits
*
* @access private
* @param Integer $bits
* @return Array
* @param int $bits
* @return array
*/
function _generateMinMax($bits)
{
@ -1867,8 +1882,8 @@ class Crypt_RSA
}
return array(
'min' => new Math_BigInteger($min, 256),
'max' => new Math_BigInteger($max, 256)
'min' => new BigInteger($min, 256),
'max' => new BigInteger($max, 256)
);
}
@ -1879,13 +1894,13 @@ class Crypt_RSA
* {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
*
* @access private
* @param String $string
* @return Integer
* @param string $string
* @return int
*/
function _decodeLength(&$string)
{
$length = ord($this->_string_shift($string));
if ( $length & 0x80 ) { // definite length, long form
if ($length & 0x80) { // definite length, long form
$length&= 0x7F;
$temp = $this->_string_shift($string, $length);
list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4));
@ -1900,8 +1915,8 @@ class Crypt_RSA
* {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
*
* @access private
* @param Integer $length
* @return String
* @param int $length
* @return string
*/
function _encodeLength($length)
{
@ -1918,9 +1933,9 @@ class Crypt_RSA
*
* Inspired by array_shift
*
* @param String $string
* @param optional Integer $index
* @return String
* @param string $string
* @param int $index
* @return string
* @access private
*/
function _string_shift(&$string, $index = 1)
@ -1933,9 +1948,9 @@ class Crypt_RSA
/**
* Determines the private key format
*
* @see createKey()
* @see self::createKey()
* @access public
* @param Integer $format
* @param int $format
*/
function setPrivateKeyFormat($format)
{
@ -1945,9 +1960,9 @@ class Crypt_RSA
/**
* Determines the public key format
*
* @see createKey()
* @see self::createKey()
* @access public
* @param Integer $format
* @param int $format
*/
function setPublicKeyFormat($format)
{
@ -1957,15 +1972,15 @@ class Crypt_RSA
/**
* Determines which hashing function should be used
*
* Used with signature production / verification and (if the encryption mode is CRYPT_RSA_ENCRYPTION_OAEP) encryption and
* Used with signature production / verification and (if the encryption mode is self::ENCRYPTION_OAEP) encryption and
* decryption. If $hash isn't supported, sha1 is used.
*
* @access public
* @param String $hash
* @param string $hash
*/
function setHash($hash)
{
// Crypt_Hash supports algorithms that PKCS#1 doesn't support. md5-96 and sha1-96, for example.
// \phpseclib\Crypt\Hash supports algorithms that PKCS#1 doesn't support. md5-96 and sha1-96, for example.
switch ($hash) {
case 'md2':
case 'md5':
@ -1973,11 +1988,11 @@ class Crypt_RSA
case 'sha256':
case 'sha384':
case 'sha512':
$this->hash = new Crypt_Hash($hash);
$this->hash = new Hash($hash);
$this->hashName = $hash;
break;
default:
$this->hash = new Crypt_Hash('sha1');
$this->hash = new Hash('sha1');
$this->hashName = 'sha1';
}
$this->hLen = $this->hash->getLength();
@ -1986,15 +2001,15 @@ class Crypt_RSA
/**
* Determines which hashing function should be used for the mask generation function
*
* The mask generation function is used by CRYPT_RSA_ENCRYPTION_OAEP and CRYPT_RSA_SIGNATURE_PSS and although it's
* The mask generation function is used by self::ENCRYPTION_OAEP and self::SIGNATURE_PSS and although it's
* best if Hash and MGFHash are set to the same thing this is not a requirement.
*
* @access public
* @param String $hash
* @param string $hash
*/
function setMGFHash($hash)
{
// Crypt_Hash supports algorithms that PKCS#1 doesn't support. md5-96 and sha1-96, for example.
// \phpseclib\Crypt\Hash supports algorithms that PKCS#1 doesn't support. md5-96 and sha1-96, for example.
switch ($hash) {
case 'md2':
case 'md5':
@ -2002,10 +2017,10 @@ class Crypt_RSA
case 'sha256':
case 'sha384':
case 'sha512':
$this->mgfHash = new Crypt_Hash($hash);
$this->mgfHash = new Hash($hash);
break;
default:
$this->mgfHash = new Crypt_Hash('sha1');
$this->mgfHash = new Hash('sha1');
}
$this->mgfHLen = $this->mgfHash->getLength();
}
@ -2019,7 +2034,7 @@ class Crypt_RSA
* of the hash function Hash) and 0.
*
* @access public
* @param Integer $format
* @param int $format
*/
function setSaltLength($sLen)
{
@ -2032,9 +2047,9 @@ class Crypt_RSA
* See {@link http://tools.ietf.org/html/rfc3447#section-4.1 RFC3447#section-4.1}.
*
* @access private
* @param Math_BigInteger $x
* @param Integer $xLen
* @return String
* @param \phpseclib\Math\BigInteger $x
* @param int $xLen
* @return string
*/
function _i2osp($x, $xLen)
{
@ -2052,12 +2067,12 @@ class Crypt_RSA
* See {@link http://tools.ietf.org/html/rfc3447#section-4.2 RFC3447#section-4.2}.
*
* @access private
* @param String $x
* @return Math_BigInteger
* @param string $x
* @return \phpseclib\Math\BigInteger
*/
function _os2ip($x)
{
return new Math_BigInteger($x, 256);
return new BigInteger($x, 256);
}
/**
@ -2066,13 +2081,19 @@ class Crypt_RSA
* See {@link http://tools.ietf.org/html/rfc3447#section-5.1.1 RFC3447#section-5.1.2}.
*
* @access private
* @param Math_BigInteger $x
* @return Math_BigInteger
* @param \phpseclib\Math\BigInteger $x
* @return \phpseclib\Math\BigInteger
*/
function _exponentiate($x)
{
if (empty($this->primes) || empty($this->coefficients) || empty($this->exponents)) {
return $x->modPow($this->exponent, $this->modulus);
switch (true) {
case empty($this->primes):
case $this->primes[1]->equals($this->zero):
case empty($this->coefficients):
case $this->coefficients[2]->equals($this->zero):
case empty($this->exponents):
case $this->exponents[1]->equals($this->zero):
return $x->modPow($this->exponent, $this->modulus);
}
$num_primes = count($this->primes);
@ -2107,7 +2128,7 @@ class Crypt_RSA
}
}
$one = new Math_BigInteger(1);
$one = new BigInteger(1);
$r = $one->random($one, $smallest->subtract($one));
@ -2144,10 +2165,10 @@ class Crypt_RSA
* Returns $x->modPow($this->exponents[$i], $this->primes[$i])
*
* @access private
* @param Math_BigInteger $x
* @param Math_BigInteger $r
* @param Integer $i
* @return Math_BigInteger
* @param \phpseclib\Math\BigInteger $x
* @param \phpseclib\Math\BigInteger $r
* @param int $i
* @return \phpseclib\Math\BigInteger
*/
function _blind($x, $r, $i)
{
@ -2171,9 +2192,9 @@ class Crypt_RSA
* Thanks for the heads up singpolyma!
*
* @access private
* @param String $x
* @param String $y
* @return Boolean
* @param string $x
* @param string $y
* @return bool
*/
function _equals($x, $y)
{
@ -2195,8 +2216,8 @@ class Crypt_RSA
* See {@link http://tools.ietf.org/html/rfc3447#section-5.1.1 RFC3447#section-5.1.1}.
*
* @access private
* @param Math_BigInteger $m
* @return Math_BigInteger
* @param \phpseclib\Math\BigInteger $m
* @return \phpseclib\Math\BigInteger
*/
function _rsaep($m)
{
@ -2213,8 +2234,8 @@ class Crypt_RSA
* See {@link http://tools.ietf.org/html/rfc3447#section-5.1.2 RFC3447#section-5.1.2}.
*
* @access private
* @param Math_BigInteger $c
* @return Math_BigInteger
* @param \phpseclib\Math\BigInteger $c
* @return \phpseclib\Math\BigInteger
*/
function _rsadp($c)
{
@ -2231,8 +2252,8 @@ class Crypt_RSA
* See {@link http://tools.ietf.org/html/rfc3447#section-5.2.1 RFC3447#section-5.2.1}.
*
* @access private
* @param Math_BigInteger $m
* @return Math_BigInteger
* @param \phpseclib\Math\BigInteger $m
* @return \phpseclib\Math\BigInteger
*/
function _rsasp1($m)
{
@ -2249,8 +2270,8 @@ class Crypt_RSA
* See {@link http://tools.ietf.org/html/rfc3447#section-5.2.2 RFC3447#section-5.2.2}.
*
* @access private
* @param Math_BigInteger $s
* @return Math_BigInteger
* @param \phpseclib\Math\BigInteger $s
* @return \phpseclib\Math\BigInteger
*/
function _rsavp1($s)
{
@ -2267,9 +2288,9 @@ class Crypt_RSA
* See {@link http://tools.ietf.org/html/rfc3447#appendix-B.2.1 RFC3447#appendix-B.2.1}.
*
* @access private
* @param String $mgfSeed
* @param Integer $mgfLen
* @return String
* @param string $mgfSeed
* @param int $mgfLen
* @return string
*/
function _mgf1($mgfSeed, $maskLen)
{
@ -2292,9 +2313,9 @@ class Crypt_RSA
* {http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding OAES}.
*
* @access private
* @param String $m
* @param String $l
* @return String
* @param string $m
* @param string $l
* @return string
*/
function _rsaes_oaep_encrypt($m, $l = '')
{
@ -2315,7 +2336,7 @@ class Crypt_RSA
$lHash = $this->hash->hash($l);
$ps = str_repeat(chr(0), $this->k - $mLen - 2 * $this->hLen - 2);
$db = $lHash . $ps . chr(1) . $m;
$seed = crypt_random_string($this->hLen);
$seed = Random::string($this->hLen);
$dbMask = $this->_mgf1($seed, $this->k - $this->hLen - 1);
$maskedDB = $db ^ $dbMask;
$seedMask = $this->_mgf1($maskedDB, $this->hLen);
@ -2355,9 +2376,9 @@ class Crypt_RSA
* this document.
*
* @access private
* @param String $c
* @param String $l
* @return String
* @param string $c
* @param string $l
* @return string
*/
function _rsaes_oaep_decrypt($c, $l = '')
{
@ -2408,14 +2429,30 @@ class Crypt_RSA
return substr($m, 1);
}
/**
* Raw Encryption / Decryption
*
* Doesn't use padding and is not recommended.
*
* @access private
* @param string $m
* @return string
*/
function _raw_encrypt($m)
{
$temp = $this->_os2ip($m);
$temp = $this->_rsaep($temp);
return $this->_i2osp($temp, $this->k);
}
/**
* RSAES-PKCS1-V1_5-ENCRYPT
*
* See {@link http://tools.ietf.org/html/rfc3447#section-7.2.1 RFC3447#section-7.2.1}.
*
* @access private
* @param String $m
* @return String
* @param string $m
* @return string
*/
function _rsaes_pkcs1_v1_5_encrypt($m)
{
@ -2433,7 +2470,7 @@ class Crypt_RSA
$psLen = $this->k - $mLen - 3;
$ps = '';
while (strlen($ps) != $psLen) {
$temp = crypt_random_string($psLen - strlen($ps));
$temp = Random::string($psLen - strlen($ps));
$temp = str_replace("\x00", '', $temp);
$ps.= $temp;
}
@ -2468,13 +2505,13 @@ class Crypt_RSA
* to be 2 regardless of which key is used. For compatibility purposes, we'll just check to make sure the
* second byte is 2 or less. If it is, we'll accept the decrypted string as valid.
*
* As a consequence of this, a private key encrypted ciphertext produced with Crypt_RSA may not decrypt
* As a consequence of this, a private key encrypted ciphertext produced with \phpseclib\Crypt\RSA may not decrypt
* with a strictly PKCS#1 v1.5 compliant RSA implementation. Public key encrypted ciphertext's should but
* not private key encrypted ciphertext's.
*
* @access private
* @param String $c
* @return String
* @param string $c
* @return string
*/
function _rsaes_pkcs1_v1_5_decrypt($c)
{
@ -2522,8 +2559,8 @@ class Crypt_RSA
* See {@link http://tools.ietf.org/html/rfc3447#section-9.1.1 RFC3447#section-9.1.1}.
*
* @access private
* @param String $m
* @param Integer $emBits
* @param string $m
* @param int $emBits
*/
function _emsa_pss_encode($m, $emBits)
{
@ -2531,7 +2568,7 @@ class Crypt_RSA
// be output.
$emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8)
$sLen = $this->sLen == false ? $this->hLen : $this->sLen;
$sLen = $this->sLen !== null ? $this->sLen : $this->hLen;
$mHash = $this->hash->hash($m);
if ($emLen < $this->hLen + $sLen + 2) {
@ -2539,7 +2576,7 @@ class Crypt_RSA
return false;
}
$salt = crypt_random_string($sLen);
$salt = Random::string($sLen);
$m2 = "\0\0\0\0\0\0\0\0" . $mHash . $salt;
$h = $this->hash->hash($m2);
$ps = str_repeat(chr(0), $emLen - $sLen - $this->hLen - 2);
@ -2558,10 +2595,10 @@ class Crypt_RSA
* See {@link http://tools.ietf.org/html/rfc3447#section-9.1.2 RFC3447#section-9.1.2}.
*
* @access private
* @param String $m
* @param String $em
* @param Integer $emBits
* @return String
* @param string $m
* @param string $em
* @param int $emBits
* @return string
*/
function _emsa_pss_verify($m, $em, $emBits)
{
@ -2569,7 +2606,7 @@ class Crypt_RSA
// be output.
$emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8);
$sLen = $this->sLen == false ? $this->hLen : $this->sLen;
$sLen = $this->sLen !== null ? $this->sLen : $this->hLen;
$mHash = $this->hash->hash($m);
if ($emLen < $this->hLen + $sLen + 2) {
@ -2605,8 +2642,8 @@ class Crypt_RSA
* See {@link http://tools.ietf.org/html/rfc3447#section-8.1.1 RFC3447#section-8.1.1}.
*
* @access private
* @param String $m
* @return String
* @param string $m
* @return string
*/
function _rsassa_pss_sign($m)
{
@ -2631,9 +2668,9 @@ class Crypt_RSA
* See {@link http://tools.ietf.org/html/rfc3447#section-8.1.2 RFC3447#section-8.1.2}.
*
* @access private
* @param String $m
* @param String $s
* @return String
* @param string $m
* @param string $s
* @return string
*/
function _rsassa_pss_verify($m, $s)
{
@ -2671,9 +2708,9 @@ class Crypt_RSA
* See {@link http://tools.ietf.org/html/rfc3447#section-9.2 RFC3447#section-9.2}.
*
* @access private
* @param String $m
* @param Integer $emLen
* @return String
* @param string $m
* @param int $emLen
* @return string
*/
function _emsa_pkcs1_v1_5_encode($m, $emLen)
{
@ -2723,8 +2760,8 @@ class Crypt_RSA
* See {@link http://tools.ietf.org/html/rfc3447#section-8.2.1 RFC3447#section-8.2.1}.
*
* @access private
* @param String $m
* @return String
* @param string $m
* @return string
*/
function _rsassa_pkcs1_v1_5_sign($m)
{
@ -2753,8 +2790,8 @@ class Crypt_RSA
* See {@link http://tools.ietf.org/html/rfc3447#section-8.2.2 RFC3447#section-8.2.2}.
*
* @access private
* @param String $m
* @return String
* @param string $m
* @return string
*/
function _rsassa_pkcs1_v1_5_verify($m, $s)
{
@ -2794,10 +2831,10 @@ class Crypt_RSA
/**
* Set Encryption Mode
*
* Valid values include CRYPT_RSA_ENCRYPTION_OAEP and CRYPT_RSA_ENCRYPTION_PKCS1.
* Valid values include self::ENCRYPTION_OAEP and self::ENCRYPTION_PKCS1.
*
* @access public
* @param Integer $mode
* @param int $mode
*/
function setEncryptionMode($mode)
{
@ -2807,10 +2844,10 @@ class Crypt_RSA
/**
* Set Signature Mode
*
* Valid values include CRYPT_RSA_SIGNATURE_PSS and CRYPT_RSA_SIGNATURE_PKCS1
* Valid values include self::SIGNATURE_PSS and self::SIGNATURE_PKCS1
*
* @access public
* @param Integer $mode
* @param int $mode
*/
function setSignatureMode($mode)
{
@ -2821,7 +2858,7 @@ class Crypt_RSA
* Set public key comment.
*
* @access public
* @param String $comment
* @param string $comment
*/
function setComment($comment)
{
@ -2832,7 +2869,7 @@ class Crypt_RSA
* Get public key comment.
*
* @access public
* @return String
* @return string
*/
function getComment()
{
@ -2842,19 +2879,26 @@ class Crypt_RSA
/**
* Encryption
*
* Both CRYPT_RSA_ENCRYPTION_OAEP and CRYPT_RSA_ENCRYPTION_PKCS1 both place limits on how long $plaintext can be.
* Both self::ENCRYPTION_OAEP and self::ENCRYPTION_PKCS1 both place limits on how long $plaintext can be.
* If $plaintext exceeds those limits it will be broken up so that it does and the resultant ciphertext's will
* be concatenated together.
*
* @see decrypt()
* @see self::decrypt()
* @access public
* @param String $plaintext
* @return String
* @param string $plaintext
* @return string
*/
function encrypt($plaintext)
{
switch ($this->encryptionMode) {
case CRYPT_RSA_ENCRYPTION_PKCS1:
case self::ENCRYPTION_NONE:
$plaintext = str_split($plaintext, $this->k);
$ciphertext = '';
foreach ($plaintext as $m) {
$ciphertext.= $this->_raw_encrypt($m);
}
return $ciphertext;
case self::ENCRYPTION_PKCS1:
$length = $this->k - 11;
if ($length <= 0) {
return false;
@ -2866,7 +2910,7 @@ class Crypt_RSA
$ciphertext.= $this->_rsaes_pkcs1_v1_5_encrypt($m);
}
return $ciphertext;
//case CRYPT_RSA_ENCRYPTION_OAEP:
//case self::ENCRYPTION_OAEP:
default:
$length = $this->k - 2 * $this->hLen - 2;
if ($length <= 0) {
@ -2885,10 +2929,10 @@ class Crypt_RSA
/**
* Decryption
*
* @see encrypt()
* @see self::encrypt()
* @access public
* @param String $plaintext
* @return String
* @param string $plaintext
* @return string
*/
function decrypt($ciphertext)
{
@ -2902,10 +2946,13 @@ class Crypt_RSA
$plaintext = '';
switch ($this->encryptionMode) {
case CRYPT_RSA_ENCRYPTION_PKCS1:
case self::ENCRYPTION_NONE:
$decrypt = '_raw_encrypt';
break;
case self::ENCRYPTION_PKCS1:
$decrypt = '_rsaes_pkcs1_v1_5_decrypt';
break;
//case CRYPT_RSA_ENCRYPTION_OAEP:
//case self::ENCRYPTION_OAEP:
default:
$decrypt = '_rsaes_oaep_decrypt';
}
@ -2924,10 +2971,10 @@ class Crypt_RSA
/**
* Create a signature
*
* @see verify()
* @see self::verify()
* @access public
* @param String $message
* @return String
* @param string $message
* @return string
*/
function sign($message)
{
@ -2936,9 +2983,9 @@ class Crypt_RSA
}
switch ($this->signatureMode) {
case CRYPT_RSA_SIGNATURE_PKCS1:
case self::SIGNATURE_PKCS1:
return $this->_rsassa_pkcs1_v1_5_sign($message);
//case CRYPT_RSA_SIGNATURE_PSS:
//case self::SIGNATURE_PSS:
default:
return $this->_rsassa_pss_sign($message);
}
@ -2947,11 +2994,11 @@ class Crypt_RSA
/**
* Verifies a signature
*
* @see sign()
* @see self::sign()
* @access public
* @param String $message
* @param String $signature
* @return Boolean
* @param string $message
* @param string $signature
* @return bool
*/
function verify($message, $signature)
{
@ -2960,9 +3007,9 @@ class Crypt_RSA
}
switch ($this->signatureMode) {
case CRYPT_RSA_SIGNATURE_PKCS1:
case self::SIGNATURE_PKCS1:
return $this->_rsassa_pkcs1_v1_5_verify($message, $signature);
//case CRYPT_RSA_SIGNATURE_PSS:
//case self::SIGNATURE_PSS:
default:
return $this->_rsassa_pss_verify($message, $signature);
}
@ -2972,8 +3019,8 @@ class Crypt_RSA
* Extract raw BER from Base64 encoding
*
* @access private
* @param String $str
* @return String
* @param string $str
* @return string
*/
function _extractBER($str)
{
@ -2986,7 +3033,7 @@ class Crypt_RSA
* subject=/O=organization/OU=org unit/CN=common name
* issuer=/O=organization/CN=common name
*/
$temp = preg_replace('#.*?^-+[^-]+-+#ms', '', $str, 1);
$temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1);
// remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff
$temp = preg_replace('#-+[^-]+-+#', '', $temp);
// remove new lines

View file

@ -3,57 +3,36 @@
/**
* Random Number Generator
*
* The idea behind this function is that it can be easily replaced with your own crypt_random_string()
* function. eg. maybe you have a better source of entropy for creating the initial states or whatever.
*
* PHP versions 4 and 5
* PHP version 5
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/Random.php';
* include 'vendor/autoload.php';
*
* echo bin2hex(crypt_random_string(8));
* echo bin2hex(\phpseclib\Crypt\Random::string(8));
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_Random
* @package Random
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
// laravel is a PHP framework that utilizes phpseclib. laravel workbenches may, independently,
// have phpseclib as a requirement as well. if you're developing such a program you may encounter
// a "Cannot redeclare crypt_random_string()" error.
if (!function_exists('crypt_random_string')) {
/**
* "Is Windows" test
*
* @access private
*/
define('CRYPT_RANDOM_IS_WINDOWS', strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
namespace phpseclib\Crypt;
/**
* Pure-PHP Random Number Generator
*
* @package Random
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Random
{
/**
* Generate a random string.
*
@ -61,16 +40,28 @@ if (!function_exists('crypt_random_string')) {
* microoptimizations because this function has the potential of being called a huge number of times.
* eg. for RSA key generation.
*
* @param Integer $length
* @return String
* @access public
* @param int $length
* @return string
*/
function crypt_random_string($length)
static function string($length)
{
if (CRYPT_RANDOM_IS_WINDOWS) {
if (version_compare(PHP_VERSION, '7.0.0', '>=')) {
try {
return \random_bytes($length);
} catch (\Throwable $e) {
// If a sufficient source of randomness is unavailable, random_bytes() will throw an
// object that implements the Throwable interface (Exception, TypeError, Error).
// We don't actually need to do anything here. The string() method should just continue
// as normal. Note, however, that if we don't have a sufficient source of randomness for
// random_bytes(), most of the other calls here will fail too, so we'll end up using
// the PHP implementation.
}
}
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
// method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call.
// ie. class_alias is a function that was introduced in PHP 5.3
if (function_exists('mcrypt_create_iv') && function_exists('class_alias')) {
if (extension_loaded('mcrypt') && function_exists('class_alias')) {
return mcrypt_create_iv($length);
}
// method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was,
@ -86,12 +77,12 @@ if (!function_exists('crypt_random_string')) {
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80
//
// we're calling it, all the same, in the off chance that the mcrypt extension is not available
if (function_exists('openssl_random_pseudo_bytes') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
return openssl_random_pseudo_bytes($length);
}
} else {
// method 1. the fastest
if (function_exists('openssl_random_pseudo_bytes')) {
if (extension_loaded('openssl')) {
return openssl_random_pseudo_bytes($length);
}
// method 2
@ -109,7 +100,7 @@ if (!function_exists('crypt_random_string')) {
// surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're
// not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir
// restrictions or some such
if (function_exists('mcrypt_create_iv')) {
if (extension_loaded('mcrypt')) {
return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
}
}
@ -149,13 +140,13 @@ if (!function_exists('crypt_random_string')) {
session_start();
$v = $seed = $_SESSION['seed'] = pack('H*', sha1(
serialize($_SERVER) .
serialize($_POST) .
serialize($_GET) .
serialize($_COOKIE) .
serialize($GLOBALS) .
serialize($_SESSION) .
serialize($_OLD_SESSION)
(isset($_SERVER) ? phpseclib_safe_serialize($_SERVER) : '') .
(isset($_POST) ? phpseclib_safe_serialize($_POST) : '') .
(isset($_GET) ? phpseclib_safe_serialize($_GET) : '') .
(isset($_COOKIE) ? phpseclib_safe_serialize($_COOKIE) : '') .
phpseclib_safe_serialize($GLOBALS) .
phpseclib_safe_serialize($_SESSION) .
phpseclib_safe_serialize($_OLD_SESSION)
));
if (!isset($_SESSION['count'])) {
$_SESSION['count'] = 0;
@ -171,9 +162,9 @@ if (!function_exists('crypt_random_string')) {
ini_set('session.use_cookies', $old_use_cookies);
session_cache_limiter($old_session_cache_limiter);
} else {
if ($_OLD_SESSION !== false) {
$_SESSION = $_OLD_SESSION;
unset($_OLD_SESSION);
if ($_OLD_SESSION !== false) {
$_SESSION = $_OLD_SESSION;
unset($_OLD_SESSION);
} else {
unset($_SESSION);
}
@ -194,44 +185,26 @@ if (!function_exists('crypt_random_string')) {
//
// http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives
switch (true) {
case phpseclib_resolve_include_path('Crypt/AES.php'):
if (!class_exists('Crypt_AES')) {
include_once 'AES.php';
}
$crypto = new Crypt_AES(CRYPT_AES_MODE_CTR);
case class_exists('\phpseclib\Crypt\AES'):
$crypto = new AES(Base::MODE_CTR);
break;
case phpseclib_resolve_include_path('Crypt/Twofish.php'):
if (!class_exists('Crypt_Twofish')) {
include_once 'Twofish.php';
}
$crypto = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR);
case class_exists('\phpseclib\Crypt\Twofish'):
$crypto = new Twofish(Base::MODE_CTR);
break;
case phpseclib_resolve_include_path('Crypt/Blowfish.php'):
if (!class_exists('Crypt_Blowfish')) {
include_once 'Blowfish.php';
}
$crypto = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR);
case class_exists('\phpseclib\Crypt\Blowfish'):
$crypto = new Blowfish(Base::MODE_CTR);
break;
case phpseclib_resolve_include_path('Crypt/TripleDES.php'):
if (!class_exists('Crypt_TripleDES')) {
include_once 'TripleDES.php';
}
$crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
case class_exists('\phpseclib\Crypt\TripleDES'):
$crypto = new TripleDES(Base::MODE_CTR);
break;
case phpseclib_resolve_include_path('Crypt/DES.php'):
if (!class_exists('Crypt_DES')) {
include_once 'DES.php';
}
$crypto = new Crypt_DES(CRYPT_DES_MODE_CTR);
case class_exists('\phpseclib\Crypt\DES'):
$crypto = new DES(Base::MODE_CTR);
break;
case phpseclib_resolve_include_path('Crypt/RC4.php'):
if (!class_exists('Crypt_RC4')) {
include_once 'RC4.php';
}
$crypto = new Crypt_RC4();
case class_exists('\phpseclib\Crypt\RC4'):
$crypto = new RC4();
break;
default:
user_error('crypt_random_string requires at least one symmetric cipher be loaded');
user_error(__CLASS__ . ' requires at least one symmetric cipher be loaded');
return false;
}
@ -261,40 +234,37 @@ if (!function_exists('crypt_random_string')) {
}
}
if (!function_exists('phpseclib_resolve_include_path')) {
if (!function_exists('phpseclib_safe_serialize')) {
/**
* Resolve filename against the include path.
* Safely serialize variables
*
* Wrapper around stream_resolve_include_path() (which was introduced in
* PHP 5.3.2) with fallback implementation for earlier PHP versions.
* If a class has a private __sleep() method it'll give a fatal error on PHP 5.2 and earlier.
* PHP 5.3 will emit a warning.
*
* @param string $filename
* @return mixed Filename (string) on success, false otherwise.
* @param mixed $arr
* @access public
*/
function phpseclib_resolve_include_path($filename)
function phpseclib_safe_serialize(&$arr)
{
if (function_exists('stream_resolve_include_path')) {
return stream_resolve_include_path($filename);
if (is_object($arr)) {
return '';
}
// handle non-relative paths
if (file_exists($filename)) {
return realpath($filename);
if (!is_array($arr)) {
return serialize($arr);
}
$paths = PATH_SEPARATOR == ':' ?
preg_split('#(?<!phar):#', get_include_path()) :
explode(PATH_SEPARATOR, get_include_path());
foreach ($paths as $prefix) {
// path's specified in include_path don't always end in /
$ds = substr($prefix, -1) == DIRECTORY_SEPARATOR ? '' : DIRECTORY_SEPARATOR;
$file = $prefix . $ds . $filename;
if (file_exists($file)) {
return realpath($file);
// prevent circular array recursion
if (isset($arr['__phpseclib_marker'])) {
return '';
}
$safearr = array();
$arr['__phpseclib_marker'] = true;
foreach (array_keys($arr) as $key) {
// do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage
if ($key !== '__phpseclib_marker') {
$safearr[$key] = phpseclib_safe_serialize($arr[$key]);
}
}
return false;
unset($arr['__phpseclib_marker']);
return serialize($safearr);
}
}

View file

@ -5,13 +5,13 @@
*
* Uses mcrypt, if available/possible, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
* PHP version 5
*
* If {@link Crypt_Rijndael::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits. If
* {@link Crypt_Rijndael::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
* {@link Crypt_Rijndael::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's
* If {@link self::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits. If
* {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
* {@link self::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 192-bits and 192 bits will be the key length until
* {@link Crypt_Rijndael::setKey() setKey()} is called, again, at which point, it'll be recalculated.
* {@link self::setKey() setKey()} is called, again, at which point, it'll be recalculated.
*
* Not all Rijndael implementations may support 160-bits or 224-bits as the block length / key length. mcrypt, for example,
* does not. AES, itself, only supports block lengths of 128 and key lengths of 128, 192, and 256.
@ -28,9 +28,9 @@
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/Rijndael.php';
* include 'vendor/autoload.php';
*
* $rijndael = new Crypt_Rijndael();
* $rijndael = new \phpseclib\Crypt\Rijndael();
*
* $rijndael->setKey('abcdefghijklmnop');
*
@ -44,134 +44,37 @@
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_Rijndael
* @package Rijndael
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2008 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Base
*
* Base cipher class
*/
if (!class_exists('Crypt_Base')) {
include_once 'Base.php';
}
/**#@+
* @access public
* @see Crypt_Rijndael::encrypt()
* @see Crypt_Rijndael::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_RIJNDAEL_MODE_CTR', CRYPT_MODE_CTR);
/**
* 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_RIJNDAEL_MODE_ECB', CRYPT_MODE_ECB);
/**
* 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_RIJNDAEL_MODE_CBC', CRYPT_MODE_CBC);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/
define('CRYPT_RIJNDAEL_MODE_CFB', CRYPT_MODE_CFB);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/
define('CRYPT_RIJNDAEL_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/
/**#@+
* @access private
* @see Crypt_Base::Crypt_Base()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_RIJNDAEL_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_RIJNDAEL_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
namespace phpseclib\Crypt;
/**
* Pure-PHP implementation of Rijndael.
*
* @package Crypt_Rijndael
* @package Rijndael
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Crypt_Rijndael extends Crypt_Base
class Rijndael extends Base
{
/**
* The default password key_size used by setPassword()
*
* @see Crypt_Base::password_key_size
* @see Crypt_Base::setPassword()
* @var Integer
* @access private
*/
var $password_key_size = 16;
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_Base::const_namespace
* @var String
* @access private
*/
var $const_namespace = 'RIJNDAEL';
/**
* The mcrypt specific name of the cipher
*
* Mcrypt is useable for 128/192/256-bit $block_size/$key_size. For 160/224 not.
* Crypt_Rijndael determines automatically whether mcrypt is useable
* or not for the current $block_size/$key_size.
* Mcrypt is useable for 128/192/256-bit $block_size/$key_length. For 160/224 not.
* \phpseclib\Crypt\Rijndael determines automatically whether mcrypt is useable
* or not for the current $block_size/$key_length.
* In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly.
*
* @see Crypt_Base::cipher_name_mcrypt
* @see Crypt_Base::engine
* @see _setupEngine()
* @var String
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt
* @see \phpseclib\Crypt\Base::engine
* @see self::isValidEngine()
* @var string
* @access private
*/
var $cipher_name_mcrypt = 'rijndael-128';
@ -179,27 +82,18 @@ class Crypt_Rijndael extends Crypt_Base
/**
* The default salt used by setPassword()
*
* @see Crypt_Base::password_default_salt
* @see Crypt_Base::setPassword()
* @var String
* @see \phpseclib\Crypt\Base::password_default_salt
* @see \phpseclib\Crypt\Base::setPassword()
* @var string
* @access private
*/
var $password_default_salt = 'phpseclib';
/**
* Has the key length explicitly been set or should it be derived from the key, itself?
*
* @see setKeyLength()
* @var Boolean
* @access private
*/
var $explicit_key_length = false;
/**
* The Key Schedule
*
* @see _setup()
* @var Array
* @see self::_setup()
* @var array
* @access private
*/
var $w;
@ -207,8 +101,8 @@ class Crypt_Rijndael extends Crypt_Base
/**
* The Inverse Key Schedule
*
* @see _setup()
* @var Array
* @see self::_setup()
* @var array
* @access private
*/
var $dw;
@ -216,35 +110,34 @@ class Crypt_Rijndael extends Crypt_Base
/**
* The Block Length divided by 32
*
* @see setBlockLength()
* @var Integer
* @see self::setBlockLength()
* @var int
* @access private
* @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $block_size
* because the encryption / decryption / key schedule creation requires this number and not $block_size. We could
* derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
* of that, we'll just precompute it once.
*
*/
var $Nb = 4;
/**
* The Key Length
* The Key Length (in bytes)
*
* @see setKeyLength()
* @var Integer
* @see self::setKeyLength()
* @var int
* @access private
* @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
* because the encryption / decryption / key schedule creation requires this number and not $key_size. We could
* derive this from $key_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
* because the encryption / decryption / key schedule creation requires this number and not $key_length. We could
* derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
* of that, we'll just precompute it once.
*/
var $key_size = 16;
var $key_length = 16;
/**
* The Key Length divided by 32
*
* @see setKeyLength()
* @var Integer
* @see self::setKeyLength()
* @var int
* @access private
* @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4
*/
@ -253,7 +146,7 @@ class Crypt_Rijndael extends Crypt_Base
/**
* The Number of Rounds
*
* @var Integer
* @var int
* @access private
* @internal The max value is 14, the min value is 10.
*/
@ -262,7 +155,7 @@ class Crypt_Rijndael extends Crypt_Base
/**
* Shift offsets
*
* @var Array
* @var array
* @access private
*/
var $c;
@ -270,456 +163,13 @@ class Crypt_Rijndael extends Crypt_Base
/**
* Holds the last used key- and block_size information
*
* @var Array
* @var array
* @access private
*/
var $kl;
/**
* Precomputed mixColumns table
*
* According to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
* precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
* those are the names we'll use.
*
* @see Crypt_Rijndael:_encryptBlock()
* @see Crypt_Rijndael:_decryptBlock()
* @var Array
* @access private
*/
var $t0 = array(
0xC66363A5, 0xF87C7C84, 0xEE777799, 0xF67B7B8D, 0xFFF2F20D, 0xD66B6BBD, 0xDE6F6FB1, 0x91C5C554,
0x60303050, 0x02010103, 0xCE6767A9, 0x562B2B7D, 0xE7FEFE19, 0xB5D7D762, 0x4DABABE6, 0xEC76769A,
0x8FCACA45, 0x1F82829D, 0x89C9C940, 0xFA7D7D87, 0xEFFAFA15, 0xB25959EB, 0x8E4747C9, 0xFBF0F00B,
0x41ADADEC, 0xB3D4D467, 0x5FA2A2FD, 0x45AFAFEA, 0x239C9CBF, 0x53A4A4F7, 0xE4727296, 0x9BC0C05B,
0x75B7B7C2, 0xE1FDFD1C, 0x3D9393AE, 0x4C26266A, 0x6C36365A, 0x7E3F3F41, 0xF5F7F702, 0x83CCCC4F,
0x6834345C, 0x51A5A5F4, 0xD1E5E534, 0xF9F1F108, 0xE2717193, 0xABD8D873, 0x62313153, 0x2A15153F,
0x0804040C, 0x95C7C752, 0x46232365, 0x9DC3C35E, 0x30181828, 0x379696A1, 0x0A05050F, 0x2F9A9AB5,
0x0E070709, 0x24121236, 0x1B80809B, 0xDFE2E23D, 0xCDEBEB26, 0x4E272769, 0x7FB2B2CD, 0xEA75759F,
0x1209091B, 0x1D83839E, 0x582C2C74, 0x341A1A2E, 0x361B1B2D, 0xDC6E6EB2, 0xB45A5AEE, 0x5BA0A0FB,
0xA45252F6, 0x763B3B4D, 0xB7D6D661, 0x7DB3B3CE, 0x5229297B, 0xDDE3E33E, 0x5E2F2F71, 0x13848497,
0xA65353F5, 0xB9D1D168, 0x00000000, 0xC1EDED2C, 0x40202060, 0xE3FCFC1F, 0x79B1B1C8, 0xB65B5BED,
0xD46A6ABE, 0x8DCBCB46, 0x67BEBED9, 0x7239394B, 0x944A4ADE, 0x984C4CD4, 0xB05858E8, 0x85CFCF4A,
0xBBD0D06B, 0xC5EFEF2A, 0x4FAAAAE5, 0xEDFBFB16, 0x864343C5, 0x9A4D4DD7, 0x66333355, 0x11858594,
0x8A4545CF, 0xE9F9F910, 0x04020206, 0xFE7F7F81, 0xA05050F0, 0x783C3C44, 0x259F9FBA, 0x4BA8A8E3,
0xA25151F3, 0x5DA3A3FE, 0x804040C0, 0x058F8F8A, 0x3F9292AD, 0x219D9DBC, 0x70383848, 0xF1F5F504,
0x63BCBCDF, 0x77B6B6C1, 0xAFDADA75, 0x42212163, 0x20101030, 0xE5FFFF1A, 0xFDF3F30E, 0xBFD2D26D,
0x81CDCD4C, 0x180C0C14, 0x26131335, 0xC3ECEC2F, 0xBE5F5FE1, 0x359797A2, 0x884444CC, 0x2E171739,
0x93C4C457, 0x55A7A7F2, 0xFC7E7E82, 0x7A3D3D47, 0xC86464AC, 0xBA5D5DE7, 0x3219192B, 0xE6737395,
0xC06060A0, 0x19818198, 0x9E4F4FD1, 0xA3DCDC7F, 0x44222266, 0x542A2A7E, 0x3B9090AB, 0x0B888883,
0x8C4646CA, 0xC7EEEE29, 0x6BB8B8D3, 0x2814143C, 0xA7DEDE79, 0xBC5E5EE2, 0x160B0B1D, 0xADDBDB76,
0xDBE0E03B, 0x64323256, 0x743A3A4E, 0x140A0A1E, 0x924949DB, 0x0C06060A, 0x4824246C, 0xB85C5CE4,
0x9FC2C25D, 0xBDD3D36E, 0x43ACACEF, 0xC46262A6, 0x399191A8, 0x319595A4, 0xD3E4E437, 0xF279798B,
0xD5E7E732, 0x8BC8C843, 0x6E373759, 0xDA6D6DB7, 0x018D8D8C, 0xB1D5D564, 0x9C4E4ED2, 0x49A9A9E0,
0xD86C6CB4, 0xAC5656FA, 0xF3F4F407, 0xCFEAEA25, 0xCA6565AF, 0xF47A7A8E, 0x47AEAEE9, 0x10080818,
0x6FBABAD5, 0xF0787888, 0x4A25256F, 0x5C2E2E72, 0x381C1C24, 0x57A6A6F1, 0x73B4B4C7, 0x97C6C651,
0xCBE8E823, 0xA1DDDD7C, 0xE874749C, 0x3E1F1F21, 0x964B4BDD, 0x61BDBDDC, 0x0D8B8B86, 0x0F8A8A85,
0xE0707090, 0x7C3E3E42, 0x71B5B5C4, 0xCC6666AA, 0x904848D8, 0x06030305, 0xF7F6F601, 0x1C0E0E12,
0xC26161A3, 0x6A35355F, 0xAE5757F9, 0x69B9B9D0, 0x17868691, 0x99C1C158, 0x3A1D1D27, 0x279E9EB9,
0xD9E1E138, 0xEBF8F813, 0x2B9898B3, 0x22111133, 0xD26969BB, 0xA9D9D970, 0x078E8E89, 0x339494A7,
0x2D9B9BB6, 0x3C1E1E22, 0x15878792, 0xC9E9E920, 0x87CECE49, 0xAA5555FF, 0x50282878, 0xA5DFDF7A,
0x038C8C8F, 0x59A1A1F8, 0x09898980, 0x1A0D0D17, 0x65BFBFDA, 0xD7E6E631, 0x844242C6, 0xD06868B8,
0x824141C3, 0x299999B0, 0x5A2D2D77, 0x1E0F0F11, 0x7BB0B0CB, 0xA85454FC, 0x6DBBBBD6, 0x2C16163A
);
/**
* Precomputed mixColumns table
*
* @see Crypt_Rijndael:_encryptBlock()
* @see Crypt_Rijndael:_decryptBlock()
* @var Array
* @access private
*/
var $t1 = array(
0xA5C66363, 0x84F87C7C, 0x99EE7777, 0x8DF67B7B, 0x0DFFF2F2, 0xBDD66B6B, 0xB1DE6F6F, 0x5491C5C5,
0x50603030, 0x03020101, 0xA9CE6767, 0x7D562B2B, 0x19E7FEFE, 0x62B5D7D7, 0xE64DABAB, 0x9AEC7676,
0x458FCACA, 0x9D1F8282, 0x4089C9C9, 0x87FA7D7D, 0x15EFFAFA, 0xEBB25959, 0xC98E4747, 0x0BFBF0F0,
0xEC41ADAD, 0x67B3D4D4, 0xFD5FA2A2, 0xEA45AFAF, 0xBF239C9C, 0xF753A4A4, 0x96E47272, 0x5B9BC0C0,
0xC275B7B7, 0x1CE1FDFD, 0xAE3D9393, 0x6A4C2626, 0x5A6C3636, 0x417E3F3F, 0x02F5F7F7, 0x4F83CCCC,
0x5C683434, 0xF451A5A5, 0x34D1E5E5, 0x08F9F1F1, 0x93E27171, 0x73ABD8D8, 0x53623131, 0x3F2A1515,
0x0C080404, 0x5295C7C7, 0x65462323, 0x5E9DC3C3, 0x28301818, 0xA1379696, 0x0F0A0505, 0xB52F9A9A,
0x090E0707, 0x36241212, 0x9B1B8080, 0x3DDFE2E2, 0x26CDEBEB, 0x694E2727, 0xCD7FB2B2, 0x9FEA7575,
0x1B120909, 0x9E1D8383, 0x74582C2C, 0x2E341A1A, 0x2D361B1B, 0xB2DC6E6E, 0xEEB45A5A, 0xFB5BA0A0,
0xF6A45252, 0x4D763B3B, 0x61B7D6D6, 0xCE7DB3B3, 0x7B522929, 0x3EDDE3E3, 0x715E2F2F, 0x97138484,
0xF5A65353, 0x68B9D1D1, 0x00000000, 0x2CC1EDED, 0x60402020, 0x1FE3FCFC, 0xC879B1B1, 0xEDB65B5B,
0xBED46A6A, 0x468DCBCB, 0xD967BEBE, 0x4B723939, 0xDE944A4A, 0xD4984C4C, 0xE8B05858, 0x4A85CFCF,
0x6BBBD0D0, 0x2AC5EFEF, 0xE54FAAAA, 0x16EDFBFB, 0xC5864343, 0xD79A4D4D, 0x55663333, 0x94118585,
0xCF8A4545, 0x10E9F9F9, 0x06040202, 0x81FE7F7F, 0xF0A05050, 0x44783C3C, 0xBA259F9F, 0xE34BA8A8,
0xF3A25151, 0xFE5DA3A3, 0xC0804040, 0x8A058F8F, 0xAD3F9292, 0xBC219D9D, 0x48703838, 0x04F1F5F5,
0xDF63BCBC, 0xC177B6B6, 0x75AFDADA, 0x63422121, 0x30201010, 0x1AE5FFFF, 0x0EFDF3F3, 0x6DBFD2D2,
0x4C81CDCD, 0x14180C0C, 0x35261313, 0x2FC3ECEC, 0xE1BE5F5F, 0xA2359797, 0xCC884444, 0x392E1717,
0x5793C4C4, 0xF255A7A7, 0x82FC7E7E, 0x477A3D3D, 0xACC86464, 0xE7BA5D5D, 0x2B321919, 0x95E67373,
0xA0C06060, 0x98198181, 0xD19E4F4F, 0x7FA3DCDC, 0x66442222, 0x7E542A2A, 0xAB3B9090, 0x830B8888,
0xCA8C4646, 0x29C7EEEE, 0xD36BB8B8, 0x3C281414, 0x79A7DEDE, 0xE2BC5E5E, 0x1D160B0B, 0x76ADDBDB,
0x3BDBE0E0, 0x56643232, 0x4E743A3A, 0x1E140A0A, 0xDB924949, 0x0A0C0606, 0x6C482424, 0xE4B85C5C,
0x5D9FC2C2, 0x6EBDD3D3, 0xEF43ACAC, 0xA6C46262, 0xA8399191, 0xA4319595, 0x37D3E4E4, 0x8BF27979,
0x32D5E7E7, 0x438BC8C8, 0x596E3737, 0xB7DA6D6D, 0x8C018D8D, 0x64B1D5D5, 0xD29C4E4E, 0xE049A9A9,
0xB4D86C6C, 0xFAAC5656, 0x07F3F4F4, 0x25CFEAEA, 0xAFCA6565, 0x8EF47A7A, 0xE947AEAE, 0x18100808,
0xD56FBABA, 0x88F07878, 0x6F4A2525, 0x725C2E2E, 0x24381C1C, 0xF157A6A6, 0xC773B4B4, 0x5197C6C6,
0x23CBE8E8, 0x7CA1DDDD, 0x9CE87474, 0x213E1F1F, 0xDD964B4B, 0xDC61BDBD, 0x860D8B8B, 0x850F8A8A,
0x90E07070, 0x427C3E3E, 0xC471B5B5, 0xAACC6666, 0xD8904848, 0x05060303, 0x01F7F6F6, 0x121C0E0E,
0xA3C26161, 0x5F6A3535, 0xF9AE5757, 0xD069B9B9, 0x91178686, 0x5899C1C1, 0x273A1D1D, 0xB9279E9E,
0x38D9E1E1, 0x13EBF8F8, 0xB32B9898, 0x33221111, 0xBBD26969, 0x70A9D9D9, 0x89078E8E, 0xA7339494,
0xB62D9B9B, 0x223C1E1E, 0x92158787, 0x20C9E9E9, 0x4987CECE, 0xFFAA5555, 0x78502828, 0x7AA5DFDF,
0x8F038C8C, 0xF859A1A1, 0x80098989, 0x171A0D0D, 0xDA65BFBF, 0x31D7E6E6, 0xC6844242, 0xB8D06868,
0xC3824141, 0xB0299999, 0x775A2D2D, 0x111E0F0F, 0xCB7BB0B0, 0xFCA85454, 0xD66DBBBB, 0x3A2C1616
);
/**
* Precomputed mixColumns table
*
* @see Crypt_Rijndael:_encryptBlock()
* @see Crypt_Rijndael:_decryptBlock()
* @var Array
* @access private
*/
var $t2 = array(
0x63A5C663, 0x7C84F87C, 0x7799EE77, 0x7B8DF67B, 0xF20DFFF2, 0x6BBDD66B, 0x6FB1DE6F, 0xC55491C5,
0x30506030, 0x01030201, 0x67A9CE67, 0x2B7D562B, 0xFE19E7FE, 0xD762B5D7, 0xABE64DAB, 0x769AEC76,
0xCA458FCA, 0x829D1F82, 0xC94089C9, 0x7D87FA7D, 0xFA15EFFA, 0x59EBB259, 0x47C98E47, 0xF00BFBF0,
0xADEC41AD, 0xD467B3D4, 0xA2FD5FA2, 0xAFEA45AF, 0x9CBF239C, 0xA4F753A4, 0x7296E472, 0xC05B9BC0,
0xB7C275B7, 0xFD1CE1FD, 0x93AE3D93, 0x266A4C26, 0x365A6C36, 0x3F417E3F, 0xF702F5F7, 0xCC4F83CC,
0x345C6834, 0xA5F451A5, 0xE534D1E5, 0xF108F9F1, 0x7193E271, 0xD873ABD8, 0x31536231, 0x153F2A15,
0x040C0804, 0xC75295C7, 0x23654623, 0xC35E9DC3, 0x18283018, 0x96A13796, 0x050F0A05, 0x9AB52F9A,
0x07090E07, 0x12362412, 0x809B1B80, 0xE23DDFE2, 0xEB26CDEB, 0x27694E27, 0xB2CD7FB2, 0x759FEA75,
0x091B1209, 0x839E1D83, 0x2C74582C, 0x1A2E341A, 0x1B2D361B, 0x6EB2DC6E, 0x5AEEB45A, 0xA0FB5BA0,
0x52F6A452, 0x3B4D763B, 0xD661B7D6, 0xB3CE7DB3, 0x297B5229, 0xE33EDDE3, 0x2F715E2F, 0x84971384,
0x53F5A653, 0xD168B9D1, 0x00000000, 0xED2CC1ED, 0x20604020, 0xFC1FE3FC, 0xB1C879B1, 0x5BEDB65B,
0x6ABED46A, 0xCB468DCB, 0xBED967BE, 0x394B7239, 0x4ADE944A, 0x4CD4984C, 0x58E8B058, 0xCF4A85CF,
0xD06BBBD0, 0xEF2AC5EF, 0xAAE54FAA, 0xFB16EDFB, 0x43C58643, 0x4DD79A4D, 0x33556633, 0x85941185,
0x45CF8A45, 0xF910E9F9, 0x02060402, 0x7F81FE7F, 0x50F0A050, 0x3C44783C, 0x9FBA259F, 0xA8E34BA8,
0x51F3A251, 0xA3FE5DA3, 0x40C08040, 0x8F8A058F, 0x92AD3F92, 0x9DBC219D, 0x38487038, 0xF504F1F5,
0xBCDF63BC, 0xB6C177B6, 0xDA75AFDA, 0x21634221, 0x10302010, 0xFF1AE5FF, 0xF30EFDF3, 0xD26DBFD2,
0xCD4C81CD, 0x0C14180C, 0x13352613, 0xEC2FC3EC, 0x5FE1BE5F, 0x97A23597, 0x44CC8844, 0x17392E17,
0xC45793C4, 0xA7F255A7, 0x7E82FC7E, 0x3D477A3D, 0x64ACC864, 0x5DE7BA5D, 0x192B3219, 0x7395E673,
0x60A0C060, 0x81981981, 0x4FD19E4F, 0xDC7FA3DC, 0x22664422, 0x2A7E542A, 0x90AB3B90, 0x88830B88,
0x46CA8C46, 0xEE29C7EE, 0xB8D36BB8, 0x143C2814, 0xDE79A7DE, 0x5EE2BC5E, 0x0B1D160B, 0xDB76ADDB,
0xE03BDBE0, 0x32566432, 0x3A4E743A, 0x0A1E140A, 0x49DB9249, 0x060A0C06, 0x246C4824, 0x5CE4B85C,
0xC25D9FC2, 0xD36EBDD3, 0xACEF43AC, 0x62A6C462, 0x91A83991, 0x95A43195, 0xE437D3E4, 0x798BF279,
0xE732D5E7, 0xC8438BC8, 0x37596E37, 0x6DB7DA6D, 0x8D8C018D, 0xD564B1D5, 0x4ED29C4E, 0xA9E049A9,
0x6CB4D86C, 0x56FAAC56, 0xF407F3F4, 0xEA25CFEA, 0x65AFCA65, 0x7A8EF47A, 0xAEE947AE, 0x08181008,
0xBAD56FBA, 0x7888F078, 0x256F4A25, 0x2E725C2E, 0x1C24381C, 0xA6F157A6, 0xB4C773B4, 0xC65197C6,
0xE823CBE8, 0xDD7CA1DD, 0x749CE874, 0x1F213E1F, 0x4BDD964B, 0xBDDC61BD, 0x8B860D8B, 0x8A850F8A,
0x7090E070, 0x3E427C3E, 0xB5C471B5, 0x66AACC66, 0x48D89048, 0x03050603, 0xF601F7F6, 0x0E121C0E,
0x61A3C261, 0x355F6A35, 0x57F9AE57, 0xB9D069B9, 0x86911786, 0xC15899C1, 0x1D273A1D, 0x9EB9279E,
0xE138D9E1, 0xF813EBF8, 0x98B32B98, 0x11332211, 0x69BBD269, 0xD970A9D9, 0x8E89078E, 0x94A73394,
0x9BB62D9B, 0x1E223C1E, 0x87921587, 0xE920C9E9, 0xCE4987CE, 0x55FFAA55, 0x28785028, 0xDF7AA5DF,
0x8C8F038C, 0xA1F859A1, 0x89800989, 0x0D171A0D, 0xBFDA65BF, 0xE631D7E6, 0x42C68442, 0x68B8D068,
0x41C38241, 0x99B02999, 0x2D775A2D, 0x0F111E0F, 0xB0CB7BB0, 0x54FCA854, 0xBBD66DBB, 0x163A2C16
);
/**
* Precomputed mixColumns table
*
* @see Crypt_Rijndael:_encryptBlock()
* @see Crypt_Rijndael:_decryptBlock()
* @var Array
* @access private
*/
var $t3 = array(
0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC,
0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B,
0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83,
0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A,
0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F,
0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA,
0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B,
0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713,
0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6,
0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85,
0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411,
0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B,
0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1,
0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF,
0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E,
0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6,
0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B,
0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD,
0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8,
0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2,
0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049,
0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810,
0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197,
0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F,
0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C,
0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927,
0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733,
0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5,
0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0,
0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
);
/**
* Precomputed invMixColumns table
*
* @see Crypt_Rijndael:_encryptBlock()
* @see Crypt_Rijndael:_decryptBlock()
* @var Array
* @access private
*/
var $dt0 = array(
0x51F4A750, 0x7E416553, 0x1A17A4C3, 0x3A275E96, 0x3BAB6BCB, 0x1F9D45F1, 0xACFA58AB, 0x4BE30393,
0x2030FA55, 0xAD766DF6, 0x88CC7691, 0xF5024C25, 0x4FE5D7FC, 0xC52ACBD7, 0x26354480, 0xB562A38F,
0xDEB15A49, 0x25BA1B67, 0x45EA0E98, 0x5DFEC0E1, 0xC32F7502, 0x814CF012, 0x8D4697A3, 0x6BD3F9C6,
0x038F5FE7, 0x15929C95, 0xBF6D7AEB, 0x955259DA, 0xD4BE832D, 0x587421D3, 0x49E06929, 0x8EC9C844,
0x75C2896A, 0xF48E7978, 0x99583E6B, 0x27B971DD, 0xBEE14FB6, 0xF088AD17, 0xC920AC66, 0x7DCE3AB4,
0x63DF4A18, 0xE51A3182, 0x97513360, 0x62537F45, 0xB16477E0, 0xBB6BAE84, 0xFE81A01C, 0xF9082B94,
0x70486858, 0x8F45FD19, 0x94DE6C87, 0x527BF8B7, 0xAB73D323, 0x724B02E2, 0xE31F8F57, 0x6655AB2A,
0xB2EB2807, 0x2FB5C203, 0x86C57B9A, 0xD33708A5, 0x302887F2, 0x23BFA5B2, 0x02036ABA, 0xED16825C,
0x8ACF1C2B, 0xA779B492, 0xF307F2F0, 0x4E69E2A1, 0x65DAF4CD, 0x0605BED5, 0xD134621F, 0xC4A6FE8A,
0x342E539D, 0xA2F355A0, 0x058AE132, 0xA4F6EB75, 0x0B83EC39, 0x4060EFAA, 0x5E719F06, 0xBD6E1051,
0x3E218AF9, 0x96DD063D, 0xDD3E05AE, 0x4DE6BD46, 0x91548DB5, 0x71C45D05, 0x0406D46F, 0x605015FF,
0x1998FB24, 0xD6BDE997, 0x894043CC, 0x67D99E77, 0xB0E842BD, 0x07898B88, 0xE7195B38, 0x79C8EEDB,
0xA17C0A47, 0x7C420FE9, 0xF8841EC9, 0x00000000, 0x09808683, 0x322BED48, 0x1E1170AC, 0x6C5A724E,
0xFD0EFFFB, 0x0F853856, 0x3DAED51E, 0x362D3927, 0x0A0FD964, 0x685CA621, 0x9B5B54D1, 0x24362E3A,
0x0C0A67B1, 0x9357E70F, 0xB4EE96D2, 0x1B9B919E, 0x80C0C54F, 0x61DC20A2, 0x5A774B69, 0x1C121A16,
0xE293BA0A, 0xC0A02AE5, 0x3C22E043, 0x121B171D, 0x0E090D0B, 0xF28BC7AD, 0x2DB6A8B9, 0x141EA9C8,
0x57F11985, 0xAF75074C, 0xEE99DDBB, 0xA37F60FD, 0xF701269F, 0x5C72F5BC, 0x44663BC5, 0x5BFB7E34,
0x8B432976, 0xCB23C6DC, 0xB6EDFC68, 0xB8E4F163, 0xD731DCCA, 0x42638510, 0x13972240, 0x84C61120,
0x854A247D, 0xD2BB3DF8, 0xAEF93211, 0xC729A16D, 0x1D9E2F4B, 0xDCB230F3, 0x0D8652EC, 0x77C1E3D0,
0x2BB3166C, 0xA970B999, 0x119448FA, 0x47E96422, 0xA8FC8CC4, 0xA0F03F1A, 0x567D2CD8, 0x223390EF,
0x87494EC7, 0xD938D1C1, 0x8CCAA2FE, 0x98D40B36, 0xA6F581CF, 0xA57ADE28, 0xDAB78E26, 0x3FADBFA4,
0x2C3A9DE4, 0x5078920D, 0x6A5FCC9B, 0x547E4662, 0xF68D13C2, 0x90D8B8E8, 0x2E39F75E, 0x82C3AFF5,
0x9F5D80BE, 0x69D0937C, 0x6FD52DA9, 0xCF2512B3, 0xC8AC993B, 0x10187DA7, 0xE89C636E, 0xDB3BBB7B,
0xCD267809, 0x6E5918F4, 0xEC9AB701, 0x834F9AA8, 0xE6956E65, 0xAAFFE67E, 0x21BCCF08, 0xEF15E8E6,
0xBAE79BD9, 0x4A6F36CE, 0xEA9F09D4, 0x29B07CD6, 0x31A4B2AF, 0x2A3F2331, 0xC6A59430, 0x35A266C0,
0x744EBC37, 0xFC82CAA6, 0xE090D0B0, 0x33A7D815, 0xF104984A, 0x41ECDAF7, 0x7FCD500E, 0x1791F62F,
0x764DD68D, 0x43EFB04D, 0xCCAA4D54, 0xE49604DF, 0x9ED1B5E3, 0x4C6A881B, 0xC12C1FB8, 0x4665517F,
0x9D5EEA04, 0x018C355D, 0xFA877473, 0xFB0B412E, 0xB3671D5A, 0x92DBD252, 0xE9105633, 0x6DD64713,
0x9AD7618C, 0x37A10C7A, 0x59F8148E, 0xEB133C89, 0xCEA927EE, 0xB761C935, 0xE11CE5ED, 0x7A47B13C,
0x9CD2DF59, 0x55F2733F, 0x1814CE79, 0x73C737BF, 0x53F7CDEA, 0x5FFDAA5B, 0xDF3D6F14, 0x7844DB86,
0xCAAFF381, 0xB968C43E, 0x3824342C, 0xC2A3405F, 0x161DC372, 0xBCE2250C, 0x283C498B, 0xFF0D9541,
0x39A80171, 0x080CB3DE, 0xD8B4E49C, 0x6456C190, 0x7BCB8461, 0xD532B670, 0x486C5C74, 0xD0B85742
);
/**
* Precomputed invMixColumns table
*
* @see Crypt_Rijndael:_encryptBlock()
* @see Crypt_Rijndael:_decryptBlock()
* @var Array
* @access private
*/
var $dt1 = array(
0x5051F4A7, 0x537E4165, 0xC31A17A4, 0x963A275E, 0xCB3BAB6B, 0xF11F9D45, 0xABACFA58, 0x934BE303,
0x552030FA, 0xF6AD766D, 0x9188CC76, 0x25F5024C, 0xFC4FE5D7, 0xD7C52ACB, 0x80263544, 0x8FB562A3,
0x49DEB15A, 0x6725BA1B, 0x9845EA0E, 0xE15DFEC0, 0x02C32F75, 0x12814CF0, 0xA38D4697, 0xC66BD3F9,
0xE7038F5F, 0x9515929C, 0xEBBF6D7A, 0xDA955259, 0x2DD4BE83, 0xD3587421, 0x2949E069, 0x448EC9C8,
0x6A75C289, 0x78F48E79, 0x6B99583E, 0xDD27B971, 0xB6BEE14F, 0x17F088AD, 0x66C920AC, 0xB47DCE3A,
0x1863DF4A, 0x82E51A31, 0x60975133, 0x4562537F, 0xE0B16477, 0x84BB6BAE, 0x1CFE81A0, 0x94F9082B,
0x58704868, 0x198F45FD, 0x8794DE6C, 0xB7527BF8, 0x23AB73D3, 0xE2724B02, 0x57E31F8F, 0x2A6655AB,
0x07B2EB28, 0x032FB5C2, 0x9A86C57B, 0xA5D33708, 0xF2302887, 0xB223BFA5, 0xBA02036A, 0x5CED1682,
0x2B8ACF1C, 0x92A779B4, 0xF0F307F2, 0xA14E69E2, 0xCD65DAF4, 0xD50605BE, 0x1FD13462, 0x8AC4A6FE,
0x9D342E53, 0xA0A2F355, 0x32058AE1, 0x75A4F6EB, 0x390B83EC, 0xAA4060EF, 0x065E719F, 0x51BD6E10,
0xF93E218A, 0x3D96DD06, 0xAEDD3E05, 0x464DE6BD, 0xB591548D, 0x0571C45D, 0x6F0406D4, 0xFF605015,
0x241998FB, 0x97D6BDE9, 0xCC894043, 0x7767D99E, 0xBDB0E842, 0x8807898B, 0x38E7195B, 0xDB79C8EE,
0x47A17C0A, 0xE97C420F, 0xC9F8841E, 0x00000000, 0x83098086, 0x48322BED, 0xAC1E1170, 0x4E6C5A72,
0xFBFD0EFF, 0x560F8538, 0x1E3DAED5, 0x27362D39, 0x640A0FD9, 0x21685CA6, 0xD19B5B54, 0x3A24362E,
0xB10C0A67, 0x0F9357E7, 0xD2B4EE96, 0x9E1B9B91, 0x4F80C0C5, 0xA261DC20, 0x695A774B, 0x161C121A,
0x0AE293BA, 0xE5C0A02A, 0x433C22E0, 0x1D121B17, 0x0B0E090D, 0xADF28BC7, 0xB92DB6A8, 0xC8141EA9,
0x8557F119, 0x4CAF7507, 0xBBEE99DD, 0xFDA37F60, 0x9FF70126, 0xBC5C72F5, 0xC544663B, 0x345BFB7E,
0x768B4329, 0xDCCB23C6, 0x68B6EDFC, 0x63B8E4F1, 0xCAD731DC, 0x10426385, 0x40139722, 0x2084C611,
0x7D854A24, 0xF8D2BB3D, 0x11AEF932, 0x6DC729A1, 0x4B1D9E2F, 0xF3DCB230, 0xEC0D8652, 0xD077C1E3,
0x6C2BB316, 0x99A970B9, 0xFA119448, 0x2247E964, 0xC4A8FC8C, 0x1AA0F03F, 0xD8567D2C, 0xEF223390,
0xC787494E, 0xC1D938D1, 0xFE8CCAA2, 0x3698D40B, 0xCFA6F581, 0x28A57ADE, 0x26DAB78E, 0xA43FADBF,
0xE42C3A9D, 0x0D507892, 0x9B6A5FCC, 0x62547E46, 0xC2F68D13, 0xE890D8B8, 0x5E2E39F7, 0xF582C3AF,
0xBE9F5D80, 0x7C69D093, 0xA96FD52D, 0xB3CF2512, 0x3BC8AC99, 0xA710187D, 0x6EE89C63, 0x7BDB3BBB,
0x09CD2678, 0xF46E5918, 0x01EC9AB7, 0xA8834F9A, 0x65E6956E, 0x7EAAFFE6, 0x0821BCCF, 0xE6EF15E8,
0xD9BAE79B, 0xCE4A6F36, 0xD4EA9F09, 0xD629B07C, 0xAF31A4B2, 0x312A3F23, 0x30C6A594, 0xC035A266,
0x37744EBC, 0xA6FC82CA, 0xB0E090D0, 0x1533A7D8, 0x4AF10498, 0xF741ECDA, 0x0E7FCD50, 0x2F1791F6,
0x8D764DD6, 0x4D43EFB0, 0x54CCAA4D, 0xDFE49604, 0xE39ED1B5, 0x1B4C6A88, 0xB8C12C1F, 0x7F466551,
0x049D5EEA, 0x5D018C35, 0x73FA8774, 0x2EFB0B41, 0x5AB3671D, 0x5292DBD2, 0x33E91056, 0x136DD647,
0x8C9AD761, 0x7A37A10C, 0x8E59F814, 0x89EB133C, 0xEECEA927, 0x35B761C9, 0xEDE11CE5, 0x3C7A47B1,
0x599CD2DF, 0x3F55F273, 0x791814CE, 0xBF73C737, 0xEA53F7CD, 0x5B5FFDAA, 0x14DF3D6F, 0x867844DB,
0x81CAAFF3, 0x3EB968C4, 0x2C382434, 0x5FC2A340, 0x72161DC3, 0x0CBCE225, 0x8B283C49, 0x41FF0D95,
0x7139A801, 0xDE080CB3, 0x9CD8B4E4, 0x906456C1, 0x617BCB84, 0x70D532B6, 0x74486C5C, 0x42D0B857
);
/**
* Precomputed invMixColumns table
*
* @see Crypt_Rijndael:_encryptBlock()
* @see Crypt_Rijndael:_decryptBlock()
* @var Array
* @access private
*/
var $dt2 = array(
0xA75051F4, 0x65537E41, 0xA4C31A17, 0x5E963A27, 0x6BCB3BAB, 0x45F11F9D, 0x58ABACFA, 0x03934BE3,
0xFA552030, 0x6DF6AD76, 0x769188CC, 0x4C25F502, 0xD7FC4FE5, 0xCBD7C52A, 0x44802635, 0xA38FB562,
0x5A49DEB1, 0x1B6725BA, 0x0E9845EA, 0xC0E15DFE, 0x7502C32F, 0xF012814C, 0x97A38D46, 0xF9C66BD3,
0x5FE7038F, 0x9C951592, 0x7AEBBF6D, 0x59DA9552, 0x832DD4BE, 0x21D35874, 0x692949E0, 0xC8448EC9,
0x896A75C2, 0x7978F48E, 0x3E6B9958, 0x71DD27B9, 0x4FB6BEE1, 0xAD17F088, 0xAC66C920, 0x3AB47DCE,
0x4A1863DF, 0x3182E51A, 0x33609751, 0x7F456253, 0x77E0B164, 0xAE84BB6B, 0xA01CFE81, 0x2B94F908,
0x68587048, 0xFD198F45, 0x6C8794DE, 0xF8B7527B, 0xD323AB73, 0x02E2724B, 0x8F57E31F, 0xAB2A6655,
0x2807B2EB, 0xC2032FB5, 0x7B9A86C5, 0x08A5D337, 0x87F23028, 0xA5B223BF, 0x6ABA0203, 0x825CED16,
0x1C2B8ACF, 0xB492A779, 0xF2F0F307, 0xE2A14E69, 0xF4CD65DA, 0xBED50605, 0x621FD134, 0xFE8AC4A6,
0x539D342E, 0x55A0A2F3, 0xE132058A, 0xEB75A4F6, 0xEC390B83, 0xEFAA4060, 0x9F065E71, 0x1051BD6E,
0x8AF93E21, 0x063D96DD, 0x05AEDD3E, 0xBD464DE6, 0x8DB59154, 0x5D0571C4, 0xD46F0406, 0x15FF6050,
0xFB241998, 0xE997D6BD, 0x43CC8940, 0x9E7767D9, 0x42BDB0E8, 0x8B880789, 0x5B38E719, 0xEEDB79C8,
0x0A47A17C, 0x0FE97C42, 0x1EC9F884, 0x00000000, 0x86830980, 0xED48322B, 0x70AC1E11, 0x724E6C5A,
0xFFFBFD0E, 0x38560F85, 0xD51E3DAE, 0x3927362D, 0xD9640A0F, 0xA621685C, 0x54D19B5B, 0x2E3A2436,
0x67B10C0A, 0xE70F9357, 0x96D2B4EE, 0x919E1B9B, 0xC54F80C0, 0x20A261DC, 0x4B695A77, 0x1A161C12,
0xBA0AE293, 0x2AE5C0A0, 0xE0433C22, 0x171D121B, 0x0D0B0E09, 0xC7ADF28B, 0xA8B92DB6, 0xA9C8141E,
0x198557F1, 0x074CAF75, 0xDDBBEE99, 0x60FDA37F, 0x269FF701, 0xF5BC5C72, 0x3BC54466, 0x7E345BFB,
0x29768B43, 0xC6DCCB23, 0xFC68B6ED, 0xF163B8E4, 0xDCCAD731, 0x85104263, 0x22401397, 0x112084C6,
0x247D854A, 0x3DF8D2BB, 0x3211AEF9, 0xA16DC729, 0x2F4B1D9E, 0x30F3DCB2, 0x52EC0D86, 0xE3D077C1,
0x166C2BB3, 0xB999A970, 0x48FA1194, 0x642247E9, 0x8CC4A8FC, 0x3F1AA0F0, 0x2CD8567D, 0x90EF2233,
0x4EC78749, 0xD1C1D938, 0xA2FE8CCA, 0x0B3698D4, 0x81CFA6F5, 0xDE28A57A, 0x8E26DAB7, 0xBFA43FAD,
0x9DE42C3A, 0x920D5078, 0xCC9B6A5F, 0x4662547E, 0x13C2F68D, 0xB8E890D8, 0xF75E2E39, 0xAFF582C3,
0x80BE9F5D, 0x937C69D0, 0x2DA96FD5, 0x12B3CF25, 0x993BC8AC, 0x7DA71018, 0x636EE89C, 0xBB7BDB3B,
0x7809CD26, 0x18F46E59, 0xB701EC9A, 0x9AA8834F, 0x6E65E695, 0xE67EAAFF, 0xCF0821BC, 0xE8E6EF15,
0x9BD9BAE7, 0x36CE4A6F, 0x09D4EA9F, 0x7CD629B0, 0xB2AF31A4, 0x23312A3F, 0x9430C6A5, 0x66C035A2,
0xBC37744E, 0xCAA6FC82, 0xD0B0E090, 0xD81533A7, 0x984AF104, 0xDAF741EC, 0x500E7FCD, 0xF62F1791,
0xD68D764D, 0xB04D43EF, 0x4D54CCAA, 0x04DFE496, 0xB5E39ED1, 0x881B4C6A, 0x1FB8C12C, 0x517F4665,
0xEA049D5E, 0x355D018C, 0x7473FA87, 0x412EFB0B, 0x1D5AB367, 0xD25292DB, 0x5633E910, 0x47136DD6,
0x618C9AD7, 0x0C7A37A1, 0x148E59F8, 0x3C89EB13, 0x27EECEA9, 0xC935B761, 0xE5EDE11C, 0xB13C7A47,
0xDF599CD2, 0x733F55F2, 0xCE791814, 0x37BF73C7, 0xCDEA53F7, 0xAA5B5FFD, 0x6F14DF3D, 0xDB867844,
0xF381CAAF, 0xC43EB968, 0x342C3824, 0x405FC2A3, 0xC372161D, 0x250CBCE2, 0x498B283C, 0x9541FF0D,
0x017139A8, 0xB3DE080C, 0xE49CD8B4, 0xC1906456, 0x84617BCB, 0xB670D532, 0x5C74486C, 0x5742D0B8
);
/**
* Precomputed invMixColumns table
*
* @see Crypt_Rijndael:_encryptBlock()
* @see Crypt_Rijndael:_decryptBlock()
* @var Array
* @access private
*/
var $dt3 = array(
0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E,
0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D,
0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9,
0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66,
0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED,
0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4,
0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD,
0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60,
0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79,
0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C,
0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24,
0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C,
0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814,
0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B,
0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084,
0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077,
0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22,
0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F,
0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582,
0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB,
0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF,
0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035,
0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17,
0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46,
0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D,
0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A,
0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678,
0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF,
0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0
);
/**
* The SubByte S-Box
*
* @see Crypt_Rijndael::_encryptBlock()
* @var Array
* @access private
*/
var $sbox = array(
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
);
/**
* The inverse SubByte S-Box
*
* @see Crypt_Rijndael::_decryptBlock()
* @var Array
* @access private
*/
var $isbox = array(
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
);
/**
* Sets the key.
*
* Keys can be of any length. Rijndael, itself, requires the use of a key that's between 128-bits and 256-bits long and
* whose length is a multiple of 32. If the key is less than 256-bits and the key length isn't set, we round the length
* up to the closest valid key length, padding $key with null bytes. If the key is more than 256-bits, we trim the
* excess bits.
*
* If the key is not explicitly set, it'll be assumed to be all null bytes.
*
* Note: 160/224-bit keys must explicitly set by setKeyLength(), otherwise they will be round/pad up to 192/256 bits.
*
* @see Crypt_Base:setKey()
* @see setKeyLength()
* @access public
* @param String $key
*/
function setKey($key)
{
parent::setKey($key);
if (!$this->explicit_key_length) {
$length = strlen($key);
switch (true) {
case $length <= 16:
$this->key_size = 16;
break;
case $length <= 20:
$this->key_size = 20;
break;
case $length <= 24:
$this->key_size = 24;
break;
case $length <= 28:
$this->key_size = 28;
break;
default:
$this->key_size = 32;
}
$this->_setupEngine();
}
}
/**
* Sets the key length
* Sets the key length.
*
* Valid key lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
* 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
@ -736,30 +186,28 @@ class Crypt_Rijndael extends Crypt_Base
* This results then in slower encryption.
*
* @access public
* @param Integer $length
* @param int $length
*/
function setKeyLength($length)
{
switch (true) {
case $length == 160:
$this->key_size = 20;
break;
case $length == 224:
$this->key_size = 28;
break;
case $length <= 128:
$this->key_size = 16;
$this->key_length = 16;
break;
case $length <= 160:
$this->key_length = 20;
break;
case $length <= 192:
$this->key_size = 24;
$this->key_length = 24;
break;
case $length <= 224:
$this->key_length = 28;
break;
default:
$this->key_size = 32;
$this->key_length = 32;
}
$this->explicit_key_length = true;
$this->changed = true;
$this->_setupEngine();
parent::setKeyLength($length);
}
/**
@ -769,110 +217,71 @@ class Crypt_Rijndael extends Crypt_Base
* 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
*
* @access public
* @param Integer $length
* @param int $length
*/
function setBlockLength($length)
{
$length >>= 5;
if ($length > 8) {
$length = 8;
} else if ($length < 4) {
} elseif ($length < 4) {
$length = 4;
}
$this->Nb = $length;
$this->block_size = $length << 2;
$this->changed = true;
$this->_setupEngine();
$this->_setEngine();
}
/**
* Setup the fastest possible $engine
* Test for engine validity
*
* Determines if the mcrypt (MODE_MCRYPT) $engine available
* and usable for the current $block_size and $key_size.
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
*
* If not, the slower MODE_INTERNAL $engine will be set.
*
* @see setKey()
* @see setKeyLength()
* @see setBlockLength()
* @access private
* @see \phpseclib\Crypt\Base::__construct()
* @param int $engine
* @access public
* @return bool
*/
function _setupEngine()
function isValidEngine($engine)
{
if (constant('CRYPT_' . $this->const_namespace . '_MODE') == CRYPT_MODE_INTERNAL) {
// No mcrypt support at all for rijndael
return;
}
// The required mcrypt module name for the current $block_size of rijndael
$cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3);
// Determining the availibility/usability of $cipher_name_mcrypt
switch (true) {
case $this->key_size % 8: // mcrypt is not usable for 160/224-bit keys, only for 128/192/256-bit keys
case !in_array($cipher_name_mcrypt, mcrypt_list_algorithms()): // $cipher_name_mcrypt is not available for the current $block_size
$engine = CRYPT_MODE_INTERNAL;
switch ($engine) {
case self::ENGINE_OPENSSL:
if ($this->block_size != 16) {
return false;
}
$this->cipher_name_openssl_ecb = 'aes-' . ($this->key_length << 3) . '-ecb';
$this->cipher_name_openssl = 'aes-' . ($this->key_length << 3) . '-' . $this->_openssl_translate_mode();
break;
default:
$engine = CRYPT_MODE_MCRYPT;
case self::ENGINE_MCRYPT:
$this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3);
if ($this->key_length % 8) { // is it a 160/224-bit key?
// mcrypt is not usable for them, only for 128/192/256-bit keys
return false;
}
}
if ($this->engine == $engine && $this->cipher_name_mcrypt == $cipher_name_mcrypt) {
// allready set, so we not unnecessary close $this->enmcrypt/demcrypt/ecb
return;
}
// Set the $engine
$this->engine = $engine;
$this->cipher_name_mcrypt = $cipher_name_mcrypt;
if ($this->enmcrypt) {
// Closing the current mcrypt resource(s). _mcryptSetup() will, if needed,
// (re)open them with the module named in $this->cipher_name_mcrypt
mcrypt_module_close($this->enmcrypt);
mcrypt_module_close($this->demcrypt);
$this->enmcrypt = null;
$this->demcrypt = null;
if ($this->ecb) {
mcrypt_module_close($this->ecb);
$this->ecb = null;
}
}
}
/**
* Setup the CRYPT_MODE_MCRYPT $engine
*
* @see Crypt_Base::_setupMcrypt()
* @access private
*/
function _setupMcrypt()
{
$this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, "\0");
parent::_setupMcrypt();
return parent::isValidEngine($engine);
}
/**
* Encrypts a block
*
* @access private
* @param String $in
* @return String
* @param string $in
* @return string
*/
function _encryptBlock($in)
{
static $t0, $t1, $t2, $t3, $sbox;
if (!$t0) {
for ($i = 0; $i < 256; ++$i) {
$t0[] = (int)$this->t0[$i];
$t1[] = (int)$this->t1[$i];
$t2[] = (int)$this->t2[$i];
$t3[] = (int)$this->t3[$i];
$sbox[] = (int)$this->sbox[$i];
}
static $tables;
if (empty($tables)) {
$tables = &$this->_getTables();
}
$t0 = $tables[0];
$t1 = $tables[1];
$t2 = $tables[2];
$t3 = $tables[3];
$sbox = $tables[4];
$state = array();
$words = unpack('N*', $in);
@ -883,9 +292,9 @@ class Crypt_Rijndael extends Crypt_Base
$Nr = $this->Nr;
// addRoundKey
$i = -1;
$wc = $Nb - 1;
foreach ($words as $word) {
$state[] = $word ^ $w[0][++$i];
$state[] = $word ^ $w[++$wc];
}
// fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
@ -908,7 +317,7 @@ class Crypt_Rijndael extends Crypt_Base
$t1[$state[$j] >> 16 & 0x000000FF] ^
$t2[$state[$k] >> 8 & 0x000000FF] ^
$t3[$state[$l] & 0x000000FF] ^
$w[$round][$i];
$w[++$wc];
++$i;
$j = ($j + 1) % $Nb;
$k = ($k + 1) % $Nb;
@ -935,7 +344,7 @@ class Crypt_Rijndael extends Crypt_Base
($state[$j] & 0x00FF0000) ^
($state[$k] & 0x0000FF00) ^
($state[$l] & 0x000000FF) ^
$w[$Nr][$i];
$w[$i];
++$i;
$j = ($j + 1) % $Nb;
$k = ($k + 1) % $Nb;
@ -960,21 +369,20 @@ class Crypt_Rijndael extends Crypt_Base
* Decrypts a block
*
* @access private
* @param String $in
* @return String
* @param string $in
* @return string
*/
function _decryptBlock($in)
{
static $dt0, $dt1, $dt2, $dt3, $isbox;
if (!$dt0) {
for ($i = 0; $i < 256; ++$i) {
$dt0[] = (int)$this->dt0[$i];
$dt1[] = (int)$this->dt1[$i];
$dt2[] = (int)$this->dt2[$i];
$dt3[] = (int)$this->dt3[$i];
$isbox[] = (int)$this->isbox[$i];
}
static $invtables;
if (empty($invtables)) {
$invtables = &$this->_getInvTables();
}
$dt0 = $invtables[0];
$dt1 = $invtables[1];
$dt2 = $invtables[2];
$dt3 = $invtables[3];
$isbox = $invtables[4];
$state = array();
$words = unpack('N*', $in);
@ -985,9 +393,9 @@ class Crypt_Rijndael extends Crypt_Base
$Nr = $this->Nr;
// addRoundKey
$i = -1;
$wc = $Nb - 1;
foreach ($words as $word) {
$state[] = $word ^ $dw[$Nr][++$i];
$state[] = $word ^ $dw[++$wc];
}
$temp = array();
@ -1002,7 +410,7 @@ class Crypt_Rijndael extends Crypt_Base
$dt1[$state[$j] >> 16 & 0x000000FF] ^
$dt2[$state[$k] >> 8 & 0x000000FF] ^
$dt3[$state[$l] & 0x000000FF] ^
$dw[$round][$i];
$dw[++$wc];
++$i;
$j = ($j + 1) % $Nb;
$k = ($k + 1) % $Nb;
@ -1023,10 +431,10 @@ class Crypt_Rijndael extends Crypt_Base
($state[$k] & 0x0000FF00) |
($state[$l] & 0x000000FF);
$temp[$i] = $dw[0][$i] ^ ($isbox[$word & 0x000000FF] |
($isbox[$word >> 8 & 0x000000FF] << 8) |
($isbox[$word >> 16 & 0x000000FF] << 16) |
($isbox[$word >> 24 & 0x000000FF] << 24));
$temp[$i] = $dw[$i] ^ ($isbox[$word & 0x000000FF] |
($isbox[$word >> 8 & 0x000000FF] << 8) |
($isbox[$word >> 16 & 0x000000FF] << 16) |
($isbox[$word >> 24 & 0x000000FF] << 24));
++$i;
$j = ($j + 1) % $Nb;
$k = ($k + 1) % $Nb;
@ -1050,7 +458,7 @@ class Crypt_Rijndael extends Crypt_Base
/**
* Setup the key (expansion)
*
* @see Crypt_Base::_setupKey()
* @see \phpseclib\Crypt\Base::_setupKey()
* @access private
*/
function _setupKey()
@ -1066,15 +474,13 @@ class Crypt_Rijndael extends Crypt_Base
0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
);
$this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, "\0");
if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_size === $this->kl['key_size'] && $this->block_size === $this->kl['block_size']) {
if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) {
// already expanded
return;
}
$this->kl = array('key' => $this->key, 'key_size' => $this->key_size, 'block_size' => $this->block_size);
$this->kl = array('key' => $this->key, 'key_length' => $this->key_length, 'block_size' => $this->block_size);
$this->Nk = $this->key_size >> 2;
$this->Nk = $this->key_length >> 2;
// see Rijndael-ammended.pdf#page=44
$this->Nr = max($this->Nk, $this->Nb) + 6;
@ -1107,7 +513,7 @@ class Crypt_Rijndael extends Crypt_Base
// with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.
$temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord
$temp = $this->_subWord($temp) ^ $rcon[$i / $this->Nk];
} else if ($this->Nk > 6 && $i % $this->Nk == 4) {
} elseif ($this->Nk > 6 && $i % $this->Nk == 4) {
$temp = $this->_subWord($temp);
}
$w[$i] = $w[$i - $this->Nk] ^ $temp;
@ -1120,6 +526,7 @@ class Crypt_Rijndael extends Crypt_Base
// 1. Apply the Key Expansion.
// 2. Apply InvMixColumn to all Round Keys except the first and the last one."
// also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher"
list($dt0, $dt1, $dt2, $dt3) = $this->_getInvTables();
$temp = $this->w = $this->dw = array();
for ($i = $row = $col = 0; $i < $length; $i++, $col++) {
if ($col == $this->Nb) {
@ -1130,10 +537,10 @@ class Crypt_Rijndael extends Crypt_Base
$j = 0;
while ($j < $this->Nb) {
$dw = $this->_subWord($this->w[$row][$j]);
$temp[$j] = $this->dt0[$dw >> 24 & 0x000000FF] ^
$this->dt1[$dw >> 16 & 0x000000FF] ^
$this->dt2[$dw >> 8 & 0x000000FF] ^
$this->dt3[$dw & 0x000000FF];
$temp[$j] = $dt0[$dw >> 24 & 0x000000FF] ^
$dt1[$dw >> 16 & 0x000000FF] ^
$dt2[$dw >> 8 & 0x000000FF] ^
$dt3[$dw & 0x000000FF];
$j++;
}
$this->dw[$row] = $temp;
@ -1147,31 +554,32 @@ class Crypt_Rijndael extends Crypt_Base
$this->dw[$row] = $this->w[$row];
// In case of $this->use_inline_crypt === true we have to use 1-dim key arrays (both ascending)
if ($this->use_inline_crypt) {
$this->dw = array_reverse($this->dw);
$w = array_pop($this->w);
$dw = array_pop($this->dw);
foreach ($this->w as $r => $wr) {
foreach ($wr as $c => $wc) {
$w[] = $wc;
$dw[] = $this->dw[$r][$c];
}
// Converting to 1-dim key arrays (both ascending)
$this->dw = array_reverse($this->dw);
$w = array_pop($this->w);
$dw = array_pop($this->dw);
foreach ($this->w as $r => $wr) {
foreach ($wr as $c => $wc) {
$w[] = $wc;
$dw[] = $this->dw[$r][$c];
}
$this->w = $w;
$this->dw = $dw;
}
$this->w = $w;
$this->dw = $dw;
}
/**
* Performs S-Box substitutions
*
* @access private
* @param Integer $word
* @param int $word
*/
function _subWord($word)
{
$sbox = $this->sbox;
static $sbox;
if (empty($sbox)) {
list(, , , , $sbox) = $this->_getTables();
}
return $sbox[$word & 0x000000FF] |
($sbox[$word >> 8 & 0x000000FF] << 8) |
@ -1179,10 +587,183 @@ class Crypt_Rijndael extends Crypt_Base
($sbox[$word >> 24 & 0x000000FF] << 24);
}
/**
* Provides the mixColumns and sboxes tables
*
* @see self::_encryptBlock()
* @see self::_setupInlineCrypt()
* @see self::_subWord()
* @access private
* @return array &$tables
*/
function &_getTables()
{
static $tables;
if (empty($tables)) {
// according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
// precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
// those are the names we'll use.
$t3 = array_map('intval', array(
// with array_map('intval', ...) we ensure we have only int's and not
// some slower floats converted by php automatically on high values
0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC,
0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B,
0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83,
0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A,
0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F,
0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA,
0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B,
0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713,
0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6,
0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85,
0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411,
0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B,
0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1,
0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF,
0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E,
0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6,
0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B,
0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD,
0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8,
0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2,
0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049,
0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810,
0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197,
0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F,
0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C,
0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927,
0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733,
0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5,
0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0,
0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
));
foreach ($t3 as $t3i) {
$t0[] = (($t3i << 24) & 0xFF000000) | (($t3i >> 8) & 0x00FFFFFF);
$t1[] = (($t3i << 16) & 0xFFFF0000) | (($t3i >> 16) & 0x0000FFFF);
$t2[] = (($t3i << 8) & 0xFFFFFF00) | (($t3i >> 24) & 0x000000FF);
}
$tables = array(
// The Precomputed mixColumns tables t0 - t3
$t0,
$t1,
$t2,
$t3,
// The SubByte S-Box
array(
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
)
);
}
return $tables;
}
/**
* Provides the inverse mixColumns and inverse sboxes tables
*
* @see self::_decryptBlock()
* @see self::_setupInlineCrypt()
* @see self::_setupKey()
* @access private
* @return array &$tables
*/
function &_getInvTables()
{
static $tables;
if (empty($tables)) {
$dt3 = array_map('intval', array(
0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E,
0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D,
0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9,
0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66,
0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED,
0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4,
0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD,
0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60,
0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79,
0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C,
0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24,
0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C,
0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814,
0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B,
0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084,
0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077,
0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22,
0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F,
0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582,
0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB,
0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF,
0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035,
0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17,
0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46,
0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D,
0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A,
0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678,
0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF,
0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0
));
foreach ($dt3 as $dt3i) {
$dt0[] = (($dt3i << 24) & 0xFF000000) | (($dt3i >> 8) & 0x00FFFFFF);
$dt1[] = (($dt3i << 16) & 0xFFFF0000) | (($dt3i >> 16) & 0x0000FFFF);
$dt2[] = (($dt3i << 8) & 0xFFFFFF00) | (($dt3i >> 24) & 0x000000FF);
};
$tables = array(
// The Precomputed inverse mixColumns tables dt0 - dt3
$dt0,
$dt1,
$dt2,
$dt3,
// The inverse SubByte S-Box
array(
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
)
);
}
return $tables;
}
/**
* Setup the performance-optimized function for de/encrypt()
*
* @see Crypt_Base::_setupInlineCrypt()
* @see \phpseclib\Crypt\Base::_setupInlineCrypt()
* @access private
*/
function _setupInlineCrypt()
@ -1191,44 +772,52 @@ class Crypt_Rijndael extends Crypt_Base
// So here we are'nt under the same heavy timing-stress as we are in _de/encryptBlock() or de/encrypt().
// However...the here generated function- $code, stored as php callback in $this->inline_crypt, must work as fast as even possible.
$lambda_functions =& Crypt_Rijndael::_getLambdaFunctions();
$lambda_functions =& self::_getLambdaFunctions();
// The first 10 generated $lambda_functions will use the key-words hardcoded for better performance.
// For memory reason we limit those ultra-optimized functions.
// After that, we use pure (extracted) integer vars for the key-words which is faster than accessing them via array.
if (count($lambda_functions) < 10) {
$w = $this->w;
$dw = $this->dw;
$init_encrypt = '';
$init_decrypt = '';
} else {
for ($i = 0, $cw = count($this->w); $i < $cw; ++$i) {
$w[] = '$w[' . $i . ']';
$dw[] = '$dw[' . $i . ']';
}
$init_encrypt = '$w = $self->w;';
$init_decrypt = '$dw = $self->dw;';
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
// (Currently, for Crypt_Rijndael/AES, one generated $lambda_function cost on php5.5@32bit ~80kb unfreeable mem and ~130kb on php5.5@64bit)
// After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
$gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
// Generation of a uniqe hash for our generated code
$code_hash = "Crypt_Rijndael, {$this->mode}, {$this->Nr}, {$this->Nb}";
if ($gen_hi_opt_code) {
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
}
$code_hash = md5(str_pad("Crypt_Rijndael, {$this->mode}, {$this->block_size}, ", 32, "\0") . implode(',', $w));
if (!isset($lambda_functions[$code_hash])) {
switch (true) {
case $gen_hi_opt_code:
// The hi-optimized $lambda_functions will use the key-words hardcoded for better performance.
$w = $this->w;
$dw = $this->dw;
$init_encrypt = '';
$init_decrypt = '';
break;
default:
for ($i = 0, $cw = count($this->w); $i < $cw; ++$i) {
$w[] = '$w[' . $i . ']';
$dw[] = '$dw[' . $i . ']';
}
$init_encrypt = '$w = $self->w;';
$init_decrypt = '$dw = $self->dw;';
}
$Nr = $this->Nr;
$Nb = $this->Nb;
$c = $this->c;
// Generating encrypt code:
$init_encrypt.= '
static $t0, $t1, $t2, $t3, $sbox;
if (!$t0) {
for ($i = 0; $i < 256; ++$i) {
$t0[$i] = (int)$self->t0[$i];
$t1[$i] = (int)$self->t1[$i];
$t2[$i] = (int)$self->t2[$i];
$t3[$i] = (int)$self->t3[$i];
$sbox[$i] = (int)$self->sbox[$i];
}
static $tables;
if (empty($tables)) {
$tables = &$self->_getTables();
}
$t0 = $tables[0];
$t1 = $tables[1];
$t2 = $tables[2];
$t3 = $tables[3];
$sbox = $tables[4];
';
$s = 'e';
@ -1267,26 +856,25 @@ class Crypt_Rijndael extends Crypt_Base
$encrypt_block .= '$in = pack("N*"'."\n";
for ($i = 0; $i < $Nb; ++$i) {
$encrypt_block.= ',
($'.$e.$i .' & 0xFF000000) ^
($'.$e.(($i + $c[1]) % $Nb).' & 0x00FF0000) ^
($'.$e.(($i + $c[2]) % $Nb).' & 0x0000FF00) ^
($'.$e.(($i + $c[3]) % $Nb).' & 0x000000FF) ^
($'.$e.$i .' & '.((int)0xFF000000).') ^
($'.$e.(($i + $c[1]) % $Nb).' & 0x00FF0000 ) ^
($'.$e.(($i + $c[2]) % $Nb).' & 0x0000FF00 ) ^
($'.$e.(($i + $c[3]) % $Nb).' & 0x000000FF ) ^
'.$w[$i]."\n";
}
$encrypt_block .= ');';
// Generating decrypt code:
$init_decrypt.= '
static $dt0, $dt1, $dt2, $dt3, $isbox;
if (!$dt0) {
for ($i = 0; $i < 256; ++$i) {
$dt0[$i] = (int)$self->dt0[$i];
$dt1[$i] = (int)$self->dt1[$i];
$dt2[$i] = (int)$self->dt2[$i];
$dt3[$i] = (int)$self->dt3[$i];
$isbox[$i] = (int)$self->isbox[$i];
}
static $invtables;
if (empty($invtables)) {
$invtables = &$self->_getInvTables();
}
$dt0 = $invtables[0];
$dt1 = $invtables[1];
$dt2 = $invtables[2];
$dt3 = $invtables[3];
$isbox = $invtables[4];
';
$s = 'e';
@ -1325,10 +913,10 @@ class Crypt_Rijndael extends Crypt_Base
$decrypt_block .= '$in = pack("N*"'."\n";
for ($i = 0; $i < $Nb; ++$i) {
$decrypt_block.= ',
($'.$e.$i. ' & 0xFF000000) ^
($'.$e.(($Nb + $i - $c[1]) % $Nb).' & 0x00FF0000) ^
($'.$e.(($Nb + $i - $c[2]) % $Nb).' & 0x0000FF00) ^
($'.$e.(($Nb + $i - $c[3]) % $Nb).' & 0x000000FF) ^
($'.$e.$i. ' & '.((int)0xFF000000).') ^
($'.$e.(($Nb + $i - $c[1]) % $Nb).' & 0x00FF0000 ) ^
($'.$e.(($Nb + $i - $c[2]) % $Nb).' & 0x0000FF00 ) ^
($'.$e.(($Nb + $i - $c[3]) % $Nb).' & 0x000000FF ) ^
'.$dw[$i]."\n";
}
$decrypt_block .= ');';

View file

@ -5,14 +5,14 @@
*
* Uses mcrypt, if available, and an internal implementation, otherwise. Operates in the EDE3 mode (encrypt-decrypt-encrypt).
*
* PHP versions 4 and 5
* PHP version 5
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/TripleDES.php';
* include 'vendor/autoload.php';
*
* $des = new Crypt_TripleDES();
* $des = new \phpseclib\Crypt\TripleDES();
*
* $des->setKey('abcdefghijklmnopqrstuvwx');
*
@ -26,99 +26,64 @@
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_TripleDES
* @package TripleDES
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_DES
*/
if (!class_exists('Crypt_DES')) {
include_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', -2);
/**
* 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);
namespace phpseclib\Crypt;
/**
* Pure-PHP implementation of Triple DES.
*
* @package Crypt_TripleDES
* @package TripleDES
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Crypt_TripleDES extends Crypt_DES
class TripleDES extends DES
{
/**
* The default password key_size used by setPassword()
* Encrypt / decrypt using inner chaining
*
* @see Crypt_DES::password_key_size
* @see Crypt_Base::password_key_size
* @see Crypt_Base::setPassword()
* @var Integer
* Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (self::MODE_CBC3).
*/
const MODE_3CBC = -2;
/**
* Encrypt / decrypt using outer chaining
*
* Outer chaining is used by SSH-2 and when the mode is set to \phpseclib\Crypt\Base::MODE_CBC.
*/
const MODE_CBC3 = Base::MODE_CBC;
/**
* Key Length (in bytes)
*
* @see \phpseclib\Crypt\TripleDES::setKeyLength()
* @var int
* @access private
*/
var $password_key_size = 24;
var $key_length = 24;
/**
* The default salt used by setPassword()
*
* @see Crypt_Base::password_default_salt
* @see Crypt_Base::setPassword()
* @var String
* @see \phpseclib\Crypt\Base::password_default_salt
* @see \phpseclib\Crypt\Base::setPassword()
* @var string
* @access private
*/
var $password_default_salt = 'phpseclib';
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_DES::const_namespace
* @see Crypt_Base::const_namespace
* @var String
* @access private
*/
var $const_namespace = 'DES';
/**
* The mcrypt specific name of the cipher
*
* @see Crypt_DES::cipher_name_mcrypt
* @see Crypt_Base::cipher_name_mcrypt
* @var String
* @see \phpseclib\Crypt\DES::cipher_name_mcrypt
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt
* @var string
* @access private
*/
var $cipher_name_mcrypt = 'tripledes';
@ -126,8 +91,8 @@ class Crypt_TripleDES extends Crypt_DES
/**
* Optimizing value while CFB-encrypting
*
* @see Crypt_Base::cfb_init_len
* @var Integer
* @see \phpseclib\Crypt\Base::cfb_init_len
* @var int
* @access private
*/
var $cfb_init_len = 750;
@ -135,27 +100,27 @@ class Crypt_TripleDES extends Crypt_DES
/**
* max possible size of $key
*
* @see Crypt_TripleDES::setKey()
* @see Crypt_DES::setKey()
* @var String
* @see self::setKey()
* @see \phpseclib\Crypt\DES::setKey()
* @var string
* @access private
*/
var $key_size_max = 24;
var $key_length_max = 24;
/**
* Internal flag whether using CRYPT_DES_MODE_3CBC or not
* Internal flag whether using self::MODE_3CBC or not
*
* @var Boolean
* @var bool
* @access private
*/
var $mode_3cbc;
/**
* The Crypt_DES objects
* The \phpseclib\Crypt\DES objects
*
* Used only if $mode_3cbc === true
*
* @var Array
* @var array
* @access private
*/
var $des;
@ -167,61 +132,82 @@ class Crypt_TripleDES extends Crypt_DES
*
* $mode could be:
*
* - CRYPT_DES_MODE_ECB
* - \phpseclib\Crypt\Base::MODE_ECB
*
* - CRYPT_DES_MODE_CBC
* - \phpseclib\Crypt\Base::MODE_CBC
*
* - CRYPT_DES_MODE_CTR
* - \phpseclib\Crypt\Base::MODE_CTR
*
* - CRYPT_DES_MODE_CFB
* - \phpseclib\Crypt\Base::MODE_CFB
*
* - CRYPT_DES_MODE_OFB
* - \phpseclib\Crypt\Base::MODE_OFB
*
* - CRYPT_DES_MODE_3CBC
* - \phpseclib\Crypt\TripleDES::MODE_3CBC
*
* If not explicitly set, CRYPT_DES_MODE_CBC will be used.
* If not explicitly set, \phpseclib\Crypt\Base::MODE_CBC will be used.
*
* @see Crypt_DES::Crypt_DES()
* @see Crypt_Base::Crypt_Base()
* @param optional Integer $mode
* @see \phpseclib\Crypt\DES::__construct()
* @see \phpseclib\Crypt\Base::__construct()
* @param int $mode
* @access public
*/
function Crypt_TripleDES($mode = CRYPT_DES_MODE_CBC)
function __construct($mode = Base::MODE_CBC)
{
switch ($mode) {
// In case of CRYPT_DES_MODE_3CBC, we init as CRYPT_DES_MODE_CBC
// In case of self::MODE_3CBC, we init as CRYPT_DES_MODE_CBC
// and additional flag us internally as 3CBC
case CRYPT_DES_MODE_3CBC:
parent::Crypt_Base(CRYPT_DES_MODE_CBC);
case self::MODE_3CBC:
parent::__construct(Base::MODE_CBC);
$this->mode_3cbc = true;
// This three $des'es will do the 3CBC work (if $key > 64bits)
$this->des = array(
new Crypt_DES(CRYPT_DES_MODE_CBC),
new Crypt_DES(CRYPT_DES_MODE_CBC),
new Crypt_DES(CRYPT_DES_MODE_CBC),
new DES(Base::MODE_CBC),
new DES(Base::MODE_CBC),
new DES(Base::MODE_CBC),
);
// we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects
// we're going to be doing the padding, ourselves, so disable it in the \phpseclib\Crypt\DES objects
$this->des[0]->disablePadding();
$this->des[1]->disablePadding();
$this->des[2]->disablePadding();
break;
// If not 3CBC, we init as usual
default:
parent::Crypt_Base($mode);
parent::__construct($mode);
}
}
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
*
* @see \phpseclib\Crypt\Base::__construct()
* @param int $engine
* @access public
* @return bool
*/
function isValidEngine($engine)
{
if ($engine == self::ENGINE_OPENSSL) {
$this->cipher_name_openssl_ecb = 'des-ede3';
$mode = $this->_openssl_translate_mode();
$this->cipher_name_openssl = $mode == 'ecb' ? 'des-ede3' : 'des-ede3-' . $mode;
}
return parent::isValidEngine($engine);
}
/**
* Sets the initialization vector. (optional)
*
* SetIV is not required when CRYPT_DES_MODE_ECB is being used. If not explicitly set, it'll be assumed
* SetIV is not required when \phpseclib\Crypt\Base::MODE_ECB is being used. If not explicitly set, it'll be assumed
* to be all zero's.
*
* @see Crypt_Base::setIV()
* @see \phpseclib\Crypt\Base::setIV()
* @access public
* @param String $iv
* @param string $iv
*/
function setIV($iv)
{
@ -233,6 +219,32 @@ class Crypt_TripleDES extends Crypt_DES
}
}
/**
* Sets the key length.
*
* Valid key lengths are 64, 128 and 192
*
* @see \phpseclib\Crypt\Base:setKeyLength()
* @access public
* @param int $length
*/
function setKeyLength($length)
{
$length >>= 3;
switch (true) {
case $length <= 8:
$this->key_length = 8;
break;
case $length <= 16:
$this->key_length = 16;
break;
default:
$this->key_length = 24;
}
parent::setKeyLength($length);
}
/**
* Sets the key.
*
@ -244,24 +256,24 @@ class Crypt_TripleDES extends Crypt_DES
* If the key is not explicitly set, it'll be assumed to be all null bytes.
*
* @access public
* @see Crypt_DES::setKey()
* @see Crypt_Base::setKey()
* @param String $key
* @see \phpseclib\Crypt\DES::setKey()
* @see \phpseclib\Crypt\Base::setKey()
* @param string $key
*/
function setKey($key)
{
$length = strlen($key);
$length = $this->explicit_key_length ? $this->key_length : strlen($key);
if ($length > 8) {
$key = str_pad(substr($key, 0, 24), 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);
$key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
} else {
$key = str_pad($key, 8, chr(0));
}
parent::setKey($key);
// And in case of CRYPT_DES_MODE_3CBC:
// And in case of self::MODE_3CBC:
// if key <= 64bits we not need the 3 $des to work,
// because we will then act as regular DES-CBC with just a <= 64bit key.
// So only if the key > 64bits (> 8 bytes) we will call setKey() for the 3 $des.
@ -275,15 +287,15 @@ class Crypt_TripleDES extends Crypt_DES
/**
* Encrypts a message.
*
* @see Crypt_Base::encrypt()
* @see \phpseclib\Crypt\Base::encrypt()
* @access public
* @param String $plaintext
* @return String $cipertext
* @param string $plaintext
* @return string $cipertext
*/
function encrypt($plaintext)
{
// parent::en/decrypt() is able to do all the work for all modes and keylengths,
// except for: CRYPT_DES_MODE_3CBC (inner chaining CBC) with a key > 64bits
// except for: self::MODE_3CBC (inner chaining CBC) with a key > 64bits
// if the key is smaller then 8, do what we'd normally do
if ($this->mode_3cbc && strlen($this->key) > 8) {
@ -302,10 +314,10 @@ class Crypt_TripleDES extends Crypt_DES
/**
* Decrypts a message.
*
* @see Crypt_Base::decrypt()
* @see \phpseclib\Crypt\Base::decrypt()
* @access public
* @param String $ciphertext
* @return String $plaintext
* @param string $ciphertext
* @return string $plaintext
*/
function decrypt($ciphertext)
{
@ -353,13 +365,13 @@ class Crypt_TripleDES extends Crypt_DES
* 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
* Put another way, when the continuous buffer is enabled, the state of the \phpseclib\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_Base::enableContinuousBuffer()
* @see Crypt_TripleDES::disableContinuousBuffer()
* @see \phpseclib\Crypt\Base::enableContinuousBuffer()
* @see self::disableContinuousBuffer()
* @access public
*/
function enableContinuousBuffer()
@ -377,8 +389,8 @@ class Crypt_TripleDES extends Crypt_DES
*
* The default behavior.
*
* @see Crypt_Base::disableContinuousBuffer()
* @see Crypt_TripleDES::enableContinuousBuffer()
* @see \phpseclib\Crypt\Base::disableContinuousBuffer()
* @see self::enableContinuousBuffer()
* @access public
*/
function disableContinuousBuffer()
@ -394,8 +406,8 @@ class Crypt_TripleDES extends Crypt_DES
/**
* Creates the key schedule
*
* @see Crypt_DES::_setupKey()
* @see Crypt_Base::_setupKey()
* @see \phpseclib\Crypt\DES::_setupKey()
* @see \phpseclib\Crypt\Base::_setupKey()
* @access private
*/
function _setupKey()
@ -425,4 +437,24 @@ class Crypt_TripleDES extends Crypt_DES
// setup our key
parent::_setupKey();
}
/**
* Sets the internal crypt engine
*
* @see \phpseclib\Crypt\Base::__construct()
* @see \phpseclib\Crypt\Base::setPreferredEngine()
* @param int $engine
* @access public
* @return int
*/
function setPreferredEngine($engine)
{
if ($this->mode_3cbc) {
$this->des[0]->setPreferredEngine($engine);
$this->des[1]->setPreferredEngine($engine);
$this->des[2]->setPreferredEngine($engine);
}
return parent::setPreferredEngine($engine);
}
}

View file

@ -5,7 +5,7 @@
*
* Uses mcrypt, if available, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
* PHP version 5
*
* Useful resources are as follows:
*
@ -14,9 +14,9 @@
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/Twofish.php';
* include 'vendor/autoload.php';
*
* $twofish = new Crypt_Twofish();
* $twofish = new \phpseclib\Crypt\Twofish();
*
* $twofish->setKey('12345678901234567890123456789012');
*
@ -26,26 +26,8 @@
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Crypt
* @package Crypt_Twofish
* @package Twofish
* @author Jim Wigginton <terrafrost@php.net>
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
* @copyright 2007 Jim Wigginton
@ -53,92 +35,23 @@
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Base
*
* Base cipher class
*/
if (!class_exists('Crypt_Base')) {
include_once 'Base.php';
}
/**#@+
* @access public
* @see Crypt_Twofish::encrypt()
* @see Crypt_Twofish::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_TWOFISH_MODE_CTR', CRYPT_MODE_CTR);
/**
* 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_TWOFISH_MODE_ECB', CRYPT_MODE_ECB);
/**
* 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_TWOFISH_MODE_CBC', CRYPT_MODE_CBC);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/
define('CRYPT_TWOFISH_MODE_CFB', CRYPT_MODE_CFB);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/
define('CRYPT_TWOFISH_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/
/**#@+
* @access private
* @see Crypt_Base::Crypt_Base()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_TWOFISH_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_TWOFISH_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
namespace phpseclib\Crypt;
/**
* Pure-PHP implementation of Twofish.
*
* @package Crypt_Twofish
* @package Twofish
* @author Jim Wigginton <terrafrost@php.net>
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
* @access public
*/
class Crypt_Twofish extends Crypt_Base
class Twofish extends Base
{
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_Base::const_namespace
* @var String
* @access private
*/
var $const_namespace = 'TWOFISH';
/**
* The mcrypt specific name of the cipher
*
* @see Crypt_Base::cipher_name_mcrypt
* @var String
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt
* @var string
* @access private
*/
var $cipher_name_mcrypt = 'twofish';
@ -146,8 +59,8 @@ class Crypt_Twofish extends Crypt_Base
/**
* Optimizing value while CFB-encrypting
*
* @see Crypt_Base::cfb_init_len
* @var Integer
* @see \phpseclib\Crypt\Base::cfb_init_len
* @var int
* @access private
*/
var $cfb_init_len = 800;
@ -155,10 +68,10 @@ class Crypt_Twofish extends Crypt_Base
/**
* Q-Table
*
* @var Array
* @var array
* @access private
*/
var $q0 = array (
var $q0 = array(
0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76,
0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38,
0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
@ -196,10 +109,10 @@ class Crypt_Twofish extends Crypt_Base
/**
* Q-Table
*
* @var Array
* @var array
* @access private
*/
var $q1 = array (
var $q1 = array(
0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8,
0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B,
0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
@ -237,10 +150,10 @@ class Crypt_Twofish extends Crypt_Base
/**
* M-Table
*
* @var Array
* @var array
* @access private
*/
var $m0 = array (
var $m0 = array(
0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8,
0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B,
0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1,
@ -278,10 +191,10 @@ class Crypt_Twofish extends Crypt_Base
/**
* M-Table
*
* @var Array
* @var array
* @access private
*/
var $m1 = array (
var $m1 = array(
0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4,
0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A,
0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141,
@ -319,10 +232,10 @@ class Crypt_Twofish extends Crypt_Base
/**
* M-Table
*
* @var Array
* @var array
* @access private
*/
var $m2 = array (
var $m2 = array(
0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA,
0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7,
0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783,
@ -360,10 +273,10 @@ class Crypt_Twofish extends Crypt_Base
/**
* M-Table
*
* @var Array
* @var array
* @access private
*/
var $m3 = array (
var $m3 = array(
0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF,
0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836,
0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77,
@ -401,7 +314,7 @@ class Crypt_Twofish extends Crypt_Base
/**
* The Key Schedule Array
*
* @var Array
* @var array
* @access private
*/
var $K = array();
@ -409,7 +322,7 @@ class Crypt_Twofish extends Crypt_Base
/**
* The Key depended S-Table 0
*
* @var Array
* @var array
* @access private
*/
var $S0 = array();
@ -417,7 +330,7 @@ class Crypt_Twofish extends Crypt_Base
/**
* The Key depended S-Table 1
*
* @var Array
* @var array
* @access private
*/
var $S1 = array();
@ -425,7 +338,7 @@ class Crypt_Twofish extends Crypt_Base
/**
* The Key depended S-Table 2
*
* @var Array
* @var array
* @access private
*/
var $S2 = array();
@ -433,7 +346,7 @@ class Crypt_Twofish extends Crypt_Base
/**
* The Key depended S-Table 3
*
* @var Array
* @var array
* @access private
*/
var $S3 = array();
@ -441,47 +354,48 @@ class Crypt_Twofish extends Crypt_Base
/**
* Holds the last used key
*
* @var Array
* @var array
* @access private
*/
var $kl;
/**
* Sets the key.
* The Key Length (in bytes)
*
* Keys can be of any length. Twofish, itself, requires the use of a key that's 128, 192 or 256-bits long.
* If the key is less than 256-bits we round the length up to the closest valid key length,
* padding $key with null bytes. If the key is more than 256-bits, we trim the excess bits.
* @see Crypt_Twofish::setKeyLength()
* @var int
* @access private
*/
var $key_length = 16;
/**
* Sets the key length.
*
* If the key is not explicitly set, it'll be assumed a 128 bits key to be all null bytes.
* Valid key lengths are 128, 192 or 256 bits
*
* @access public
* @see Crypt_Base::setKey()
* @param String $key
* @param int $length
*/
function setKey($key)
function setKeyLength($length)
{
$keylength = strlen($key);
switch (true) {
case $keylength <= 16:
$key = str_pad($key, 16, "\0");
case $length <= 128:
$this->key_length = 16;
break;
case $keylength <= 24:
$key = str_pad($key, 24, "\0");
case $length <= 192:
$this->key_length = 24;
break;
case $keylength < 32:
$key = str_pad($key, 32, "\0");
break;
case $keylength > 32:
$key = substr($key, 0, 32);
default:
$this->key_length = 32;
}
parent::setKey($key);
parent::setKeyLength($length);
}
/**
* Setup the key (expansion)
*
* @see Crypt_Base::_setupKey()
* @see \phpseclib\Crypt\Base::_setupKey()
* @access private
*/
function _setupKey()
@ -506,9 +420,9 @@ class Crypt_Twofish extends Crypt_Base
switch (strlen($this->key)) {
case 16:
list ($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[1], $le_longs[2]);
list ($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[3], $le_longs[4]);
for ($i = 0, $j = 1; $i < 40; $i+= 2,$j+= 2) {
list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[1], $le_longs[2]);
list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[3], $le_longs[4]);
for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
$A = $m0[$q0[$q0[$i] ^ $key[ 9]] ^ $key[1]] ^
$m1[$q0[$q1[$i] ^ $key[10]] ^ $key[2]] ^
$m2[$q1[$q0[$i] ^ $key[11]] ^ $key[3]] ^
@ -529,9 +443,9 @@ class Crypt_Twofish extends Crypt_Base
}
break;
case 24:
list ($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[1], $le_longs[2]);
list ($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[3], $le_longs[4]);
list ($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[5], $le_longs[6]);
list($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[1], $le_longs[2]);
list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[3], $le_longs[4]);
list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[5], $le_longs[6]);
for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
$A = $m0[$q0[$q0[$q1[$i] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
$m1[$q0[$q1[$q1[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
@ -553,10 +467,10 @@ class Crypt_Twofish extends Crypt_Base
}
break;
default: // 32
list ($sf, $se, $sd, $sc) = $this->_mdsrem($le_longs[1], $le_longs[2]);
list ($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[3], $le_longs[4]);
list ($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[5], $le_longs[6]);
list ($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[7], $le_longs[8]);
list($sf, $se, $sd, $sc) = $this->_mdsrem($le_longs[1], $le_longs[2]);
list($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[3], $le_longs[4]);
list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[5], $le_longs[6]);
list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[7], $le_longs[8]);
for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
$A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[25]] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
$m1[$q0[$q1[$q1[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
@ -589,9 +503,9 @@ class Crypt_Twofish extends Crypt_Base
* _mdsrem function using by the twofish cipher algorithm
*
* @access private
* @param String $A
* @param String $B
* @return Array
* @param string $A
* @param string $B
* @return array
*/
function _mdsrem($A, $B)
{
@ -618,7 +532,9 @@ class Crypt_Twofish extends Crypt_Base
$u^= 0x7fffffff & ($t >> 1);
// Add the modular polynomial on underflow.
if ($t & 0x01) $u^= 0xa6 ;
if ($t & 0x01) {
$u^= 0xa6 ;
}
// Remove t * (a + 1/a) * (x^3 + x).
$B^= ($u << 24) | ($u << 8);
@ -635,8 +551,8 @@ class Crypt_Twofish extends Crypt_Base
* Encrypts a block
*
* @access private
* @param String $in
* @return String
* @param string $in
* @return string
*/
function _encryptBlock($in)
{
@ -691,8 +607,8 @@ class Crypt_Twofish extends Crypt_Base
* Decrypts a block
*
* @access private
* @param String $in
* @return String
* @param string $in
* @return string
*/
function _decryptBlock($in)
{
@ -746,29 +662,27 @@ class Crypt_Twofish extends Crypt_Base
/**
* Setup the performance-optimized function for de/encrypt()
*
* @see Crypt_Base::_setupInlineCrypt()
* @see \phpseclib\Crypt\Base::_setupInlineCrypt()
* @access private
*/
function _setupInlineCrypt()
{
$lambda_functions =& Crypt_Twofish::_getLambdaFunctions();
$lambda_functions =& self::_getLambdaFunctions();
// Max. 10 Ultra-Hi-optimized inline-crypt functions. After that, we'll (still) create very fast code, but not the ultimate fast one.
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
// (Currently, for Crypt_Twofish, one generated $lambda_function cost on php5.5@32bit ~140kb unfreeable mem and ~240kb on php5.5@64bit)
$gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
switch (true) {
case $gen_hi_opt_code:
$code_hash = md5(str_pad("Crypt_Twofish, {$this->mode}, ", 32, "\0") . $this->key);
break;
default:
$code_hash = "Crypt_Twofish, {$this->mode}";
// Generation of a unique hash for our generated code
$code_hash = "Crypt_Twofish, {$this->mode}";
if ($gen_hi_opt_code) {
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
}
if (!isset($lambda_functions[$code_hash])) {
switch (true) {
case $gen_hi_opt_code:
$K = $this->K;
$init_crypt = '
static $S0, $S1, $S2, $S3;
if (!$S0) {
@ -786,7 +700,6 @@ class Crypt_Twofish extends Crypt_Base
for ($i = 0; $i < 40; ++$i) {
$K[] = '$K_' . $i;
}
$init_crypt = '
$S0 = $self->S0;
$S1 = $self->S1;

View file

@ -3,52 +3,36 @@
/**
* Pure-PHP ANSI Decoder
*
* PHP versions 4 and 5
* PHP version 5
*
* If you call read() in Net_SSH2 you may get {@link http://en.wikipedia.org/wiki/ANSI_escape_code ANSI escape codes} back.
* If you call read() in \phpseclib\Net\SSH2 you may get {@link http://en.wikipedia.org/wiki/ANSI_escape_code ANSI escape codes} back.
* They'd look like chr(0x1B) . '[00m' or whatever (0x1B = ESC). They tell a
* {@link http://en.wikipedia.org/wiki/Terminal_emulator terminal emulator} how to format the characters, what
* color to display them in, etc. File_ANSI is a {@link http://en.wikipedia.org/wiki/VT100 VT100} terminal emulator.
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* color to display them in, etc. \phpseclib\File\ANSI is a {@link http://en.wikipedia.org/wiki/VT100 VT100} terminal emulator.
*
* @category File
* @package File_ANSI
* @package ANSI
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2012 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\File;
/**
* Pure-PHP ANSI Decoder
*
* @package File_ANSI
* @package ANSI
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class File_ANSI
class ANSI
{
/**
* Max Width
*
* @var Integer
* @var int
* @access private
*/
var $max_x;
@ -56,7 +40,7 @@ class File_ANSI
/**
* Max Height
*
* @var Integer
* @var int
* @access private
*/
var $max_y;
@ -64,7 +48,7 @@ class File_ANSI
/**
* Max History
*
* @var Integer
* @var int
* @access private
*/
var $max_history;
@ -72,7 +56,7 @@ class File_ANSI
/**
* History
*
* @var Array
* @var array
* @access private
*/
var $history;
@ -80,7 +64,7 @@ class File_ANSI
/**
* History Attributes
*
* @var Array
* @var array
* @access private
*/
var $history_attrs;
@ -88,7 +72,7 @@ class File_ANSI
/**
* Current Column
*
* @var Integer
* @var int
* @access private
*/
var $x;
@ -96,7 +80,7 @@ class File_ANSI
/**
* Current Row
*
* @var Integer
* @var int
* @access private
*/
var $y;
@ -104,7 +88,7 @@ class File_ANSI
/**
* Old Column
*
* @var Integer
* @var int
* @access private
*/
var $old_x;
@ -112,15 +96,31 @@ class File_ANSI
/**
* Old Row
*
* @var Integer
* @var int
* @access private
*/
var $old_y;
/**
* An empty attribute cell
*
* @var object
* @access private
*/
var $base_attr_cell;
/**
* The current attribute cell
*
* @var object
* @access private
*/
var $attr_cell;
/**
* An empty attribute row
*
* @var Array
* @var array
* @access private
*/
var $attr_row;
@ -128,7 +128,7 @@ class File_ANSI
/**
* The current screen text
*
* @var Array
* @var array
* @access private
*/
var $screen;
@ -136,83 +136,45 @@ class File_ANSI
/**
* The current screen attributes
*
* @var Array
* @var array
* @access private
*/
var $attrs;
/**
* The current foreground color
*
* @var String
* @access private
*/
var $foreground;
/**
* The current background color
*
* @var String
* @access private
*/
var $background;
/**
* Bold flag
*
* @var Boolean
* @access private
*/
var $bold;
/**
* Underline flag
*
* @var Boolean
* @access private
*/
var $underline;
/**
* Blink flag
*
* @var Boolean
* @access private
*/
var $blink;
/**
* Reverse flag
*
* @var Boolean
* @access private
*/
var $reverse;
/**
* Color flag
*
* @var Boolean
* @access private
*/
var $color;
/**
* Current ANSI code
*
* @var String
* @var string
* @access private
*/
var $ansi;
/**
* Tokenization
*
* @var array
* @access private
*/
var $tokenization;
/**
* Default Constructor.
*
* @return File_ANSI
* @return \phpseclib\File\ANSI
* @access public
*/
function File_ANSI()
function __construct()
{
$attr_cell = new \stdClass();
$attr_cell->bold = false;
$attr_cell->underline = false;
$attr_cell->blink = false;
$attr_cell->background = 'black';
$attr_cell->foreground = 'white';
$attr_cell->reverse = false;
$this->base_attr_cell = clone $attr_cell;
$this->attr_cell = clone $attr_cell;
$this->setHistory(200);
$this->setDimensions(80, 24);
}
@ -222,8 +184,8 @@ class File_ANSI
*
* Resets the screen as well
*
* @param Integer $x
* @param Integer $y
* @param int $x
* @param int $y
* @access public
*/
function setDimensions($x, $y)
@ -232,25 +194,17 @@ class File_ANSI
$this->max_y = $y - 1;
$this->x = $this->y = 0;
$this->history = $this->history_attrs = array();
$this->attr_row = array_fill(0, $this->max_x + 1, '');
$this->attr_row = array_fill(0, $this->max_x + 2, $this->base_attr_cell);
$this->screen = array_fill(0, $this->max_y + 1, '');
$this->attrs = array_fill(0, $this->max_y + 1, $this->attr_row);
$this->foreground = 'white';
$this->background = 'black';
$this->bold = false;
$this->underline = false;
$this->blink = false;
$this->reverse = false;
$this->color = false;
$this->ansi = '';
}
/**
* Set the number of lines that should be logged past the terminal height
*
* @param Integer $x
* @param Integer $y
* @param int $x
* @param int $y
* @access public
*/
function setHistory($history)
@ -261,7 +215,7 @@ class File_ANSI
/**
* Load a string
*
* @param String $source
* @param string $source
* @access public
*/
function loadString($source)
@ -273,11 +227,12 @@ class File_ANSI
/**
* Appdend a string
*
* @param String $source
* @param string $source
* @access public
*/
function appendString($source)
{
$this->tokenization = array('');
for ($i = 0; $i < strlen($source); $i++) {
if (strlen($this->ansi)) {
$this->ansi.= $source[$i];
@ -294,6 +249,8 @@ class File_ANSI
default:
continue 2;
}
$this->tokenization[] = $this->ansi;
$this->tokenization[] = '';
// http://ascii-table.com/ansi-escape-sequences-vt-100.php
switch ($this->ansi) {
case "\x1B[H": // Move cursor to upper left corner
@ -315,7 +272,7 @@ class File_ANSI
case "\x1B[K": // Clear screen from cursor right
$this->screen[$this->y] = substr($this->screen[$this->y], 0, $this->x);
array_splice($this->attrs[$this->y], $this->x + 1);
array_splice($this->attrs[$this->y], $this->x + 1, $this->max_x - $this->x, array_fill($this->x, $this->max_x - $this->x - 1, $this->base_attr_cell));
break;
case "\x1B[2K": // Clear entire line
$this->screen[$this->y] = str_repeat(' ', $this->x);
@ -323,6 +280,7 @@ class File_ANSI
break;
case "\x1B[?1h": // set cursor key to application
case "\x1B[?25h": // show the cursor
case "\x1B(B": // set united states g0 character set
break;
case "\x1BE": // Move to next line
$this->_newLine();
@ -330,6 +288,10 @@ class File_ANSI
break;
default:
switch (true) {
case preg_match('#\x1B\[(\d+)B#', $this->ansi, $match): // Move cursor down n lines
$this->old_y = $this->y;
$this->y+= $match[1];
break;
case preg_match('#\x1B\[(\d+);(\d+)H#', $this->ansi, $match): // Move cursor to screen location v,h
$this->old_x = $this->x;
$this->old_y = $this->y;
@ -338,65 +300,44 @@ class File_ANSI
break;
case preg_match('#\x1B\[(\d+)C#', $this->ansi, $match): // Move cursor right n lines
$this->old_x = $this->x;
$x = $match[1] - 1;
$this->x+= $match[1];
break;
case preg_match('#\x1B\[(\d+)D#', $this->ansi, $match): // Move cursor left n lines
$this->old_x = $this->x;
$this->x-= $match[1];
break;
case preg_match('#\x1B\[(\d+);(\d+)r#', $this->ansi, $match): // Set top and bottom lines of a window
break;
case preg_match('#\x1B\[(\d*(?:;\d*)*)m#', $this->ansi, $match): // character attributes
$attr_cell = &$this->attr_cell;
$mods = explode(';', $match[1]);
foreach ($mods as $mod) {
switch ($mod) {
case 0: // Turn off character attributes
$this->attrs[$this->y][$this->x] = '';
if ($this->bold) $this->attrs[$this->y][$this->x].= '</b>';
if ($this->underline) $this->attrs[$this->y][$this->x].= '</u>';
if ($this->blink) $this->attrs[$this->y][$this->x].= '</blink>';
if ($this->color) $this->attrs[$this->y][$this->x].= '</span>';
if ($this->reverse) {
$temp = $this->background;
$this->background = $this->foreground;
$this->foreground = $temp;
}
$this->bold = $this->underline = $this->blink = $this->color = $this->reverse = false;
$attr_cell = clone $this->base_attr_cell;
break;
case 1: // Turn bold mode on
if (!$this->bold) {
$this->attrs[$this->y][$this->x] = '<b>';
$this->bold = true;
}
$attr_cell->bold = true;
break;
case 4: // Turn underline mode on
if (!$this->underline) {
$this->attrs[$this->y][$this->x] = '<u>';
$this->underline = true;
}
$attr_cell->underline = true;
break;
case 5: // Turn blinking mode on
if (!$this->blink) {
$this->attrs[$this->y][$this->x] = '<blink>';
$this->blink = true;
}
$attr_cell->blink = true;
break;
case 7: // Turn reverse video on
$this->reverse = !$this->reverse;
$temp = $this->background;
$this->background = $this->foreground;
$this->foreground = $temp;
$this->attrs[$this->y][$this->x] = '<span style="color: ' . $this->foreground . '; background: ' . $this->background . '">';
if ($this->color) {
$this->attrs[$this->y][$this->x] = '</span>' . $this->attrs[$this->y][$this->x];
}
$this->color = true;
$attr_cell->reverse = !$attr_cell->reverse;
$temp = $attr_cell->background;
$attr_cell->background = $attr_cell->foreground;
$attr_cell->foreground = $temp;
break;
default: // set colors
//$front = $this->reverse ? &$this->background : &$this->foreground;
$front = &$this->{ $this->reverse ? 'background' : 'foreground' };
//$back = $this->reverse ? &$this->foreground : &$this->background;
$back = &$this->{ $this->reverse ? 'foreground' : 'background' };
//$front = $attr_cell->reverse ? &$attr_cell->background : &$attr_cell->foreground;
$front = &$attr_cell->{ $attr_cell->reverse ? 'background' : 'foreground' };
//$back = $attr_cell->reverse ? &$attr_cell->foreground : &$attr_cell->background;
$back = &$attr_cell->{ $attr_cell->reverse ? 'foreground' : 'background' };
switch ($mod) {
// @codingStandardsIgnoreStart
case 30: $front = 'black'; break;
case 31: $front = 'red'; break;
case 32: $front = 'green'; break;
@ -414,30 +355,25 @@ class File_ANSI
case 45: $back = 'magenta'; break;
case 46: $back = 'cyan'; break;
case 47: $back = 'white'; break;
// @codingStandardsIgnoreEnd
default:
user_error('Unsupported attribute: ' . $mod);
//user_error('Unsupported attribute: ' . $mod);
$this->ansi = '';
break 2;
}
unset($temp);
$this->attrs[$this->y][$this->x] = '<span style="color: ' . $this->foreground . '; background: ' . $this->background . '">';
if ($this->color) {
$this->attrs[$this->y][$this->x] = '</span>' . $this->attrs[$this->y][$this->x];
}
$this->color = true;
}
}
break;
default:
user_error("{$this->ansi} unsupported\r\n");
//user_error("{$this->ansi} is unsupported\r\n");
}
}
$this->ansi = '';
continue;
}
$this->tokenization[count($this->tokenization) - 1].= $source[$i];
switch ($source[$i]) {
case "\r":
$this->x = 0;
@ -445,12 +381,32 @@ class File_ANSI
case "\n":
$this->_newLine();
break;
case "\x08": // backspace
if ($this->x) {
$this->x--;
$this->attrs[$this->y][$this->x] = clone $this->base_attr_cell;
$this->screen[$this->y] = substr_replace(
$this->screen[$this->y],
$source[$i],
$this->x,
1
);
}
break;
case "\x0F": // shift
break;
case "\x1B": // start ANSI escape code
$this->tokenization[count($this->tokenization) - 1] = substr($this->tokenization[count($this->tokenization) - 1], 0, -1);
//if (!strlen($this->tokenization[count($this->tokenization) - 1])) {
// array_pop($this->tokenization);
//}
$this->ansi.= "\x1B";
break;
default:
$this->attrs[$this->y][$this->x] = clone $this->attr_cell;
if ($this->x > strlen($this->screen[$this->y])) {
$this->screen[$this->y] = str_repeat(' ', $this->x);
}
$this->screen[$this->y] = substr_replace(
$this->screen[$this->y],
$source[$i],
@ -498,26 +454,84 @@ class File_ANSI
$this->y++;
}
/**
* Returns the current coordinate without preformating
*
* @access private
* @return string
*/
function _processCoordinate($last_attr, $cur_attr, $char)
{
$output = '';
if ($last_attr != $cur_attr) {
$close = $open = '';
if ($last_attr->foreground != $cur_attr->foreground) {
if ($cur_attr->foreground != 'white') {
$open.= '<span style="color: ' . $cur_attr->foreground . '">';
}
if ($last_attr->foreground != 'white') {
$close = '</span>' . $close;
}
}
if ($last_attr->background != $cur_attr->background) {
if ($cur_attr->background != 'black') {
$open.= '<span style="background: ' . $cur_attr->background . '">';
}
if ($last_attr->background != 'black') {
$close = '</span>' . $close;
}
}
if ($last_attr->bold != $cur_attr->bold) {
if ($cur_attr->bold) {
$open.= '<b>';
} else {
$close = '</b>' . $close;
}
}
if ($last_attr->underline != $cur_attr->underline) {
if ($cur_attr->underline) {
$open.= '<u>';
} else {
$close = '</u>' . $close;
}
}
if ($last_attr->blink != $cur_attr->blink) {
if ($cur_attr->blink) {
$open.= '<blink>';
} else {
$close = '</blink>' . $close;
}
}
$output.= $close . $open;
}
$output.= htmlspecialchars($char);
return $output;
}
/**
* Returns the current screen without preformating
*
* @access private
* @return String
* @return string
*/
function _getScreen()
{
$output = '';
$last_attr = $this->base_attr_cell;
for ($i = 0; $i <= $this->max_y; $i++) {
for ($j = 0; $j <= $this->max_x + 1; $j++) {
if (isset($this->attrs[$i][$j])) {
$output.= $this->attrs[$i][$j];
}
if (isset($this->screen[$i][$j])) {
$output.= htmlspecialchars($this->screen[$i][$j]);
}
for ($j = 0; $j <= $this->max_x; $j++) {
$cur_attr = $this->attrs[$i][$j];
$output.= $this->_processCoordinate($last_attr, $cur_attr, isset($this->screen[$i][$j]) ? $this->screen[$i][$j] : '');
$last_attr = $this->attrs[$i][$j];
}
$output.= "\r\n";
}
$output = substr($output, 0, -2);
// close any remaining open tags
$output.= $this->_processCoordinate($last_attr, $this->base_attr_cell, '');
return rtrim($output);
}
@ -525,35 +539,36 @@ class File_ANSI
* Returns the current screen
*
* @access public
* @return String
* @return string
*/
function getScreen()
{
return '<pre style="color: white; background: black" width="' . ($this->max_x + 1) . '">' . $this->_getScreen() . '</pre>';
return '<pre width="' . ($this->max_x + 1) . '" style="color: white; background: black">' . $this->_getScreen() . '</pre>';
}
/**
* Returns the current screen and the x previous lines
*
* @access public
* @return String
* @return string
*/
function getHistory()
{
$scrollback = '';
$last_attr = $this->base_attr_cell;
for ($i = 0; $i < count($this->history); $i++) {
for ($j = 0; $j <= $this->max_x + 1; $j++) {
if (isset($this->history_attrs[$i][$j])) {
$scrollback.= $this->history_attrs[$i][$j];
}
if (isset($this->history[$i][$j])) {
$scrollback.= htmlspecialchars($this->history[$i][$j]);
}
$cur_attr = $this->history_attrs[$i][$j];
$scrollback.= $this->_processCoordinate($last_attr, $cur_attr, isset($this->history[$i][$j]) ? $this->history[$i][$j] : '');
$last_attr = $this->history_attrs[$i][$j];
}
$scrollback.= "\r\n";
}
$base_attr_cell = $this->base_attr_cell;
$this->base_attr_cell = $last_attr;
$scrollback.= $this->_getScreen();
$this->base_attr_cell = $base_attr_cell;
return '<pre style="color: white; background: black" width="' . ($this->max_x + 1) . '">' . $scrollback . '</pre>';
return '<pre width="' . ($this->max_x + 1) . '" style="color: white; background: black">' . $scrollback . '</span></pre>';
}
}

View file

@ -3,153 +3,108 @@
/**
* Pure-PHP ASN.1 Parser
*
* PHP versions 4 and 5
* PHP version 5
*
* ASN.1 provides the semantics for data encoded using various schemes. The most commonly
* utilized scheme is DER or the "Distinguished Encoding Rules". PEM's are base64 encoded
* DER blobs.
*
* File_ASN1 decodes and encodes DER formatted messages and places them in a semantic context.
* \phpseclib\File\ASN1 decodes and encodes DER formatted messages and places them in a semantic context.
*
* Uses the 1988 ASN.1 syntax.
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category File
* @package File_ASN1
* @package ASN1
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2012 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**#@+
* Tag Classes
*
* @access private
* @link http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=12
*/
define('FILE_ASN1_CLASS_UNIVERSAL', 0);
define('FILE_ASN1_CLASS_APPLICATION', 1);
define('FILE_ASN1_CLASS_CONTEXT_SPECIFIC', 2);
define('FILE_ASN1_CLASS_PRIVATE', 3);
/**#@-*/
namespace phpseclib\File;
/**#@+
* Tag Classes
*
* @access private
* @link http://www.obj-sys.com/asn1tutorial/node124.html
*/
define('FILE_ASN1_TYPE_BOOLEAN', 1);
define('FILE_ASN1_TYPE_INTEGER', 2);
define('FILE_ASN1_TYPE_BIT_STRING', 3);
define('FILE_ASN1_TYPE_OCTET_STRING', 4);
define('FILE_ASN1_TYPE_NULL', 5);
define('FILE_ASN1_TYPE_OBJECT_IDENTIFIER', 6);
//define('FILE_ASN1_TYPE_OBJECT_DESCRIPTOR', 7);
//define('FILE_ASN1_TYPE_INSTANCE_OF', 8); // EXTERNAL
define('FILE_ASN1_TYPE_REAL', 9);
define('FILE_ASN1_TYPE_ENUMERATED', 10);
//define('FILE_ASN1_TYPE_EMBEDDED', 11);
define('FILE_ASN1_TYPE_UTF8_STRING', 12);
//define('FILE_ASN1_TYPE_RELATIVE_OID', 13);
define('FILE_ASN1_TYPE_SEQUENCE', 16); // SEQUENCE OF
define('FILE_ASN1_TYPE_SET', 17); // SET OF
/**#@-*/
/**#@+
* More Tag Classes
*
* @access private
* @link http://www.obj-sys.com/asn1tutorial/node10.html
*/
define('FILE_ASN1_TYPE_NUMERIC_STRING', 18);
define('FILE_ASN1_TYPE_PRINTABLE_STRING', 19);
define('FILE_ASN1_TYPE_TELETEX_STRING', 20); // T61String
define('FILE_ASN1_TYPE_VIDEOTEX_STRING', 21);
define('FILE_ASN1_TYPE_IA5_STRING', 22);
define('FILE_ASN1_TYPE_UTC_TIME', 23);
define('FILE_ASN1_TYPE_GENERALIZED_TIME', 24);
define('FILE_ASN1_TYPE_GRAPHIC_STRING', 25);
define('FILE_ASN1_TYPE_VISIBLE_STRING', 26); // ISO646String
define('FILE_ASN1_TYPE_GENERAL_STRING', 27);
define('FILE_ASN1_TYPE_UNIVERSAL_STRING', 28);
//define('FILE_ASN1_TYPE_CHARACTER_STRING', 29);
define('FILE_ASN1_TYPE_BMP_STRING', 30);
/**#@-*/
/**#@+
* Tag Aliases
*
* These tags are kinda place holders for other tags.
*
* @access private
*/
define('FILE_ASN1_TYPE_CHOICE', -1);
define('FILE_ASN1_TYPE_ANY', -2);
/**#@-*/
/**
* ASN.1 Element
*
* Bypass normal encoding rules in File_ASN1::encodeDER()
*
* @package File_ASN1
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class File_ASN1_Element
{
/**
* Raw element value
*
* @var String
* @access private
*/
var $element;
/**
* Constructor
*
* @param String $encoded
* @return File_ASN1_Element
* @access public
*/
function File_ASN1_Element($encoded)
{
$this->element = $encoded;
}
}
use phpseclib\File\ASN1\Element;
use phpseclib\Math\BigInteger;
/**
* Pure-PHP ASN.1 Parser
*
* @package File_ASN1
* @package ASN1
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class File_ASN1
class ASN1
{
/**#@+
* Tag Classes
*
* @access private
* @link http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=12
*/
const CLASS_UNIVERSAL = 0;
const CLASS_APPLICATION = 1;
const CLASS_CONTEXT_SPECIFIC = 2;
const CLASS_PRIVATE = 3;
/**#@-*/
/**#@+
* Tag Classes
*
* @access private
* @link http://www.obj-sys.com/asn1tutorial/node124.html
*/
const TYPE_BOOLEAN = 1;
const TYPE_INTEGER = 2;
const TYPE_BIT_STRING = 3;
const TYPE_OCTET_STRING = 4;
const TYPE_NULL = 5;
const TYPE_OBJECT_IDENTIFIER = 6;
//const TYPE_OBJECT_DESCRIPTOR = 7;
//const TYPE_INSTANCE_OF = 8; // EXTERNAL
const TYPE_REAL = 9;
const TYPE_ENUMERATED = 10;
//const TYPE_EMBEDDED = 11;
const TYPE_UTF8_STRING = 12;
//const TYPE_RELATIVE_OID = 13;
const TYPE_SEQUENCE = 16; // SEQUENCE OF
const TYPE_SET = 17; // SET OF
/**#@-*/
/**#@+
* More Tag Classes
*
* @access private
* @link http://www.obj-sys.com/asn1tutorial/node10.html
*/
const TYPE_NUMERIC_STRING = 18;
const TYPE_PRINTABLE_STRING = 19;
const TYPE_TELETEX_STRING = 20; // T61String
const TYPE_VIDEOTEX_STRING = 21;
const TYPE_IA5_STRING = 22;
const TYPE_UTC_TIME = 23;
const TYPE_GENERALIZED_TIME = 24;
const TYPE_GRAPHIC_STRING = 25;
const TYPE_VISIBLE_STRING = 26; // ISO646String
const TYPE_GENERAL_STRING = 27;
const TYPE_UNIVERSAL_STRING = 28;
//const TYPE_CHARACTER_STRING = 29;
const TYPE_BMP_STRING = 30;
/**#@-*/
/**#@+
* Tag Aliases
*
* These tags are kinda place holders for other tags.
*
* @access private
*/
const TYPE_CHOICE = -1;
const TYPE_ANY = -2;
/**#@-*/
/**
* ASN.1 object identifier
*
* @var Array
* @var array
* @access private
* @link http://en.wikipedia.org/wiki/Object_identifier
*/
@ -158,7 +113,7 @@ class File_ASN1
/**
* Default date format
*
* @var String
* @var string
* @access private
* @link http://php.net/class.datetime
*/
@ -167,10 +122,10 @@ class File_ASN1
/**
* Default date format
*
* @var Array
* @var array
* @access private
* @see File_ASN1::setTimeFormat()
* @see File_ASN1::asn1map()
* @see self::setTimeFormat()
* @see self::asn1map()
* @link http://php.net/class.datetime
*/
var $encoded;
@ -178,47 +133,47 @@ class File_ASN1
/**
* Filters
*
* If the mapping type is FILE_ASN1_TYPE_ANY what do we actually encode it as?
* If the mapping type is self::TYPE_ANY what do we actually encode it as?
*
* @var Array
* @var array
* @access private
* @see File_ASN1::_encode_der()
* @see self::_encode_der()
*/
var $filters;
/**
* Type mapping table for the ANY type.
*
* Structured or unknown types are mapped to a FILE_ASN1_Element.
* Structured or unknown types are mapped to a \phpseclib\File\ASN1\Element.
* Unambiguous types get the direct mapping (int/real/bool).
* Others are mapped as a choice, with an extra indexing level.
*
* @var Array
* @var array
* @access public
*/
var $ANYmap = array(
FILE_ASN1_TYPE_BOOLEAN => true,
FILE_ASN1_TYPE_INTEGER => true,
FILE_ASN1_TYPE_BIT_STRING => 'bitString',
FILE_ASN1_TYPE_OCTET_STRING => 'octetString',
FILE_ASN1_TYPE_NULL => 'null',
FILE_ASN1_TYPE_OBJECT_IDENTIFIER => 'objectIdentifier',
FILE_ASN1_TYPE_REAL => true,
FILE_ASN1_TYPE_ENUMERATED => 'enumerated',
FILE_ASN1_TYPE_UTF8_STRING => 'utf8String',
FILE_ASN1_TYPE_NUMERIC_STRING => 'numericString',
FILE_ASN1_TYPE_PRINTABLE_STRING => 'printableString',
FILE_ASN1_TYPE_TELETEX_STRING => 'teletexString',
FILE_ASN1_TYPE_VIDEOTEX_STRING => 'videotexString',
FILE_ASN1_TYPE_IA5_STRING => 'ia5String',
FILE_ASN1_TYPE_UTC_TIME => 'utcTime',
FILE_ASN1_TYPE_GENERALIZED_TIME => 'generalTime',
FILE_ASN1_TYPE_GRAPHIC_STRING => 'graphicString',
FILE_ASN1_TYPE_VISIBLE_STRING => 'visibleString',
FILE_ASN1_TYPE_GENERAL_STRING => 'generalString',
FILE_ASN1_TYPE_UNIVERSAL_STRING => 'universalString',
//FILE_ASN1_TYPE_CHARACTER_STRING => 'characterString',
FILE_ASN1_TYPE_BMP_STRING => 'bmpString'
self::TYPE_BOOLEAN => true,
self::TYPE_INTEGER => true,
self::TYPE_BIT_STRING => 'bitString',
self::TYPE_OCTET_STRING => 'octetString',
self::TYPE_NULL => 'null',
self::TYPE_OBJECT_IDENTIFIER => 'objectIdentifier',
self::TYPE_REAL => true,
self::TYPE_ENUMERATED => 'enumerated',
self::TYPE_UTF8_STRING => 'utf8String',
self::TYPE_NUMERIC_STRING => 'numericString',
self::TYPE_PRINTABLE_STRING => 'printableString',
self::TYPE_TELETEX_STRING => 'teletexString',
self::TYPE_VIDEOTEX_STRING => 'videotexString',
self::TYPE_IA5_STRING => 'ia5String',
self::TYPE_UTC_TIME => 'utcTime',
self::TYPE_GENERALIZED_TIME => 'generalTime',
self::TYPE_GRAPHIC_STRING => 'graphicString',
self::TYPE_VISIBLE_STRING => 'visibleString',
self::TYPE_GENERAL_STRING => 'generalString',
self::TYPE_UNIVERSAL_STRING => 'universalString',
//self::TYPE_CHARACTER_STRING => 'characterString',
self::TYPE_BMP_STRING => 'bmpString'
);
/**
@ -227,47 +182,31 @@ class File_ASN1
* Non-convertable types are absent from this table.
* size == 0 indicates variable length encoding.
*
* @var Array
* @var array
* @access public
*/
var $stringTypeSize = array(
FILE_ASN1_TYPE_UTF8_STRING => 0,
FILE_ASN1_TYPE_BMP_STRING => 2,
FILE_ASN1_TYPE_UNIVERSAL_STRING => 4,
FILE_ASN1_TYPE_PRINTABLE_STRING => 1,
FILE_ASN1_TYPE_TELETEX_STRING => 1,
FILE_ASN1_TYPE_IA5_STRING => 1,
FILE_ASN1_TYPE_VISIBLE_STRING => 1,
self::TYPE_UTF8_STRING => 0,
self::TYPE_BMP_STRING => 2,
self::TYPE_UNIVERSAL_STRING => 4,
self::TYPE_PRINTABLE_STRING => 1,
self::TYPE_TELETEX_STRING => 1,
self::TYPE_IA5_STRING => 1,
self::TYPE_VISIBLE_STRING => 1,
);
/**
* Default Constructor.
*
* @access public
*/
function File_ASN1()
{
static $static_init = null;
if (!$static_init) {
$static_init = true;
if (!class_exists('Math_BigInteger')) {
include_once 'Math/BigInteger.php';
}
}
}
/**
* Parse BER-encoding
*
* Serves a similar purpose to openssl's asn1parse
*
* @param String $encoded
* @return Array
* @param string $encoded
* @return array
* @access public
*/
function decodeBER($encoded)
{
if (is_object($encoded) && strtolower(get_class($encoded)) == 'file_asn1_element') {
if ($encoded instanceof Element) {
$encoded = $encoded->element;
}
@ -280,19 +219,20 @@ class File_ASN1
* Parse BER-encoding (Helper function)
*
* Sometimes we want to get the BER encoding of a particular tag. $start lets us do that without having to reencode.
* $encoded is passed by reference for the recursive calls done for FILE_ASN1_TYPE_BIT_STRING and
* FILE_ASN1_TYPE_OCTET_STRING. In those cases, the indefinite length is used.
* $encoded is passed by reference for the recursive calls done for self::TYPE_BIT_STRING and
* self::TYPE_OCTET_STRING. In those cases, the indefinite length is used.
*
* @param String $encoded
* @param Integer $start
* @return Array
* @param string $encoded
* @param int $start
* @param int $encoded_pos
* @return array
* @access private
*/
function _decode_ber($encoded, $start = 0)
function _decode_ber($encoded, $start = 0, $encoded_pos = 0)
{
$current = array('start' => $start);
$type = ord($this->_string_shift($encoded));
$type = ord($encoded[$encoded_pos++]);
$start++;
$constructed = ($type >> 5) & 1;
@ -304,23 +244,24 @@ class File_ASN1
do {
$loop = ord($encoded[0]) >> 7;
$tag <<= 7;
$tag |= ord($this->_string_shift($encoded)) & 0x7F;
$tag |= ord($encoded[$encoded_pos++]) & 0x7F;
$start++;
} while ( $loop );
} while ($loop);
}
// Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13
$length = ord($this->_string_shift($encoded));
$length = ord($encoded[$encoded_pos++]);
$start++;
if ( $length == 0x80 ) { // indefinite length
if ($length == 0x80) { // indefinite length
// "[A sender shall] use the indefinite form (see 8.1.3.6) if the encoding is constructed and is not all
// immediately available." -- paragraph 8.1.3.2.c
$length = strlen($encoded);
} elseif ( $length & 0x80 ) { // definite length, long form
$length = strlen($encoded) - $encoded_pos;
} elseif ($length & 0x80) { // definite length, long form
// technically, the long form of the length can be represented by up to 126 octets (bytes), but we'll only
// support it up to four.
$length&= 0x7F;
$temp = $this->_string_shift($encoded, $length);
$temp = substr($encoded, $encoded_pos, $length);
$encoded_pos += $length;
// tags of indefinte length don't really have a header length; this length includes the tag
$current+= array('headerlength' => $length + 2);
$start+= $length;
@ -329,7 +270,12 @@ class File_ASN1
$current+= array('headerlength' => 2);
}
$content = $this->_string_shift($encoded, $length);
if ($length > (strlen($encoded) - $encoded_pos)) {
return false;
}
$content = substr($encoded, $encoded_pos, $length);
$content_pos = 0;
// at this point $length can be overwritten. it's only accurate for definite length things as is
@ -344,9 +290,9 @@ class File_ASN1
-- http://www.obj-sys.com/asn1tutorial/node12.html */
$class = ($type >> 6) & 3;
switch ($class) {
case FILE_ASN1_CLASS_APPLICATION:
case FILE_ASN1_CLASS_PRIVATE:
case FILE_ASN1_CLASS_CONTEXT_SPECIFIC:
case self::CLASS_APPLICATION:
case self::CLASS_PRIVATE:
case self::CLASS_CONTEXT_SPECIFIC:
if (!$constructed) {
return array(
'type' => $class,
@ -357,14 +303,21 @@ class File_ASN1
}
$newcontent = array();
if (strlen($content)) {
$newcontent = $this->_decode_ber($content, $start);
$length = $newcontent['length'];
if (substr($content, $length, 2) == "\0\0") {
$remainingLength = $length;
while ($remainingLength > 0) {
$temp = $this->_decode_ber($content, $start, $content_pos);
$length = $temp['length'];
// end-of-content octets - see paragraph 8.1.5
if (substr($content, $content_pos + $length, 2) == "\0\0") {
$length+= 2;
$start+= $length;
$newcontent[] = $temp;
break;
}
$start+= $length;
$newcontent = array($newcontent);
$remainingLength-= $length;
$newcontent[] = $temp;
$content_pos += $length;
}
return array(
@ -383,94 +336,96 @@ class File_ASN1
// decode UNIVERSAL tags
switch ($tag) {
case FILE_ASN1_TYPE_BOOLEAN:
case self::TYPE_BOOLEAN:
// "The contents octets shall consist of a single octet." -- paragraph 8.2.1
//if (strlen($content) != 1) {
// return false;
//}
$current['content'] = (bool) ord($content[0]);
$current['content'] = (bool) ord($content[$content_pos]);
break;
case FILE_ASN1_TYPE_INTEGER:
case FILE_ASN1_TYPE_ENUMERATED:
$current['content'] = new Math_BigInteger($content, -256);
case self::TYPE_INTEGER:
case self::TYPE_ENUMERATED:
$current['content'] = new BigInteger(substr($content, $content_pos), -256);
break;
case FILE_ASN1_TYPE_REAL: // not currently supported
case self::TYPE_REAL: // not currently supported
return false;
case FILE_ASN1_TYPE_BIT_STRING:
case self::TYPE_BIT_STRING:
// The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit,
// the number of unused bits in the final subsequent octet. The number shall be in the range zero to
// seven.
if (!$constructed) {
$current['content'] = $content;
$current['content'] = substr($content, $content_pos);
} else {
$temp = $this->_decode_ber($content, $start);
$length-= strlen($content);
$temp = $this->_decode_ber($content, $start, $content_pos);
$length-= (strlen($content) - $content_pos);
$last = count($temp) - 1;
for ($i = 0; $i < $last; $i++) {
// all subtags should be bit strings
//if ($temp[$i]['type'] != FILE_ASN1_TYPE_BIT_STRING) {
//if ($temp[$i]['type'] != self::TYPE_BIT_STRING) {
// return false;
//}
$current['content'].= substr($temp[$i]['content'], 1);
}
// all subtags should be bit strings
//if ($temp[$last]['type'] != FILE_ASN1_TYPE_BIT_STRING) {
//if ($temp[$last]['type'] != self::TYPE_BIT_STRING) {
// return false;
//}
$current['content'] = $temp[$last]['content'][0] . $current['content'] . substr($temp[$i]['content'], 1);
}
break;
case FILE_ASN1_TYPE_OCTET_STRING:
case self::TYPE_OCTET_STRING:
if (!$constructed) {
$current['content'] = $content;
$current['content'] = substr($content, $content_pos);
} else {
$current['content'] = '';
$length = 0;
while (substr($content, 0, 2) != "\0\0") {
$temp = $this->_decode_ber($content, $length + $start);
$this->_string_shift($content, $temp['length']);
while (substr($content, $content_pos, 2) != "\0\0") {
$temp = $this->_decode_ber($content, $length + $start, $content_pos);
$content_pos += $temp['length'];
// all subtags should be octet strings
//if ($temp['type'] != FILE_ASN1_TYPE_OCTET_STRING) {
//if ($temp['type'] != self::TYPE_OCTET_STRING) {
// return false;
//}
$current['content'].= $temp['content'];
$length+= $temp['length'];
}
if (substr($content, 0, 2) == "\0\0") {
if (substr($content, $content_pos, 2) == "\0\0") {
$length+= 2; // +2 for the EOC
}
}
break;
case FILE_ASN1_TYPE_NULL:
case self::TYPE_NULL:
// "The contents octets shall not contain any octets." -- paragraph 8.8.2
//if (strlen($content)) {
// return false;
//}
break;
case FILE_ASN1_TYPE_SEQUENCE:
case FILE_ASN1_TYPE_SET:
case self::TYPE_SEQUENCE:
case self::TYPE_SET:
$offset = 0;
$current['content'] = array();
while (strlen($content)) {
$content_len = strlen($content);
while ($content_pos < $content_len) {
// if indefinite length construction was used and we have an end-of-content string next
// see paragraphs 8.1.1.3, 8.1.3.2, 8.1.3.6, 8.1.5, and (for an example) 8.6.4.2
if (!isset($current['headerlength']) && substr($content, 0, 2) == "\0\0") {
if (!isset($current['headerlength']) && substr($content, $content_pos, 2) == "\0\0") {
$length = $offset + 2; // +2 for the EOC
break 2;
}
$temp = $this->_decode_ber($content, $start + $offset);
$this->_string_shift($content, $temp['length']);
$temp = $this->_decode_ber($content, $start + $offset, $content_pos);
$content_pos += $temp['length'];
$current['content'][] = $temp;
$offset+= $temp['length'];
}
break;
case FILE_ASN1_TYPE_OBJECT_IDENTIFIER:
$temp = ord($this->_string_shift($content));
case self::TYPE_OBJECT_IDENTIFIER:
$temp = ord($content[$content_pos++]);
$current['content'] = sprintf('%d.%d', floor($temp / 40), $temp % 40);
$valuen = 0;
// process septets
while (strlen($content)) {
$temp = ord($this->_string_shift($content));
$content_len = strlen($content);
while ($content_pos < $content_len) {
$temp = ord($content[$content_pos++]);
$valuen <<= 7;
$valuen |= $temp & 0x7F;
if (~$temp & 0x80) {
@ -490,32 +445,32 @@ class File_ASN1
Per that, we're not going to do any validation. If there are any illegal characters in the string,
we don't really care */
case FILE_ASN1_TYPE_NUMERIC_STRING:
case self::TYPE_NUMERIC_STRING:
// 0,1,2,3,4,5,6,7,8,9, and space
case FILE_ASN1_TYPE_PRINTABLE_STRING:
case self::TYPE_PRINTABLE_STRING:
// Upper and lower case letters, digits, space, apostrophe, left/right parenthesis, plus sign, comma,
// hyphen, full stop, solidus, colon, equal sign, question mark
case FILE_ASN1_TYPE_TELETEX_STRING:
case self::TYPE_TELETEX_STRING:
// The Teletex character set in CCITT's T61, space, and delete
// see http://en.wikipedia.org/wiki/Teletex#Character_sets
case FILE_ASN1_TYPE_VIDEOTEX_STRING:
case self::TYPE_VIDEOTEX_STRING:
// The Videotex character set in CCITT's T.100 and T.101, space, and delete
case FILE_ASN1_TYPE_VISIBLE_STRING:
case self::TYPE_VISIBLE_STRING:
// Printing character sets of international ASCII, and space
case FILE_ASN1_TYPE_IA5_STRING:
case self::TYPE_IA5_STRING:
// International Alphabet 5 (International ASCII)
case FILE_ASN1_TYPE_GRAPHIC_STRING:
case self::TYPE_GRAPHIC_STRING:
// All registered G sets, and space
case FILE_ASN1_TYPE_GENERAL_STRING:
case self::TYPE_GENERAL_STRING:
// All registered C and G sets, space and delete
case FILE_ASN1_TYPE_UTF8_STRING:
case self::TYPE_UTF8_STRING:
// ????
case FILE_ASN1_TYPE_BMP_STRING:
$current['content'] = $content;
case self::TYPE_BMP_STRING:
$current['content'] = substr($content, $content_pos);
break;
case FILE_ASN1_TYPE_UTC_TIME:
case FILE_ASN1_TYPE_GENERALIZED_TIME:
$current['content'] = $this->_decodeTime($content, $tag);
case self::TYPE_UTC_TIME:
case self::TYPE_GENERALIZED_TIME:
$current['content'] = $this->_decodeTime(substr($content, $content_pos), $tag);
default:
}
@ -532,10 +487,10 @@ class File_ASN1
*
* "Special" mappings may be applied on a per tag-name basis via $special.
*
* @param Array $decoded
* @param Array $mapping
* @param Array $special
* @return Array
* @param array $decoded
* @param array $mapping
* @param array $special
* @return array
* @access public
*/
function asn1map($decoded, $mapping, $special = array())
@ -545,24 +500,24 @@ class File_ASN1
}
switch (true) {
case $mapping['type'] == FILE_ASN1_TYPE_ANY:
case $mapping['type'] == self::TYPE_ANY:
$intype = $decoded['type'];
if (isset($decoded['constant']) || !isset($this->ANYmap[$intype]) || ($this->encoded[$decoded['start']] & 0x20)) {
return new File_ASN1_Element(substr($this->encoded, $decoded['start'], $decoded['length']));
if (isset($decoded['constant']) || !isset($this->ANYmap[$intype]) || (ord($this->encoded[$decoded['start']]) & 0x20)) {
return new Element(substr($this->encoded, $decoded['start'], $decoded['length']));
}
$inmap = $this->ANYmap[$intype];
if (is_string($inmap)) {
return array($inmap => $this->asn1map($decoded, array('type' => $intype) + $mapping, $special));
}
break;
case $mapping['type'] == FILE_ASN1_TYPE_CHOICE:
case $mapping['type'] == self::TYPE_CHOICE:
foreach ($mapping['children'] as $key => $option) {
switch (true) {
case isset($option['constant']) && $option['constant'] == $decoded['constant']:
case !isset($option['constant']) && $option['type'] == $decoded['type']:
$value = $this->asn1map($decoded, $option, $special);
break;
case !isset($option['constant']) && $option['type'] == FILE_ASN1_TYPE_CHOICE:
case !isset($option['constant']) && $option['type'] == self::TYPE_CHOICE:
$v = $this->asn1map($decoded, $option, $special);
if (isset($v)) {
$value = $v;
@ -584,8 +539,8 @@ class File_ASN1
// if $decoded['type'] and $mapping['type'] are both strings, but different types of strings,
// let it through
switch (true) {
case $decoded['type'] < 18: // FILE_ASN1_TYPE_NUMERIC_STRING == 18
case $decoded['type'] > 30: // FILE_ASN1_TYPE_BMP_STRING == 30
case $decoded['type'] < 18: // self::TYPE_NUMERIC_STRING == 18
case $decoded['type'] > 30: // self::TYPE_BMP_STRING == 30
case $mapping['type'] < 18:
case $mapping['type'] > 30:
return null;
@ -597,7 +552,7 @@ class File_ASN1
}
switch ($decoded['type']) {
case FILE_ASN1_TYPE_SEQUENCE:
case self::TYPE_SEQUENCE:
$map = array();
// ignore the min and max
@ -620,18 +575,18 @@ class File_ASN1
if ($maymatch) {
$temp = $decoded['content'][$i];
if ($child['type'] != FILE_ASN1_TYPE_CHOICE) {
if ($child['type'] != self::TYPE_CHOICE) {
// Get the mapping and input class & constant.
$childClass = $tempClass = FILE_ASN1_CLASS_UNIVERSAL;
$childClass = $tempClass = self::CLASS_UNIVERSAL;
$constant = null;
if (isset($temp['constant'])) {
$tempClass = isset($temp['class']) ? $temp['class'] : FILE_ASN1_CLASS_CONTEXT_SPECIFIC;
$tempClass = isset($temp['class']) ? $temp['class'] : self::CLASS_CONTEXT_SPECIFIC;
}
if (isset($child['class'])) {
$childClass = $child['class'];
$constant = $child['cast'];
} elseif (isset($child['constant'])) {
$childClass = FILE_ASN1_CLASS_CONTEXT_SPECIFIC;
$childClass = self::CLASS_CONTEXT_SPECIFIC;
$constant = $child['constant'];
}
@ -640,7 +595,7 @@ class File_ASN1
$maymatch = $constant == $temp['constant'] && $childClass == $tempClass;
} else {
// Can only match if no constant expected and type matches or is generic.
$maymatch = !isset($child['constant']) && array_search($child['type'], array($temp['type'], FILE_ASN1_TYPE_ANY, FILE_ASN1_TYPE_CHOICE)) !== false;
$maymatch = !isset($child['constant']) && array_search($child['type'], array($temp['type'], self::TYPE_ANY, self::TYPE_CHOICE)) !== false;
}
}
}
@ -666,10 +621,10 @@ class File_ASN1
}
// Fail mapping if all input items have not been consumed.
return $i < $n? null: $map;
return $i < $n ? null: $map;
// the main diff between sets and sequences is the encapsulation of the foreach in another for loop
case FILE_ASN1_TYPE_SET:
case self::TYPE_SET:
$map = array();
// ignore the min and max
@ -686,9 +641,9 @@ class File_ASN1
for ($i = 0; $i < count($decoded['content']); $i++) {
$temp = $decoded['content'][$i];
$tempClass = FILE_ASN1_CLASS_UNIVERSAL;
$tempClass = self::CLASS_UNIVERSAL;
if (isset($temp['constant'])) {
$tempClass = isset($temp['class']) ? $temp['class'] : FILE_ASN1_CLASS_CONTEXT_SPECIFIC;
$tempClass = isset($temp['class']) ? $temp['class'] : self::CLASS_CONTEXT_SPECIFIC;
}
foreach ($mapping['children'] as $key => $child) {
@ -696,14 +651,14 @@ class File_ASN1
continue;
}
$maymatch = true;
if ($child['type'] != FILE_ASN1_TYPE_CHOICE) {
$childClass = FILE_ASN1_CLASS_UNIVERSAL;
if ($child['type'] != self::TYPE_CHOICE) {
$childClass = self::CLASS_UNIVERSAL;
$constant = null;
if (isset($child['class'])) {
$childClass = $child['class'];
$constant = $child['cast'];
} elseif (isset($child['constant'])) {
$childClass = FILE_ASN1_CLASS_CONTEXT_SPECIFIC;
$childClass = self::CLASS_CONTEXT_SPECIFIC;
$constant = $child['constant'];
}
@ -712,7 +667,7 @@ class File_ASN1
$maymatch = $constant == $temp['constant'] && $childClass == $tempClass;
} else {
// Can only match if no constant expected and type matches or is generic.
$maymatch = !isset($child['constant']) && array_search($child['type'], array($temp['type'], FILE_ASN1_TYPE_ANY, FILE_ASN1_TYPE_CHOICE)) !== false;
$maymatch = !isset($child['constant']) && array_search($child['type'], array($temp['type'], self::TYPE_ANY, self::TYPE_CHOICE)) !== false;
}
}
@ -745,15 +700,15 @@ class File_ASN1
}
}
return $map;
case FILE_ASN1_TYPE_OBJECT_IDENTIFIER:
case self::TYPE_OBJECT_IDENTIFIER:
return isset($this->oids[$decoded['content']]) ? $this->oids[$decoded['content']] : $decoded['content'];
case FILE_ASN1_TYPE_UTC_TIME:
case FILE_ASN1_TYPE_GENERALIZED_TIME:
case self::TYPE_UTC_TIME:
case self::TYPE_GENERALIZED_TIME:
if (isset($mapping['implicit'])) {
$decoded['content'] = $this->_decodeTime($decoded['content'], $decoded['type']);
}
return @date($this->format, $decoded['content']);
case FILE_ASN1_TYPE_BIT_STRING:
case self::TYPE_BIT_STRING:
if (isset($mapping['mapping'])) {
$offset = ord($decoded['content'][0]);
$size = (strlen($decoded['content']) - 1) * 8 - $offset;
@ -782,29 +737,29 @@ class File_ASN1
}
return $values;
}
case FILE_ASN1_TYPE_OCTET_STRING:
case self::TYPE_OCTET_STRING:
return base64_encode($decoded['content']);
case FILE_ASN1_TYPE_NULL:
case self::TYPE_NULL:
return '';
case FILE_ASN1_TYPE_BOOLEAN:
case self::TYPE_BOOLEAN:
return $decoded['content'];
case FILE_ASN1_TYPE_NUMERIC_STRING:
case FILE_ASN1_TYPE_PRINTABLE_STRING:
case FILE_ASN1_TYPE_TELETEX_STRING:
case FILE_ASN1_TYPE_VIDEOTEX_STRING:
case FILE_ASN1_TYPE_IA5_STRING:
case FILE_ASN1_TYPE_GRAPHIC_STRING:
case FILE_ASN1_TYPE_VISIBLE_STRING:
case FILE_ASN1_TYPE_GENERAL_STRING:
case FILE_ASN1_TYPE_UNIVERSAL_STRING:
case FILE_ASN1_TYPE_UTF8_STRING:
case FILE_ASN1_TYPE_BMP_STRING:
case self::TYPE_NUMERIC_STRING:
case self::TYPE_PRINTABLE_STRING:
case self::TYPE_TELETEX_STRING:
case self::TYPE_VIDEOTEX_STRING:
case self::TYPE_IA5_STRING:
case self::TYPE_GRAPHIC_STRING:
case self::TYPE_VISIBLE_STRING:
case self::TYPE_GENERAL_STRING:
case self::TYPE_UNIVERSAL_STRING:
case self::TYPE_UTF8_STRING:
case self::TYPE_BMP_STRING:
return $decoded['content'];
case FILE_ASN1_TYPE_INTEGER:
case FILE_ASN1_TYPE_ENUMERATED:
case self::TYPE_INTEGER:
case self::TYPE_ENUMERATED:
$temp = $decoded['content'];
if (isset($mapping['implicit'])) {
$temp = new Math_BigInteger($decoded['content'], -256);
$temp = new BigInteger($decoded['content'], -256);
}
if (isset($mapping['mapping'])) {
$temp = (int) $temp->toString();
@ -824,10 +779,10 @@ class File_ASN1
*
* "Special" mappings can be applied via $special.
*
* @param String $source
* @param String $mapping
* @param Integer $idx
* @return String
* @param string $source
* @param string $mapping
* @param int $idx
* @return string
* @access public
*/
function encodeDER($source, $mapping, $special = array())
@ -839,15 +794,15 @@ class File_ASN1
/**
* ASN.1 Encode (Helper function)
*
* @param String $source
* @param String $mapping
* @param Integer $idx
* @return String
* @param string $source
* @param string $mapping
* @param int $idx
* @return string
* @access private
*/
function _encode_der($source, $mapping, $idx = null, $special = array())
{
if (is_object($source) && strtolower(get_class($source)) == 'file_asn1_element') {
if ($source instanceof Element) {
return $source->element;
}
@ -866,13 +821,13 @@ class File_ASN1
$tag = $mapping['type'];
switch ($tag) {
case FILE_ASN1_TYPE_SET: // Children order is not important, thus process in sequence.
case FILE_ASN1_TYPE_SEQUENCE:
case self::TYPE_SET: // Children order is not important, thus process in sequence.
case self::TYPE_SEQUENCE:
$tag|= 0x20; // set the constructed bit
$value = '';
// ignore the min and max
if (isset($mapping['min']) && isset($mapping['max'])) {
$value = array();
$child = $mapping['children'];
foreach ($source as $content) {
@ -880,13 +835,23 @@ class File_ASN1
if ($temp === false) {
return false;
}
$value.= $temp;
$value[]= $temp;
}
/* "The encodings of the component values of a set-of value shall appear in ascending order, the encodings being compared
as octet strings with the shorter components being padded at their trailing end with 0-octets.
NOTE - The padding octets are for comparison purposes only and do not appear in the encodings."
-- sec 11.6 of http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf */
if ($mapping['type'] == self::TYPE_SET) {
sort($value);
}
$value = implode($value, '');
break;
}
$value = '';
foreach ($mapping['children'] as $key => $child) {
if (!isset($source[$key])) {
if (!array_key_exists($key, $source)) {
if (!isset($child['optional'])) {
return false;
}
@ -915,18 +880,18 @@ class File_ASN1
AUTOMATIC TAGS, but the type defined by "Type" is an untagged choice type, an untagged open type, or
an untagged "DummyReference" (see ITU-T Rec. X.683 | ISO/IEC 8824-4, 8.3)."
*/
if (isset($child['explicit']) || $child['type'] == FILE_ASN1_TYPE_CHOICE) {
$subtag = chr((FILE_ASN1_CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | $child['constant']);
if (isset($child['explicit']) || $child['type'] == self::TYPE_CHOICE) {
$subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | $child['constant']);
$temp = $subtag . $this->_encodeLength(strlen($temp)) . $temp;
} else {
$subtag = chr((FILE_ASN1_CLASS_CONTEXT_SPECIFIC << 6) | (ord($temp[0]) & 0x20) | $child['constant']);
$subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | (ord($temp[0]) & 0x20) | $child['constant']);
$temp = $subtag . substr($temp, 1);
}
}
$value.= $temp;
}
break;
case FILE_ASN1_TYPE_CHOICE:
case self::TYPE_CHOICE:
$temp = false;
foreach ($mapping['children'] as $key => $child) {
@ -949,11 +914,11 @@ class File_ASN1
// if isset($child['constant']) is true then isset($child['optional']) should be true as well
if (isset($child['constant'])) {
if (isset($child['explicit']) || $child['type'] == FILE_ASN1_TYPE_CHOICE) {
$subtag = chr((FILE_ASN1_CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | $child['constant']);
if (isset($child['explicit']) || $child['type'] == self::TYPE_CHOICE) {
$subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | $child['constant']);
$temp = $subtag . $this->_encodeLength(strlen($temp)) . $temp;
} else {
$subtag = chr((FILE_ASN1_CLASS_CONTEXT_SPECIFIC << 6) | (ord($temp[0]) & 0x20) | $child['constant']);
$subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | (ord($temp[0]) & 0x20) | $child['constant']);
$temp = $subtag . substr($temp, 1);
}
}
@ -968,11 +933,11 @@ class File_ASN1
}
return $temp;
case FILE_ASN1_TYPE_INTEGER:
case FILE_ASN1_TYPE_ENUMERATED:
case self::TYPE_INTEGER:
case self::TYPE_ENUMERATED:
if (!isset($mapping['mapping'])) {
if (is_numeric($source)) {
$source = new Math_BigInteger($source);
$source = new BigInteger($source);
}
$value = $source->toBytes(true);
} else {
@ -980,20 +945,20 @@ class File_ASN1
if ($value === false) {
return false;
}
$value = new Math_BigInteger($value);
$value = new BigInteger($value);
$value = $value->toBytes(true);
}
if (!strlen($value)) {
$value = chr(0);
}
break;
case FILE_ASN1_TYPE_UTC_TIME:
case FILE_ASN1_TYPE_GENERALIZED_TIME:
$format = $mapping['type'] == FILE_ASN1_TYPE_UTC_TIME ? 'y' : 'Y';
case self::TYPE_UTC_TIME:
case self::TYPE_GENERALIZED_TIME:
$format = $mapping['type'] == self::TYPE_UTC_TIME ? 'y' : 'Y';
$format.= 'mdHis';
$value = @gmdate($format, strtotime($source)) . 'Z';
break;
case FILE_ASN1_TYPE_BIT_STRING:
case self::TYPE_BIT_STRING:
if (isset($mapping['mapping'])) {
$bits = array_fill(0, count($mapping['mapping']), 0);
$size = 0;
@ -1025,14 +990,14 @@ class File_ASN1
break;
}
case FILE_ASN1_TYPE_OCTET_STRING:
case self::TYPE_OCTET_STRING:
/* The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit,
the number of unused bits in the final subsequent octet. The number shall be in the range zero to seven.
-- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=16 */
$value = base64_decode($source);
break;
case FILE_ASN1_TYPE_OBJECT_IDENTIFIER:
case self::TYPE_OBJECT_IDENTIFIER:
$oid = preg_match('#(?:\d+\.)+#', $source) ? $source : array_search($source, $this->oids);
if ($oid === false) {
user_error('Invalid OID');
@ -1055,7 +1020,7 @@ class File_ASN1
$value.= $temp;
}
break;
case FILE_ASN1_TYPE_ANY:
case self::TYPE_ANY:
$loc = $this->location;
if (isset($idx)) {
array_pop($this->location);
@ -1063,21 +1028,21 @@ class File_ASN1
switch (true) {
case !isset($source):
return $this->_encode_der(null, array('type' => FILE_ASN1_TYPE_NULL) + $mapping, null, $special);
return $this->_encode_der(null, array('type' => self::TYPE_NULL) + $mapping, null, $special);
case is_int($source):
case is_object($source) && strtolower(get_class($source)) == 'math_biginteger':
return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_INTEGER) + $mapping, null, $special);
case $source instanceof BigInteger:
return $this->_encode_der($source, array('type' => self::TYPE_INTEGER) + $mapping, null, $special);
case is_float($source):
return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_REAL) + $mapping, null, $special);
return $this->_encode_der($source, array('type' => self::TYPE_REAL) + $mapping, null, $special);
case is_bool($source):
return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_BOOLEAN) + $mapping, null, $special);
return $this->_encode_der($source, array('type' => self::TYPE_BOOLEAN) + $mapping, null, $special);
case is_array($source) && count($source) == 1:
$typename = implode('', array_keys($source));
$outtype = array_search($typename, $this->ANYmap, true);
if ($outtype !== false) {
return $this->_encode_der($source[$typename], array('type' => $outtype) + $mapping, null, $special);
}
}
}
$filters = $this->filters;
foreach ($loc as $part) {
@ -1092,23 +1057,23 @@ class File_ASN1
return false;
}
return $this->_encode_der($source, $filters + $mapping, null, $special);
case FILE_ASN1_TYPE_NULL:
case self::TYPE_NULL:
$value = '';
break;
case FILE_ASN1_TYPE_NUMERIC_STRING:
case FILE_ASN1_TYPE_TELETEX_STRING:
case FILE_ASN1_TYPE_PRINTABLE_STRING:
case FILE_ASN1_TYPE_UNIVERSAL_STRING:
case FILE_ASN1_TYPE_UTF8_STRING:
case FILE_ASN1_TYPE_BMP_STRING:
case FILE_ASN1_TYPE_IA5_STRING:
case FILE_ASN1_TYPE_VISIBLE_STRING:
case FILE_ASN1_TYPE_VIDEOTEX_STRING:
case FILE_ASN1_TYPE_GRAPHIC_STRING:
case FILE_ASN1_TYPE_GENERAL_STRING:
case self::TYPE_NUMERIC_STRING:
case self::TYPE_TELETEX_STRING:
case self::TYPE_PRINTABLE_STRING:
case self::TYPE_UNIVERSAL_STRING:
case self::TYPE_UTF8_STRING:
case self::TYPE_BMP_STRING:
case self::TYPE_IA5_STRING:
case self::TYPE_VISIBLE_STRING:
case self::TYPE_VIDEOTEX_STRING:
case self::TYPE_GRAPHIC_STRING:
case self::TYPE_GENERAL_STRING:
$value = $source;
break;
case FILE_ASN1_TYPE_BOOLEAN:
case self::TYPE_BOOLEAN:
$value = $source ? "\xFF" : "\x00";
break;
default:
@ -1121,7 +1086,7 @@ class File_ASN1
}
if (isset($mapping['cast'])) {
if (isset($mapping['explicit']) || $mapping['type'] == FILE_ASN1_TYPE_CHOICE) {
if (isset($mapping['explicit']) || $mapping['type'] == self::TYPE_CHOICE) {
$value = chr($tag) . $this->_encodeLength(strlen($value)) . $value;
$tag = ($mapping['class'] << 6) | 0x20 | $mapping['cast'];
} else {
@ -1139,8 +1104,8 @@ class File_ASN1
* {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
*
* @access private
* @param Integer $length
* @return String
* @param int $length
* @return string
*/
function _encodeLength($length)
{
@ -1158,9 +1123,9 @@ class File_ASN1
* Called by _decode_ber() and in the case of implicit tags asn1map().
*
* @access private
* @param String $content
* @param Integer $tag
* @return String
* @param string $content
* @param int $tag
* @return string
*/
function _decodeTime($content, $tag)
{
@ -1172,7 +1137,7 @@ class File_ASN1
http://tools.ietf.org/html/rfc5280#section-4.1.2.5.2
http://www.obj-sys.com/asn1tutorial/node14.html */
$pattern = $tag == FILE_ASN1_TYPE_UTC_TIME ?
$pattern = $tag == self::TYPE_UTC_TIME ?
'#(..)(..)(..)(..)(..)(..)(.*)#' :
'#(....)(..)(..)(..)(..)(..).*([Z+-].*)$#';
@ -1180,7 +1145,7 @@ class File_ASN1
list(, $year, $month, $day, $hour, $minute, $second, $timezone) = $matches;
if ($tag == FILE_ASN1_TYPE_UTC_TIME) {
if ($tag == self::TYPE_UTC_TIME) {
$year = $year >= 50 ? "19$year" : "20$year";
}
@ -1207,7 +1172,7 @@ class File_ASN1
* Sets the time / date format for asn1map().
*
* @access public
* @param String $format
* @param string $format
*/
function setTimeFormat($format)
{
@ -1220,7 +1185,7 @@ class File_ASN1
* Load the relevant OIDs for a particular ASN.1 semantic mapping.
*
* @access public
* @param Array $oids
* @param array $oids
*/
function loadOIDs($oids)
{
@ -1230,10 +1195,10 @@ class File_ASN1
/**
* Load filters
*
* See File_X509, etc, for an example.
* See \phpseclib\File\X509, etc, for an example.
*
* @access public
* @param Array $filters
* @param array $filters
*/
function loadFilters($filters)
{
@ -1245,9 +1210,9 @@ class File_ASN1
*
* Inspired by array_shift
*
* @param String $string
* @param optional Integer $index
* @return String
* @param string $string
* @param int $index
* @return string
* @access private
*/
function _string_shift(&$string, $index = 1)
@ -1263,13 +1228,13 @@ class File_ASN1
* This is a lazy conversion, dealing only with character size.
* No real conversion table is used.
*
* @param String $in
* @param optional Integer $from
* @param optional Integer $to
* @return String
* @param string $in
* @param int $from
* @param int $to
* @return string
* @access public
*/
function convert($in, $from = FILE_ASN1_TYPE_UTF8_STRING, $to = FILE_ASN1_TYPE_UTF8_STRING)
function convert($in, $from = self::TYPE_UTF8_STRING, $to = self::TYPE_UTF8_STRING)
{
if (!isset($this->stringTypeSize[$from]) || !isset($this->stringTypeSize[$to])) {
return false;

View file

@ -0,0 +1,47 @@
<?php
/**
* Pure-PHP ASN.1 Parser
*
* PHP version 5
*
* @category File
* @package ASN1
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2012 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\File\ASN1;
/**
* ASN.1 Element
*
* Bypass normal encoding rules in phpseclib\File\ASN1::encodeDER()
*
* @package ASN1
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Element
{
/**
* Raw element value
*
* @var string
* @access private
*/
var $element;
/**
* Constructor
*
* @param string $encoded
* @return \phpseclib\File\ASN1\Element
* @access public
*/
function __construct($encoded)
{
$this->element = $encoded;
}
}

View file

@ -3,7 +3,7 @@
/**
* Pure-PHP X.509 Parser
*
* PHP versions 4 and 5
* PHP version 5
*
* Encode and decode X.509 certificates.
*
@ -16,123 +16,112 @@
* be encoded. It can be encoded explicitly or left out all together. This would effect the signature value and thus may invalidate the
* the certificate all together unless the certificate is re-signed.
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category File
* @package File_X509
* @package X509
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2012 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include File_ASN1
*/
if (!class_exists('File_ASN1')) {
include_once 'ASN1.php';
}
namespace phpseclib\File;
/**
* Flag to only accept signatures signed by certificate authorities
*
* Not really used anymore but retained all the same to suppress E_NOTICEs from old installs
*
* @access public
*/
define('FILE_X509_VALIDATE_SIGNATURE_BY_CA', 1);
/**#@+
* @access public
* @see File_X509::getDN()
*/
/**
* Return internal array representation
*/
define('FILE_X509_DN_ARRAY', 0);
/**
* Return string
*/
define('FILE_X509_DN_STRING', 1);
/**
* Return ASN.1 name string
*/
define('FILE_X509_DN_ASN1', 2);
/**
* Return OpenSSL compatible array
*/
define('FILE_X509_DN_OPENSSL', 3);
/**
* Return canonical ASN.1 RDNs string
*/
define('FILE_X509_DN_CANON', 4);
/**
* Return name hash for file indexing
*/
define('FILE_X509_DN_HASH', 5);
/**#@-*/
/**#@+
* @access public
* @see File_X509::saveX509()
* @see File_X509::saveCSR()
* @see File_X509::saveCRL()
*/
/**
* Save as PEM
*
* ie. a base64-encoded PEM with a header and a footer
*/
define('FILE_X509_FORMAT_PEM', 0);
/**
* Save as DER
*/
define('FILE_X509_FORMAT_DER', 1);
/**
* Save as a SPKAC
*
* Only works on CSRs. Not currently supported.
*/
define('FILE_X509_FORMAT_SPKAC', 2);
/**#@-*/
/**
* Attribute value disposition.
* If disposition is >= 0, this is the index of the target value.
*/
define('FILE_X509_ATTR_ALL', -1); // All attribute values (array).
define('FILE_X509_ATTR_APPEND', -2); // Add a value.
define('FILE_X509_ATTR_REPLACE', -3); // Clear first, then add a value.
use phpseclib\Crypt\Hash;
use phpseclib\Crypt\Random;
use phpseclib\Crypt\RSA;
use phpseclib\File\ASN1\Element;
use phpseclib\Math\BigInteger;
/**
* Pure-PHP X.509 Parser
*
* @package File_X509
* @package X509
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class File_X509
class X509
{
/**
* Flag to only accept signatures signed by certificate authorities
*
* Not really used anymore but retained all the same to suppress E_NOTICEs from old installs
*
* @access public
*/
const VALIDATE_SIGNATURE_BY_CA = 1;
/**#@+
* @access public
* @see \phpseclib\File\X509::getDN()
*/
/**
* Return internal array representation
*/
const DN_ARRAY = 0;
/**
* Return string
*/
const DN_STRING = 1;
/**
* Return ASN.1 name string
*/
const DN_ASN1 = 2;
/**
* Return OpenSSL compatible array
*/
const DN_OPENSSL = 3;
/**
* Return canonical ASN.1 RDNs string
*/
const DN_CANON = 4;
/**
* Return name hash for file indexing
*/
const DN_HASH = 5;
/**#@-*/
/**#@+
* @access public
* @see \phpseclib\File\X509::saveX509()
* @see \phpseclib\File\X509::saveCSR()
* @see \phpseclib\File\X509::saveCRL()
*/
/**
* Save as PEM
*
* ie. a base64-encoded PEM with a header and a footer
*/
const FORMAT_PEM = 0;
/**
* Save as DER
*/
const FORMAT_DER = 1;
/**
* Save as a SPKAC
*
* Only works on CSRs. Not currently supported.
*/
const FORMAT_SPKAC = 2;
/**
* Auto-detect the format
*
* Used only by the load*() functions
*/
const FORMAT_AUTO_DETECT = 3;
/**#@-*/
/**
* Attribute value disposition.
* If disposition is >= 0, this is the index of the target value.
*/
const ATTR_ALL = -1; // All attribute values (array).
const ATTR_APPEND = -2; // Add a value.
const ATTR_REPLACE = -3; // Clear first, then add a value.
/**
* ASN.1 syntax for X.509 certificates
*
* @var Array
* @var array
* @access private
*/
var $Certificate;
@ -155,6 +144,7 @@ class File_X509
var $CertificatePolicies;
var $AuthorityInfoAccessSyntax;
var $SubjectAltName;
var $SubjectDirectoryAttributes;
var $PrivateKeyUsagePeriod;
var $IssuerAltName;
var $PolicyMappings;
@ -178,10 +168,18 @@ class File_X509
var $SignedPublicKeyAndChallenge;
/**#@-*/
/**#@+
* ASN.1 syntax for various DN attributes
*
* @access private
*/
var $PostalAddress;
/**#@-*/
/**
* ASN.1 syntax for Certificate Signing Requests (RFC2986)
*
* @var Array
* @var array
* @access private
*/
var $CertificationRequest;
@ -189,7 +187,7 @@ class File_X509
/**
* ASN.1 syntax for Certificate Revocation Lists (RFC5280)
*
* @var Array
* @var array
* @access private
*/
var $CertificateList;
@ -197,7 +195,7 @@ class File_X509
/**
* Distinguished Name
*
* @var Array
* @var array
* @access private
*/
var $dn;
@ -205,7 +203,7 @@ class File_X509
/**
* Public key
*
* @var String
* @var string
* @access private
*/
var $publicKey;
@ -213,7 +211,7 @@ class File_X509
/**
* Private key
*
* @var String
* @var string
* @access private
*/
var $privateKey;
@ -221,7 +219,7 @@ class File_X509
/**
* Object identifiers for X.509 certificates
*
* @var Array
* @var array
* @access private
* @link http://en.wikipedia.org/wiki/Object_identifier
*/
@ -230,7 +228,7 @@ class File_X509
/**
* The certificate authorities
*
* @var Array
* @var array
* @access private
*/
var $CAs;
@ -238,7 +236,7 @@ class File_X509
/**
* The currently loaded certificate
*
* @var Array
* @var array
* @access private
*/
var $currentCert;
@ -246,10 +244,10 @@ class File_X509
/**
* The signature subject
*
* There's no guarantee File_X509 is going to reencode an X.509 cert in the same way it was originally
* There's no guarantee \phpseclib\File\X509 is going to re-encode an X.509 cert in the same way it was originally
* encoded so we take save the portion of the original cert that the signature would have made for.
*
* @var String
* @var string
* @access private
*/
var $signatureSubject;
@ -257,7 +255,7 @@ class File_X509
/**
* Certificate Start Date
*
* @var String
* @var string
* @access private
*/
var $startDate;
@ -265,7 +263,7 @@ class File_X509
/**
* Certificate End Date
*
* @var String
* @var string
* @access private
*/
var $endDate;
@ -273,7 +271,7 @@ class File_X509
/**
* Serial Number
*
* @var String
* @var string
* @access private
*/
var $serialNumber;
@ -284,7 +282,7 @@ class File_X509
* See {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.1 RFC5280#section-4.2.1.1} and
* {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.2 RFC5280#section-4.2.1.2}.
*
* @var String
* @var string
* @access private
*/
var $currentKeyIdentifier;
@ -292,7 +290,7 @@ class File_X509
/**
* CA Flag
*
* @var Boolean
* @var bool
* @access private
*/
var $caFlag = false;
@ -300,7 +298,7 @@ class File_X509
/**
* SPKAC Challenge
*
* @var String
* @var string
* @access private
*/
var $challenge;
@ -308,43 +306,39 @@ class File_X509
/**
* Default Constructor.
*
* @return File_X509
* @return \phpseclib\File\X509
* @access public
*/
function File_X509()
function __construct()
{
if (!class_exists('Math_BigInteger')) {
include_once 'Math/BigInteger.php';
}
// Explicitly Tagged Module, 1988 Syntax
// http://tools.ietf.org/html/rfc5280#appendix-A.1
$this->DirectoryString = array(
'type' => FILE_ASN1_TYPE_CHOICE,
'type' => ASN1::TYPE_CHOICE,
'children' => array(
'teletexString' => array('type' => FILE_ASN1_TYPE_TELETEX_STRING),
'printableString' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING),
'universalString' => array('type' => FILE_ASN1_TYPE_UNIVERSAL_STRING),
'utf8String' => array('type' => FILE_ASN1_TYPE_UTF8_STRING),
'bmpString' => array('type' => FILE_ASN1_TYPE_BMP_STRING)
'teletexString' => array('type' => ASN1::TYPE_TELETEX_STRING),
'printableString' => array('type' => ASN1::TYPE_PRINTABLE_STRING),
'universalString' => array('type' => ASN1::TYPE_UNIVERSAL_STRING),
'utf8String' => array('type' => ASN1::TYPE_UTF8_STRING),
'bmpString' => array('type' => ASN1::TYPE_BMP_STRING)
)
);
$this->PKCS9String = array(
'type' => FILE_ASN1_TYPE_CHOICE,
'type' => ASN1::TYPE_CHOICE,
'children' => array(
'ia5String' => array('type' => FILE_ASN1_TYPE_IA5_STRING),
'ia5String' => array('type' => ASN1::TYPE_IA5_STRING),
'directoryString' => $this->DirectoryString
)
);
$this->AttributeValue = array('type' => FILE_ASN1_TYPE_ANY);
$this->AttributeValue = array('type' => ASN1::TYPE_ANY);
$AttributeType = array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER);
$AttributeType = array('type' => ASN1::TYPE_OBJECT_IDENTIFIER);
$AttributeTypeAndValue = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'type' => $AttributeType,
'value'=> $this->AttributeValue
@ -359,7 +353,7 @@ class File_X509
- https://www.opends.org/wiki/page/DefinitionRelativeDistinguishedName
*/
$this->RelativeDistinguishedName = array(
'type' => FILE_ASN1_TYPE_SET,
'type' => ASN1::TYPE_SET,
'min' => 1,
'max' => -1,
'children' => $AttributeTypeAndValue
@ -367,7 +361,7 @@ class File_X509
// http://tools.ietf.org/html/rfc5280#section-4.1.2.4
$RDNSequence = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
// RDNSequence does not define a min or a max, which means it doesn't have one
'min' => 0,
'max' => -1,
@ -375,7 +369,7 @@ class File_X509
);
$this->Name = array(
'type' => FILE_ASN1_TYPE_CHOICE,
'type' => ASN1::TYPE_CHOICE,
'children' => array(
'rdnSequence' => $RDNSequence
)
@ -383,11 +377,11 @@ class File_X509
// http://tools.ietf.org/html/rfc5280#section-4.1.1.2
$AlgorithmIdentifier = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'algorithm' => array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER),
'algorithm' => array('type' => ASN1::TYPE_OBJECT_IDENTIFIER),
'parameters' => array(
'type' => FILE_ASN1_TYPE_ANY,
'type' => ASN1::TYPE_ANY,
'optional' => true
)
)
@ -401,20 +395,20 @@ class File_X509
http://tools.ietf.org/html/rfc5280#section-4.2
*/
$Extension = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'extnId' => array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER),
'extnId' => array('type' => ASN1::TYPE_OBJECT_IDENTIFIER),
'critical' => array(
'type' => FILE_ASN1_TYPE_BOOLEAN,
'type' => ASN1::TYPE_BOOLEAN,
'optional' => true,
'default' => false
),
'extnValue' => array('type' => FILE_ASN1_TYPE_OCTET_STRING)
'extnValue' => array('type' => ASN1::TYPE_OCTET_STRING)
)
);
$this->Extensions = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'min' => 1,
// technically, it's MAX, but we'll assume anything < 0 is MAX
'max' => -1,
@ -423,42 +417,42 @@ class File_X509
);
$SubjectPublicKeyInfo = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'algorithm' => $AlgorithmIdentifier,
'subjectPublicKey' => array('type' => FILE_ASN1_TYPE_BIT_STRING)
'subjectPublicKey' => array('type' => ASN1::TYPE_BIT_STRING)
)
);
$UniqueIdentifier = array('type' => FILE_ASN1_TYPE_BIT_STRING);
$UniqueIdentifier = array('type' => ASN1::TYPE_BIT_STRING);
$Time = array(
'type' => FILE_ASN1_TYPE_CHOICE,
'type' => ASN1::TYPE_CHOICE,
'children' => array(
'utcTime' => array('type' => FILE_ASN1_TYPE_UTC_TIME),
'generalTime' => array('type' => FILE_ASN1_TYPE_GENERALIZED_TIME)
'utcTime' => array('type' => ASN1::TYPE_UTC_TIME),
'generalTime' => array('type' => ASN1::TYPE_GENERALIZED_TIME)
)
);
// http://tools.ietf.org/html/rfc5280#section-4.1.2.5
$Validity = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'notBefore' => $Time,
'notAfter' => $Time
)
);
$CertificateSerialNumber = array('type' => FILE_ASN1_TYPE_INTEGER);
$CertificateSerialNumber = array('type' => ASN1::TYPE_INTEGER);
$Version = array(
'type' => FILE_ASN1_TYPE_INTEGER,
'type' => ASN1::TYPE_INTEGER,
'mapping' => array('v1', 'v2', 'v3')
);
// assert($TBSCertificate['children']['signature'] == $Certificate['children']['signatureAlgorithm'])
$TBSCertificate = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
// technically, default implies optional, but we'll define it as being optional, none-the-less, just to
// reenforce that fact
@ -496,16 +490,16 @@ class File_X509
);
$this->Certificate = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'tbsCertificate' => $TBSCertificate,
'signatureAlgorithm' => $AlgorithmIdentifier,
'signature' => array('type' => FILE_ASN1_TYPE_BIT_STRING)
'signature' => array('type' => ASN1::TYPE_BIT_STRING)
)
);
$this->KeyUsage = array(
'type' => FILE_ASN1_TYPE_BIT_STRING,
'type' => ASN1::TYPE_BIT_STRING,
'mapping' => array(
'digitalSignature',
'nonRepudiation',
@ -520,52 +514,52 @@ class File_X509
);
$this->BasicConstraints = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'cA' => array(
'type' => FILE_ASN1_TYPE_BOOLEAN,
'type' => ASN1::TYPE_BOOLEAN,
'optional' => true,
'default' => false
),
'pathLenConstraint' => array(
'type' => FILE_ASN1_TYPE_INTEGER,
'type' => ASN1::TYPE_INTEGER,
'optional' => true
)
)
);
$this->KeyIdentifier = array('type' => FILE_ASN1_TYPE_OCTET_STRING);
$this->KeyIdentifier = array('type' => ASN1::TYPE_OCTET_STRING);
$OrganizationalUnitNames = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'min' => 1,
'max' => 4, // ub-organizational-units
'children' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING)
'children' => array('type' => ASN1::TYPE_PRINTABLE_STRING)
);
$PersonalName = array(
'type' => FILE_ASN1_TYPE_SET,
'type' => ASN1::TYPE_SET,
'children' => array(
'surname' => array(
'type' => FILE_ASN1_TYPE_PRINTABLE_STRING,
'type' => ASN1::TYPE_PRINTABLE_STRING,
'constant' => 0,
'optional' => true,
'implicit' => true
),
'given-name' => array(
'type' => FILE_ASN1_TYPE_PRINTABLE_STRING,
'type' => ASN1::TYPE_PRINTABLE_STRING,
'constant' => 1,
'optional' => true,
'implicit' => true
),
'initials' => array(
'type' => FILE_ASN1_TYPE_PRINTABLE_STRING,
'type' => ASN1::TYPE_PRINTABLE_STRING,
'constant' => 2,
'optional' => true,
'implicit' => true
),
'generation-qualifier' => array(
'type' => FILE_ASN1_TYPE_PRINTABLE_STRING,
'type' => ASN1::TYPE_PRINTABLE_STRING,
'constant' => 3,
'optional' => true,
'implicit' => true
@ -573,52 +567,52 @@ class File_X509
)
);
$NumericUserIdentifier = array('type' => FILE_ASN1_TYPE_NUMERIC_STRING);
$NumericUserIdentifier = array('type' => ASN1::TYPE_NUMERIC_STRING);
$OrganizationName = array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING);
$OrganizationName = array('type' => ASN1::TYPE_PRINTABLE_STRING);
$PrivateDomainName = array(
'type' => FILE_ASN1_TYPE_CHOICE,
'type' => ASN1::TYPE_CHOICE,
'children' => array(
'numeric' => array('type' => FILE_ASN1_TYPE_NUMERIC_STRING),
'printable' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING)
'numeric' => array('type' => ASN1::TYPE_NUMERIC_STRING),
'printable' => array('type' => ASN1::TYPE_PRINTABLE_STRING)
)
);
$TerminalIdentifier = array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING);
$TerminalIdentifier = array('type' => ASN1::TYPE_PRINTABLE_STRING);
$NetworkAddress = array('type' => FILE_ASN1_TYPE_NUMERIC_STRING);
$NetworkAddress = array('type' => ASN1::TYPE_NUMERIC_STRING);
$AdministrationDomainName = array(
'type' => FILE_ASN1_TYPE_CHOICE,
// if class isn't present it's assumed to be FILE_ASN1_CLASS_UNIVERSAL or
// (if constant is present) FILE_ASN1_CLASS_CONTEXT_SPECIFIC
'class' => FILE_ASN1_CLASS_APPLICATION,
'type' => ASN1::TYPE_CHOICE,
// if class isn't present it's assumed to be \phpseclib\File\ASN1::CLASS_UNIVERSAL or
// (if constant is present) \phpseclib\File\ASN1::CLASS_CONTEXT_SPECIFIC
'class' => ASN1::CLASS_APPLICATION,
'cast' => 2,
'children' => array(
'numeric' => array('type' => FILE_ASN1_TYPE_NUMERIC_STRING),
'printable' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING)
'numeric' => array('type' => ASN1::TYPE_NUMERIC_STRING),
'printable' => array('type' => ASN1::TYPE_PRINTABLE_STRING)
)
);
$CountryName = array(
'type' => FILE_ASN1_TYPE_CHOICE,
// if class isn't present it's assumed to be FILE_ASN1_CLASS_UNIVERSAL or
// (if constant is present) FILE_ASN1_CLASS_CONTEXT_SPECIFIC
'class' => FILE_ASN1_CLASS_APPLICATION,
'type' => ASN1::TYPE_CHOICE,
// if class isn't present it's assumed to be \phpseclib\File\ASN1::CLASS_UNIVERSAL or
// (if constant is present) \phpseclib\File\ASN1::CLASS_CONTEXT_SPECIFIC
'class' => ASN1::CLASS_APPLICATION,
'cast' => 1,
'children' => array(
'x121-dcc-code' => array('type' => FILE_ASN1_TYPE_NUMERIC_STRING),
'iso-3166-alpha2-code' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING)
'x121-dcc-code' => array('type' => ASN1::TYPE_NUMERIC_STRING),
'iso-3166-alpha2-code' => array('type' => ASN1::TYPE_PRINTABLE_STRING)
)
);
$AnotherName = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'type-id' => array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER),
'type-id' => array('type' => ASN1::TYPE_OBJECT_IDENTIFIER),
'value' => array(
'type' => FILE_ASN1_TYPE_ANY,
'type' => ASN1::TYPE_ANY,
'constant' => 0,
'optional' => true,
'explicit' => true
@ -627,16 +621,16 @@ class File_X509
);
$ExtensionAttribute = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'extension-attribute-type' => array(
'type' => FILE_ASN1_TYPE_PRINTABLE_STRING,
'type' => ASN1::TYPE_PRINTABLE_STRING,
'constant' => 0,
'optional' => true,
'implicit' => true
),
'extension-attribute-value' => array(
'type' => FILE_ASN1_TYPE_ANY,
'type' => ASN1::TYPE_ANY,
'constant' => 1,
'optional' => true,
'explicit' => true
@ -645,29 +639,29 @@ class File_X509
);
$ExtensionAttributes = array(
'type' => FILE_ASN1_TYPE_SET,
'type' => ASN1::TYPE_SET,
'min' => 1,
'max' => 256, // ub-extension-attributes
'children' => $ExtensionAttribute
);
$BuiltInDomainDefinedAttribute = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'type' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING),
'value' => array('type' => FILE_ASN1_TYPE_PRINTABLE_STRING)
'type' => array('type' => ASN1::TYPE_PRINTABLE_STRING),
'value' => array('type' => ASN1::TYPE_PRINTABLE_STRING)
)
);
$BuiltInDomainDefinedAttributes = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'min' => 1,
'max' => 4, // ub-domain-defined-attributes
'children' => $BuiltInDomainDefinedAttribute
);
$BuiltInStandardAttributes = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'country-name' => array('optional' => true) + $CountryName,
'administration-domain-name' => array('optional' => true) + $AdministrationDomainName,
@ -710,7 +704,7 @@ class File_X509
);
$ORAddress = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'built-in-standard-attributes' => $BuiltInStandardAttributes,
'built-in-domain-defined-attributes' => array('optional' => true) + $BuiltInDomainDefinedAttributes,
@ -719,14 +713,14 @@ class File_X509
);
$EDIPartyName = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'nameAssigner' => array(
'constant' => 0,
'optional' => true,
'implicit' => true
) + $this->DirectoryString,
// partyName is technically required but File_ASN1 doesn't currently support non-optional constants and
// partyName is technically required but \phpseclib\File\ASN1 doesn't currently support non-optional constants and
// setting it to optional gets the job done in any event.
'partyName' => array(
'constant' => 1,
@ -737,7 +731,7 @@ class File_X509
);
$GeneralName = array(
'type' => FILE_ASN1_TYPE_CHOICE,
'type' => ASN1::TYPE_CHOICE,
'children' => array(
'otherName' => array(
'constant' => 0,
@ -745,13 +739,13 @@ class File_X509
'implicit' => true
) + $AnotherName,
'rfc822Name' => array(
'type' => FILE_ASN1_TYPE_IA5_STRING,
'type' => ASN1::TYPE_IA5_STRING,
'constant' => 1,
'optional' => true,
'implicit' => true
),
'dNSName' => array(
'type' => FILE_ASN1_TYPE_IA5_STRING,
'type' => ASN1::TYPE_IA5_STRING,
'constant' => 2,
'optional' => true,
'implicit' => true
@ -772,19 +766,19 @@ class File_X509
'implicit' => true
) + $EDIPartyName,
'uniformResourceIdentifier' => array(
'type' => FILE_ASN1_TYPE_IA5_STRING,
'type' => ASN1::TYPE_IA5_STRING,
'constant' => 6,
'optional' => true,
'implicit' => true
),
'iPAddress' => array(
'type' => FILE_ASN1_TYPE_OCTET_STRING,
'type' => ASN1::TYPE_OCTET_STRING,
'constant' => 7,
'optional' => true,
'implicit' => true
),
'registeredID' => array(
'type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER,
'type' => ASN1::TYPE_OBJECT_IDENTIFIER,
'constant' => 8,
'optional' => true,
'implicit' => true
@ -793,7 +787,7 @@ class File_X509
);
$GeneralNames = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'min' => 1,
'max' => -1,
'children' => $GeneralName
@ -802,7 +796,7 @@ class File_X509
$this->IssuerAltName = $GeneralNames;
$ReasonFlags = array(
'type' => FILE_ASN1_TYPE_BIT_STRING,
'type' => ASN1::TYPE_BIT_STRING,
'mapping' => array(
'unused',
'keyCompromise',
@ -817,7 +811,7 @@ class File_X509
);
$DistributionPointName = array(
'type' => FILE_ASN1_TYPE_CHOICE,
'type' => ASN1::TYPE_CHOICE,
'children' => array(
'fullName' => array(
'constant' => 0,
@ -833,7 +827,7 @@ class File_X509
);
$DistributionPoint = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'distributionPoint' => array(
'constant' => 0,
@ -854,14 +848,14 @@ class File_X509
);
$this->CRLDistributionPoints = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'min' => 1,
'max' => -1,
'children' => $DistributionPoint
);
$this->AuthorityKeyIdentifier = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'keyIdentifier' => array(
'constant' => 0,
@ -881,24 +875,24 @@ class File_X509
)
);
$PolicyQualifierId = array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER);
$PolicyQualifierId = array('type' => ASN1::TYPE_OBJECT_IDENTIFIER);
$PolicyQualifierInfo = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'policyQualifierId' => $PolicyQualifierId,
'qualifier' => array('type' => FILE_ASN1_TYPE_ANY)
'qualifier' => array('type' => ASN1::TYPE_ANY)
)
);
$CertPolicyId = array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER);
$CertPolicyId = array('type' => ASN1::TYPE_OBJECT_IDENTIFIER);
$PolicyInformation = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'policyIdentifier' => $CertPolicyId,
'policyQualifiers' => array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'min' => 0,
'max' => -1,
'optional' => true,
@ -908,18 +902,18 @@ class File_X509
);
$this->CertificatePolicies = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'min' => 1,
'max' => -1,
'children' => $PolicyInformation
);
$this->PolicyMappings = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'min' => 1,
'max' => -1,
'children' => array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'issuerDomainPolicy' => $CertPolicyId,
'subjectDomainPolicy' => $CertPolicyId
@ -927,25 +921,25 @@ class File_X509
)
);
$KeyPurposeId = array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER);
$KeyPurposeId = array('type' => ASN1::TYPE_OBJECT_IDENTIFIER);
$this->ExtKeyUsageSyntax = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'min' => 1,
'max' => -1,
'children' => $KeyPurposeId
);
$AccessDescription = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'accessMethod' => array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER),
'accessMethod' => array('type' => ASN1::TYPE_OBJECT_IDENTIFIER),
'accessLocation' => $GeneralName
)
);
$this->AuthorityInfoAccessSyntax = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'min' => 1,
'max' => -1,
'children' => $AccessDescription
@ -954,32 +948,32 @@ class File_X509
$this->SubjectAltName = $GeneralNames;
$this->PrivateKeyUsagePeriod = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'notBefore' => array(
'constant' => 0,
'optional' => true,
'implicit' => true,
'type' => FILE_ASN1_TYPE_GENERALIZED_TIME),
'type' => ASN1::TYPE_GENERALIZED_TIME),
'notAfter' => array(
'constant' => 1,
'optional' => true,
'implicit' => true,
'type' => FILE_ASN1_TYPE_GENERALIZED_TIME)
'type' => ASN1::TYPE_GENERALIZED_TIME)
)
);
$BaseDistance = array('type' => FILE_ASN1_TYPE_INTEGER);
$BaseDistance = array('type' => ASN1::TYPE_INTEGER);
$GeneralSubtree = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'base' => $GeneralName,
'minimum' => array(
'constant' => 0,
'optional' => true,
'implicit' => true,
'default' => new Math_BigInteger(0)
'default' => new BigInteger(0)
) + $BaseDistance,
'maximum' => array(
'constant' => 1,
@ -990,14 +984,14 @@ class File_X509
);
$GeneralSubtrees = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'min' => 1,
'max' => -1,
'children' => $GeneralSubtree
);
$this->NameConstraints = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'permittedSubtrees' => array(
'constant' => 0,
@ -1012,33 +1006,33 @@ class File_X509
)
);
$this->CPSuri = array('type' => FILE_ASN1_TYPE_IA5_STRING);
$this->CPSuri = array('type' => ASN1::TYPE_IA5_STRING);
$DisplayText = array(
'type' => FILE_ASN1_TYPE_CHOICE,
'type' => ASN1::TYPE_CHOICE,
'children' => array(
'ia5String' => array('type' => FILE_ASN1_TYPE_IA5_STRING),
'visibleString' => array('type' => FILE_ASN1_TYPE_VISIBLE_STRING),
'bmpString' => array('type' => FILE_ASN1_TYPE_BMP_STRING),
'utf8String' => array('type' => FILE_ASN1_TYPE_UTF8_STRING)
'ia5String' => array('type' => ASN1::TYPE_IA5_STRING),
'visibleString' => array('type' => ASN1::TYPE_VISIBLE_STRING),
'bmpString' => array('type' => ASN1::TYPE_BMP_STRING),
'utf8String' => array('type' => ASN1::TYPE_UTF8_STRING)
)
);
$NoticeReference = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'organization' => $DisplayText,
'noticeNumbers' => array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'min' => 1,
'max' => 200,
'children' => array('type' => FILE_ASN1_TYPE_INTEGER)
'children' => array('type' => ASN1::TYPE_INTEGER)
)
)
);
$this->UserNotice = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'noticeRef' => array(
'optional' => true,
@ -1053,7 +1047,7 @@ class File_X509
// mapping is from <http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html>
$this->netscape_cert_type = array(
'type' => FILE_ASN1_TYPE_BIT_STRING,
'type' => ASN1::TYPE_BIT_STRING,
'mapping' => array(
'SSLClient',
'SSLServer',
@ -1066,17 +1060,17 @@ class File_X509
)
);
$this->netscape_comment = array('type' => FILE_ASN1_TYPE_IA5_STRING);
$this->netscape_ca_policy_url = array('type' => FILE_ASN1_TYPE_IA5_STRING);
$this->netscape_comment = array('type' => ASN1::TYPE_IA5_STRING);
$this->netscape_ca_policy_url = array('type' => ASN1::TYPE_IA5_STRING);
// attribute is used in RFC2986 but we're using the RFC5280 definition
$Attribute = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'type' => $AttributeType,
'value'=> array(
'type' => FILE_ASN1_TYPE_SET,
'type' => ASN1::TYPE_SET,
'min' => 1,
'max' => -1,
'children' => $this->AttributeValue
@ -1084,20 +1078,27 @@ class File_X509
)
);
$this->SubjectDirectoryAttributes = array(
'type' => ASN1::TYPE_SEQUENCE,
'min' => 1,
'max' => -1,
'children' => $Attribute
);
// adapted from <http://tools.ietf.org/html/rfc2986>
$Attributes = array(
'type' => FILE_ASN1_TYPE_SET,
'type' => ASN1::TYPE_SET,
'min' => 1,
'max' => -1,
'children' => $Attribute
);
$CertificationRequestInfo = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'version' => array(
'type' => FILE_ASN1_TYPE_INTEGER,
'type' => ASN1::TYPE_INTEGER,
'mapping' => array('v1')
),
'subject' => $this->Name,
@ -1111,16 +1112,16 @@ class File_X509
);
$this->CertificationRequest = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'certificationRequestInfo' => $CertificationRequestInfo,
'signatureAlgorithm' => $AlgorithmIdentifier,
'signature' => array('type' => FILE_ASN1_TYPE_BIT_STRING)
'signature' => array('type' => ASN1::TYPE_BIT_STRING)
)
);
$RevokedCertificate = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'userCertificate' => $CertificateSerialNumber,
'revocationDate' => $Time,
@ -1131,7 +1132,7 @@ class File_X509
);
$TBSCertList = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'version' => array(
'optional' => true,
@ -1144,7 +1145,7 @@ class File_X509
'optional' => true
) + $Time,
'revokedCertificates' => array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'optional' => true,
'min' => 0,
'max' => -1,
@ -1159,17 +1160,17 @@ class File_X509
);
$this->CertificateList = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'tbsCertList' => $TBSCertList,
'signatureAlgorithm' => $AlgorithmIdentifier,
'signature' => array('type' => FILE_ASN1_TYPE_BIT_STRING)
'signature' => array('type' => ASN1::TYPE_BIT_STRING)
)
);
$this->CRLNumber = array('type' => FILE_ASN1_TYPE_INTEGER);
$this->CRLNumber = array('type' => ASN1::TYPE_INTEGER);
$this->CRLReason = array('type' => FILE_ASN1_TYPE_ENUMERATED,
$this->CRLReason = array('type' => ASN1::TYPE_ENUMERATED,
'mapping' => array(
'unspecified',
'keyCompromise',
@ -1185,7 +1186,7 @@ class File_X509
)
);
$this->IssuingDistributionPoint = array('type' => FILE_ASN1_TYPE_SEQUENCE,
$this->IssuingDistributionPoint = array('type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'distributionPoint' => array(
'constant' => 0,
@ -1193,14 +1194,14 @@ class File_X509
'explicit' => true
) + $DistributionPointName,
'onlyContainsUserCerts' => array(
'type' => FILE_ASN1_TYPE_BOOLEAN,
'type' => ASN1::TYPE_BOOLEAN,
'constant' => 1,
'optional' => true,
'default' => false,
'implicit' => true
),
'onlyContainsCACerts' => array(
'type' => FILE_ASN1_TYPE_BOOLEAN,
'type' => ASN1::TYPE_BOOLEAN,
'constant' => 2,
'optional' => true,
'default' => false,
@ -1212,14 +1213,14 @@ class File_X509
'implicit' => true
) + $ReasonFlags,
'indirectCRL' => array(
'type' => FILE_ASN1_TYPE_BOOLEAN,
'type' => ASN1::TYPE_BOOLEAN,
'constant' => 4,
'optional' => true,
'default' => false,
'implicit' => true
),
'onlyContainsAttributeCerts' => array(
'type' => FILE_ASN1_TYPE_BOOLEAN,
'type' => ASN1::TYPE_BOOLEAN,
'constant' => 5,
'optional' => true,
'default' => false,
@ -1228,29 +1229,37 @@ class File_X509
)
);
$this->InvalidityDate = array('type' => FILE_ASN1_TYPE_GENERALIZED_TIME);
$this->InvalidityDate = array('type' => ASN1::TYPE_GENERALIZED_TIME);
$this->CertificateIssuer = $GeneralNames;
$this->HoldInstructionCode = array('type' => FILE_ASN1_TYPE_OBJECT_IDENTIFIER);
$this->HoldInstructionCode = array('type' => ASN1::TYPE_OBJECT_IDENTIFIER);
$PublicKeyAndChallenge = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'spki' => $SubjectPublicKeyInfo,
'challenge' => array('type' => FILE_ASN1_TYPE_IA5_STRING)
'challenge' => array('type' => ASN1::TYPE_IA5_STRING)
)
);
$this->SignedPublicKeyAndChallenge = array(
'type' => FILE_ASN1_TYPE_SEQUENCE,
'type' => ASN1::TYPE_SEQUENCE,
'children' => array(
'publicKeyAndChallenge' => $PublicKeyAndChallenge,
'signatureAlgorithm' => $AlgorithmIdentifier,
'signature' => array('type' => FILE_ASN1_TYPE_BIT_STRING)
'signature' => array('type' => ASN1::TYPE_BIT_STRING)
)
);
$this->PostalAddress = array(
'type' => ASN1::TYPE_SEQUENCE,
'optional' => true,
'min' => 1,
'max' => -1,
'children' => $this->DirectoryString
);
// OIDs from RFC5280 and those RFCs mentioned in RFC5280#section-4.1.1.2
$this->oids = array(
'1.3.6.1.5.5.7' => 'id-pkix',
@ -1285,6 +1294,7 @@ class File_X509
'2.5.4.9' => 'id-at-streetAddress',
'2.5.4.45' => 'id-at-uniqueIdentifier',
'2.5.4.72' => 'id-at-role',
'2.5.4.16' => 'id-at-postalAddress',
'0.9.2342.19200300.100.1.25' => 'id-domainComponent',
'1.2.840.113549.1.9' => 'pkcs-9',
@ -1422,11 +1432,12 @@ class File_X509
*
* Returns an associative array describing the X.509 cert or a false if the cert failed to load
*
* @param String $cert
* @param string $cert
* @param int $mode
* @access public
* @return Mixed
* @return mixed
*/
function loadX509($cert)
function loadX509($cert, $mode = self::FORMAT_AUTO_DETECT)
{
if (is_array($cert) && isset($cert['tbsCertificate'])) {
unset($this->currentCert);
@ -1445,9 +1456,15 @@ class File_X509
return $cert;
}
$asn1 = new File_ASN1();
$asn1 = new ASN1();
$cert = $this->_extractBER($cert);
if ($mode != self::FORMAT_DER) {
$newcert = $this->_extractBER($cert);
if ($mode == self::FORMAT_PEM && $cert == $newcert) {
return false;
}
$cert = $newcert;
}
if ($cert === false) {
$this->currentCert = false;
@ -1467,7 +1484,11 @@ class File_X509
$this->signatureSubject = substr($cert, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
$this->_mapInExtensions($x509, 'tbsCertificate/extensions', $asn1);
if ($this->_isSubArrayValid($x509, 'tbsCertificate/extensions')) {
$this->_mapInExtensions($x509, 'tbsCertificate/extensions', $asn1);
}
$this->_mapInDNs($x509, 'tbsCertificate/issuer/rdnSequence', $asn1);
$this->_mapInDNs($x509, 'tbsCertificate/subject/rdnSequence', $asn1);
$key = &$x509['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'];
$key = $this->_reformatKey($x509['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], $key);
@ -1484,12 +1505,12 @@ class File_X509
/**
* Save X.509 certificate
*
* @param Array $cert
* @param Integer $format optional
* @param array $cert
* @param int $format optional
* @access public
* @return String
* @return string
*/
function saveX509($cert, $format = FILE_X509_FORMAT_PEM)
function saveX509($cert, $format = self::FORMAT_PEM)
{
if (!is_array($cert) || !isset($cert['tbsCertificate'])) {
return false;
@ -1505,14 +1526,24 @@ class File_X509
case 'rsaEncryption':
$cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']
= base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'])));
/* "[For RSA keys] the parameters field MUST have ASN.1 type NULL for this algorithm identifier."
-- https://tools.ietf.org/html/rfc3279#section-2.3.1
given that and the fact that RSA keys appear ot be the only key type for which the parameters field can be blank,
it seems like perhaps the ASN.1 description ought not say the parameters field is OPTIONAL, but whatever.
*/
$cert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['parameters'] = null;
// https://tools.ietf.org/html/rfc3279#section-2.2.1
$cert['signatureAlgorithm']['parameters'] = null;
$cert['tbsCertificate']['signature']['parameters'] = null;
}
}
$asn1 = new File_ASN1();
$asn1 = new ASN1();
$asn1->loadOIDs($this->oids);
$filters = array();
$type_utf8_string = array('type' => FILE_ASN1_TYPE_UTF8_STRING);
$type_utf8_string = array('type' => ASN1::TYPE_UTF8_STRING);
$filters['tbsCertificate']['signature']['parameters'] = $type_utf8_string;
$filters['tbsCertificate']['signature']['issuer']['rdnSequence']['value'] = $type_utf8_string;
$filters['tbsCertificate']['issuer']['rdnSequence']['value'] = $type_utf8_string;
@ -1524,23 +1555,25 @@ class File_X509
$filters['distributionPoint']['fullName']['directoryName']['rdnSequence']['value'] = $type_utf8_string;
$filters['directoryName']['rdnSequence']['value'] = $type_utf8_string;
/* in the case of policyQualifiers/qualifier, the type has to be FILE_ASN1_TYPE_IA5_STRING.
FILE_ASN1_TYPE_PRINTABLE_STRING will cause OpenSSL's X.509 parser to spit out random
/* in the case of policyQualifiers/qualifier, the type has to be \phpseclib\File\ASN1::TYPE_IA5_STRING.
\phpseclib\File\ASN1::TYPE_PRINTABLE_STRING will cause OpenSSL's X.509 parser to spit out random
characters.
*/
$filters['policyQualifiers']['qualifier']
= array('type' => FILE_ASN1_TYPE_IA5_STRING);
= array('type' => ASN1::TYPE_IA5_STRING);
$asn1->loadFilters($filters);
$this->_mapOutExtensions($cert, 'tbsCertificate/extensions', $asn1);
$this->_mapOutDNs($cert, 'tbsCertificate/issuer/rdnSequence', $asn1);
$this->_mapOutDNs($cert, 'tbsCertificate/subject/rdnSequence', $asn1);
$cert = $asn1->encodeDER($cert, $this->Certificate);
switch ($format) {
case FILE_X509_FORMAT_DER:
case self::FORMAT_DER:
return $cert;
// case FILE_X509_FORMAT_PEM:
// case self::FORMAT_PEM:
default:
return "-----BEGIN CERTIFICATE-----\r\n" . chunk_split(base64_encode($cert), 64) . '-----END CERTIFICATE-----';
}
@ -1550,16 +1583,16 @@ class File_X509
* Map extension values from octet string to extension-specific internal
* format.
*
* @param Array ref $root
* @param String $path
* @param Object $asn1
* @param array ref $root
* @param string $path
* @param object $asn1
* @access private
*/
function _mapInExtensions(&$root, $path, $asn1)
{
$extensions = &$this->_subArray($root, $path);
$extensions = &$this->_subArrayUnchecked($root, $path);
if (is_array($extensions)) {
if ($extensions) {
for ($i = 0; $i < count($extensions); $i++) {
$id = $extensions[$i]['extnId'];
$value = &$extensions[$i]['extnValue'];
@ -1589,7 +1622,7 @@ class File_X509
}
}
}
} elseif ($map) {
} else {
$value = base64_encode($value);
}
}
@ -1600,9 +1633,9 @@ class File_X509
* Map extension values from extension-specific internal format to
* octet string.
*
* @param Array ref $root
* @param String $path
* @param Object $asn1
* @param array ref $root
* @param string $path
* @param object $asn1
* @access private
*/
function _mapOutExtensions(&$root, $path, $asn1)
@ -1612,6 +1645,10 @@ class File_X509
if (is_array($extensions)) {
$size = count($extensions);
for ($i = 0; $i < $size; $i++) {
if ($extensions[$i] instanceof Element) {
continue;
}
$id = $extensions[$i]['extnId'];
$value = &$extensions[$i]['extnValue'];
@ -1626,9 +1663,9 @@ class File_X509
$map = $this->_getMapping($subid);
$subvalue = &$value[$j]['policyQualifiers'][$k]['qualifier'];
if ($map !== false) {
// by default File_ASN1 will try to render qualifier as a FILE_ASN1_TYPE_IA5_STRING since it's
// actual type is FILE_ASN1_TYPE_ANY
$subvalue = new File_ASN1_Element($asn1->encodeDER($subvalue, $map));
// by default \phpseclib\File\ASN1 will try to render qualifier as a \phpseclib\File\ASN1::TYPE_IA5_STRING since it's
// actual type is \phpseclib\File\ASN1::TYPE_ANY
$subvalue = new Element($asn1->encodeDER($subvalue, $map));
}
}
}
@ -1636,8 +1673,8 @@ class File_X509
case 'id-ce-authorityKeyIdentifier': // use 00 as the serial number instead of an empty string
if (isset($value['authorityCertSerialNumber'])) {
if ($value['authorityCertSerialNumber']->toBytes() == '') {
$temp = chr((FILE_ASN1_CLASS_CONTEXT_SPECIFIC << 6) | 2) . "\1\0";
$value['authorityCertSerialNumber'] = new File_ASN1_Element($temp);
$temp = chr((ASN1::CLASS_CONTEXT_SPECIFIC << 6) | 2) . "\1\0";
$value['authorityCertSerialNumber'] = new Element($temp);
}
}
}
@ -1662,9 +1699,9 @@ class File_X509
* Map attribute values from ANY type to attribute-specific internal
* format.
*
* @param Array ref $root
* @param String $path
* @param Object $asn1
* @param array ref $root
* @param string $path
* @param object $asn1
* @access private
*/
function _mapInAttributes(&$root, $path, $asn1)
@ -1687,7 +1724,7 @@ class File_X509
if ($mapped !== false) {
$values[$j] = $mapped;
}
if ($id == 'pkcs-9-at-extensionRequest') {
if ($id == 'pkcs-9-at-extensionRequest' && $this->_isSubArrayValid($values, $j)) {
$this->_mapInExtensions($values, $j, $asn1);
}
} elseif ($map) {
@ -1703,9 +1740,9 @@ class File_X509
* Map attribute values from attribute-specific internal format to
* ANY type.
*
* @param Array ref $root
* @param String $path
* @param Object $asn1
* @param array ref $root
* @param string $path
* @param object $asn1
* @access private
*/
function _mapOutAttributes(&$root, $path, $asn1)
@ -1742,16 +1779,78 @@ class File_X509
}
}
/**
* Map DN values from ANY type to DN-specific internal
* format.
*
* @param array ref $root
* @param string $path
* @param object $asn1
* @access private
*/
function _mapInDNs(&$root, $path, $asn1)
{
$dns = &$this->_subArray($root, $path);
if (is_array($dns)) {
for ($i = 0; $i < count($dns); $i++) {
for ($j = 0; $j < count($dns[$i]); $j++) {
$type = $dns[$i][$j]['type'];
$value = &$dns[$i][$j]['value'];
if (is_object($value) && $value instanceof Element) {
$map = $this->_getMapping($type);
if (!is_bool($map)) {
$decoded = $asn1->decodeBER($value);
$value = $asn1->asn1map($decoded[0], $map);
}
}
}
}
}
}
/**
* Map DN values from DN-specific internal format to
* ANY type.
*
* @param array ref $root
* @param string $path
* @param object $asn1
* @access private
*/
function _mapOutDNs(&$root, $path, $asn1)
{
$dns = &$this->_subArray($root, $path);
if (is_array($dns)) {
$size = count($dns);
for ($i = 0; $i < $size; $i++) {
for ($j = 0; $j < count($dns[$i]); $j++) {
$type = $dns[$i][$j]['type'];
$value = &$dns[$i][$j]['value'];
if (is_object($value) && $value instanceof Element) {
continue;
}
$map = $this->_getMapping($type);
if (!is_bool($map)) {
$value = new Element($asn1->encodeDER($value, $map));
}
}
}
}
}
/**
* Associate an extension ID to an extension mapping
*
* @param String $extnId
* @param string $extnId
* @access private
* @return Mixed
* @return mixed
*/
function _getMapping($extnId)
{
if (!is_string($extnId)) { // eg. if it's a File_ASN1_Element object
if (!is_string($extnId)) { // eg. if it's a \phpseclib\File\ASN1\Element object
return true;
}
@ -1774,6 +1873,8 @@ class File_X509
return $this->AuthorityInfoAccessSyntax;
case 'id-ce-subjectAltName':
return $this->SubjectAltName;
case 'id-ce-subjectDirectoryAttributes':
return $this->SubjectDirectoryAttributes;
case 'id-ce-privateKeyUsagePeriod':
return $this->PrivateKeyUsagePeriod;
case 'id-ce-issuerAltName':
@ -1833,6 +1934,8 @@ class File_X509
return $this->CertificateIssuer;
case 'id-ce-holdInstructionCode':
return $this->HoldInstructionCode;
case 'id-at-postalAddress':
return $this->PostalAddress;
}
return false;
@ -1841,9 +1944,9 @@ class File_X509
/**
* Load an X.509 certificate as a certificate authority
*
* @param String $cert
* @param string $cert
* @access public
* @return Boolean
* @return bool
*/
function loadCA($cert)
{
@ -1908,9 +2011,9 @@ class File_X509
* component or component fragment. E.g., *.a.com matches foo.a.com but
* not bar.foo.a.com. f*.com matches foo.com but not bar.com.
*
* @param String $url
* @param string $url
* @access public
* @return Boolean
* @return bool
*/
function validateURL($url)
{
@ -1966,7 +2069,7 @@ class File_X509
*
* If $date isn't defined it is assumed to be the current date.
*
* @param Integer $date optional
* @param int $date optional
* @access public
*/
function validateDate($date = null)
@ -2005,9 +2108,9 @@ class File_X509
*
* The behavior of this function is inspired by {@link http://php.net/openssl-verify openssl_verify}.
*
* @param Boolean $caonly optional
* @param bool $caonly optional
* @access public
* @return Mixed
* @return mixed
*/
function validateSignature($caonly = true)
{
@ -2024,14 +2127,16 @@ class File_X509
switch (true) {
case isset($this->currentCert['tbsCertificate']):
// self-signed cert
if ($this->currentCert['tbsCertificate']['issuer'] === $this->currentCert['tbsCertificate']['subject']) {
$authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier');
switch (true) {
case !is_array($authorityKey):
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
$signingCert = $this->currentCert; // working cert
}
switch (true) {
case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertificate']['issuer'] === $this->currentCert['tbsCertificate']['subject']:
case defined('FILE_X509_IGNORE_TYPE') && $this->getIssuerDN(self::DN_STRING) === $this->getDN(self::DN_STRING):
$authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier');
switch (true) {
case !is_array($authorityKey):
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
$signingCert = $this->currentCert; // working cert
}
}
if (!empty($this->CAs)) {
@ -2039,15 +2144,17 @@ class File_X509
// even if the cert is a self-signed one we still want to see if it's a CA;
// if not, we'll conditionally return an error
$ca = $this->CAs[$i];
if ($this->currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']) {
$authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
switch (true) {
case !is_array($authorityKey):
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
$signingCert = $ca; // working cert
break 2;
}
switch (true) {
case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']:
case defined('FILE_X509_IGNORE_TYPE') && $this->getDN(self::DN_STRING, $this->currentCert['tbsCertificate']['issuer']) === $this->getDN(self::DN_STRING, $ca['tbsCertificate']['subject']):
$authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
switch (true) {
case !is_array($authorityKey):
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
$signingCert = $ca; // working cert
break 3;
}
}
}
if (count($this->CAs) == $i && $caonly) {
@ -2083,15 +2190,17 @@ class File_X509
if (!empty($this->CAs)) {
for ($i = 0; $i < count($this->CAs); $i++) {
$ca = $this->CAs[$i];
if ($this->currentCert['tbsCertList']['issuer'] === $ca['tbsCertificate']['subject']) {
$authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
switch (true) {
case !is_array($authorityKey):
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
$signingCert = $ca; // working cert
break 2;
}
switch (true) {
case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertList']['issuer'] === $ca['tbsCertificate']['subject']:
case defined('FILE_X509_IGNORE_TYPE') && $this->getDN(self::DN_STRING, $this->currentCert['tbsCertList']['issuer']) === $this->getDN(self::DN_STRING, $ca['tbsCertificate']['subject']):
$authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
switch (true) {
case !is_array($authorityKey):
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
$signingCert = $ca; // working cert
break 3;
}
}
}
}
@ -2115,22 +2224,19 @@ class File_X509
*
* Returns true if the signature is verified, false if it is not correct or null on error
*
* @param String $publicKeyAlgorithm
* @param String $publicKey
* @param String $signatureAlgorithm
* @param String $signature
* @param String $signatureSubject
* @param string $publicKeyAlgorithm
* @param string $publicKey
* @param string $signatureAlgorithm
* @param string $signature
* @param string $signatureSubject
* @access private
* @return Integer
* @return int
*/
function _validateSignature($publicKeyAlgorithm, $publicKey, $signatureAlgorithm, $signature, $signatureSubject)
{
switch ($publicKeyAlgorithm) {
case 'rsaEncryption':
if (!class_exists('Crypt_RSA')) {
include_once 'Crypt/RSA.php';
}
$rsa = new Crypt_RSA();
$rsa = new RSA();
$rsa->loadKey($publicKey);
switch ($signatureAlgorithm) {
@ -2142,7 +2248,7 @@ class File_X509
case 'sha384WithRSAEncryption':
case 'sha512WithRSAEncryption':
$rsa->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm));
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);
if (!@$rsa->verify($signatureSubject, $signature)) {
return false;
}
@ -2163,10 +2269,10 @@ class File_X509
*
* Reformats a public key to a format supported by phpseclib (if applicable)
*
* @param String $algorithm
* @param String $key
* @param string $algorithm
* @param string $key
* @access private
* @return String
* @return string
*/
function _reformatKey($algorithm, $key)
{
@ -2189,15 +2295,13 @@ class File_X509
*
* Takes in a base64 encoded "blob" and returns a human readable IP address
*
* @param String $ip
* @param string $ip
* @access private
* @return String
* @return string
*/
function _decodeIP($ip)
{
$ip = base64_decode($ip);
list(, $ip) = unpack('N', $ip);
return long2ip($ip);
return inet_ntop(base64_decode($ip));
}
/**
@ -2205,21 +2309,21 @@ class File_X509
*
* Takes a human readable IP address into a base64-encoded "blob"
*
* @param String $ip
* @param string $ip
* @access private
* @return String
* @return string
*/
function _encodeIP($ip)
{
return base64_encode(pack('N', ip2long($ip)));
return base64_encode(inet_pton($ip));
}
/**
* "Normalizes" a Distinguished Name property
*
* @param String $propName
* @param string $propName
* @access private
* @return Mixed
* @return mixed
*/
function _translateDNProp($propName)
{
@ -2298,6 +2402,9 @@ class File_X509
case 'uniqueidentifier':
case 'x500uniqueidentifier':
return 'id-at-uniqueIdentifier';
case 'postaladdress':
case 'id-at-postaladdress':
return 'id-at-postalAddress';
default:
return false;
}
@ -2306,11 +2413,11 @@ class File_X509
/**
* Set a Distinguished Name property
*
* @param String $propName
* @param Mixed $propValue
* @param String $type optional
* @param string $propName
* @param mixed $propValue
* @param string $type optional
* @access public
* @return Boolean
* @return bool
*/
function setDNProp($propName, $propValue, $type = 'utf8String')
{
@ -2340,7 +2447,7 @@ class File_X509
/**
* Remove Distinguished Name properties
*
* @param String $propName
* @param string $propName
* @access public
*/
function removeDNProp($propName)
@ -2367,10 +2474,10 @@ class File_X509
/**
* Get Distinguished Name properties
*
* @param String $propName
* @param Array $dn optional
* @param Boolean $withType optional
* @return Mixed
* @param string $propName
* @param array $dn optional
* @param bool $withType optional
* @return mixed
* @access public
*/
function getDNProp($propName, $dn = null, $withType = false)
@ -2387,25 +2494,38 @@ class File_X509
return false;
}
$asn1 = new ASN1();
$asn1->loadOIDs($this->oids);
$filters = array();
$filters['value'] = array('type' => ASN1::TYPE_UTF8_STRING);
$asn1->loadFilters($filters);
$this->_mapOutDNs($dn, 'rdnSequence', $asn1);
$dn = $dn['rdnSequence'];
$result = array();
$asn1 = new File_ASN1();
for ($i = 0; $i < count($dn); $i++) {
if ($dn[$i][0]['type'] == $propName) {
$v = $dn[$i][0]['value'];
if (!$withType && is_array($v)) {
foreach ($v as $type => $s) {
$type = array_search($type, $asn1->ANYmap, true);
if ($type !== false && isset($asn1->stringTypeSize[$type])) {
$s = $asn1->convert($s, $type);
if ($s !== false) {
$v = $s;
break;
if (!$withType) {
if (is_array($v)) {
foreach ($v as $type => $s) {
$type = array_search($type, $asn1->ANYmap, true);
if ($type !== false && isset($asn1->stringTypeSize[$type])) {
$s = $asn1->convert($s, $type);
if ($s !== false) {
$v = $s;
break;
}
}
}
}
if (is_array($v)) {
$v = array_pop($v); // Always strip data type.
if (is_array($v)) {
$v = array_pop($v); // Always strip data type.
}
} elseif (is_object($v) && $v instanceof Element) {
$map = $this->_getMapping($propName);
if (!is_bool($map)) {
$decoded = $asn1->decodeBER($v);
$v = $asn1->asn1map($decoded[0], $map);
}
}
}
$result[] = $v;
@ -2418,11 +2538,11 @@ class File_X509
/**
* Set a Distinguished Name
*
* @param Mixed $dn
* @param Boolean $merge optional
* @param String $type optional
* @param mixed $dn
* @param bool $merge optional
* @param string $type optional
* @access public
* @return Boolean
* @return bool
*/
function setDN($dn, $merge = false, $type = 'utf8String')
{
@ -2446,7 +2566,7 @@ class File_X509
}
// handles everything else
$results = preg_split('#((?:^|, *|/)(?:C=|O=|OU=|CN=|L=|ST=|SN=|postalCode=|streetAddress=|emailAddress=|serialNumber=|organizationalUnitName=|title=|description=|role=|x500UniqueIdentifier=))#', $dn, -1, PREG_SPLIT_DELIM_CAPTURE);
$results = preg_split('#((?:^|, *|/)(?:C=|O=|OU=|CN=|L=|ST=|SN=|postalCode=|streetAddress=|emailAddress=|serialNumber=|organizationalUnitName=|title=|description=|role=|x500UniqueIdentifier=|postalAddress=))#', $dn, -1, PREG_SPLIT_DELIM_CAPTURE);
for ($i = 1; $i < count($results); $i+=2) {
$prop = trim($results[$i], ', =/');
$value = $results[$i + 1];
@ -2461,55 +2581,41 @@ class File_X509
/**
* Get the Distinguished Name for a certificates subject
*
* @param Mixed $format optional
* @param Array $dn optional
* @param mixed $format optional
* @param array $dn optional
* @access public
* @return Boolean
* @return bool
*/
function getDN($format = FILE_X509_DN_ARRAY, $dn = null)
function getDN($format = self::DN_ARRAY, $dn = null)
{
if (!isset($dn)) {
$dn = isset($this->currentCert['tbsCertList']) ? $this->currentCert['tbsCertList']['issuer'] : $this->dn;
}
switch ((int) $format) {
case FILE_X509_DN_ARRAY:
case self::DN_ARRAY:
return $dn;
case FILE_X509_DN_ASN1:
$asn1 = new File_ASN1();
case self::DN_ASN1:
$asn1 = new ASN1();
$asn1->loadOIDs($this->oids);
$filters = array();
$filters['rdnSequence']['value'] = array('type' => FILE_ASN1_TYPE_UTF8_STRING);
$filters['rdnSequence']['value'] = array('type' => ASN1::TYPE_UTF8_STRING);
$asn1->loadFilters($filters);
$this->_mapOutDNs($dn, 'rdnSequence', $asn1);
return $asn1->encodeDER($dn, $this->Name);
case FILE_X509_DN_OPENSSL:
$dn = $this->getDN(FILE_X509_DN_STRING, $dn);
if ($dn === false) {
return false;
}
$attrs = preg_split('#((?:^|, *|/)[a-z][a-z0-9]*=)#i', $dn, -1, PREG_SPLIT_DELIM_CAPTURE);
$dn = array();
for ($i = 1; $i < count($attrs); $i += 2) {
$prop = trim($attrs[$i], ', =/');
$value = $attrs[$i + 1];
if (!isset($dn[$prop])) {
$dn[$prop] = $value;
} else {
$dn[$prop] = array_merge((array) $dn[$prop], array($value));
}
}
return $dn;
case FILE_X509_DN_CANON:
case self::DN_CANON:
// No SEQUENCE around RDNs and all string values normalized as
// trimmed lowercase UTF-8 with all spacing as one blank.
$asn1 = new File_ASN1();
// trimmed lowercase UTF-8 with all spacing as one blank.
// constructed RDNs will not be canonicalized
$asn1 = new ASN1();
$asn1->loadOIDs($this->oids);
$filters = array();
$filters['value'] = array('type' => FILE_ASN1_TYPE_UTF8_STRING);
$filters['value'] = array('type' => ASN1::TYPE_UTF8_STRING);
$asn1->loadFilters($filters);
$result = '';
$this->_mapOutDNs($dn, 'rdnSequence', $asn1);
foreach ($dn['rdnSequence'] as $rdn) {
foreach ($rdn as $i=>$attr) {
foreach ($rdn as $i => $attr) {
$attr = &$rdn[$i];
if (is_array($attr['value'])) {
foreach ($attr['value'] as $type => $v) {
@ -2528,12 +2634,9 @@ class File_X509
$result .= $asn1->encodeDER($rdn, $this->RelativeDistinguishedName);
}
return $result;
case FILE_X509_DN_HASH:
$dn = $this->getDN(FILE_X509_DN_CANON, $dn);
if (!class_exists('Crypt_Hash')) {
include_once 'Crypt/Hash.php';
}
$hash = new Crypt_Hash('sha1');
case self::DN_HASH:
$dn = $this->getDN(self::DN_CANON, $dn);
$hash = new Hash('sha1');
$hash = $hash->hash($dn);
extract(unpack('Vhash', $hash));
return strtolower(bin2hex(pack('N', $hash)));
@ -2542,7 +2645,15 @@ class File_X509
// Default is to return a string.
$start = true;
$output = '';
$asn1 = new File_ASN1();
$result = array();
$asn1 = new ASN1();
$asn1->loadOIDs($this->oids);
$filters = array();
$filters['rdnSequence']['value'] = array('type' => ASN1::TYPE_UTF8_STRING);
$asn1->loadFilters($filters);
$this->_mapOutDNs($dn, 'rdnSequence', $asn1);
foreach ($dn['rdnSequence'] as $field) {
$prop = $field[0]['type'];
$value = $field[0]['value'];
@ -2550,33 +2661,37 @@ class File_X509
$delim = ', ';
switch ($prop) {
case 'id-at-countryName':
$desc = 'C=';
$desc = 'C';
break;
case 'id-at-stateOrProvinceName':
$desc = 'ST=';
$desc = 'ST';
break;
case 'id-at-organizationName':
$desc = 'O=';
$desc = 'O';
break;
case 'id-at-organizationalUnitName':
$desc = 'OU=';
$desc = 'OU';
break;
case 'id-at-commonName':
$desc = 'CN=';
$desc = 'CN';
break;
case 'id-at-localityName':
$desc = 'L=';
$desc = 'L';
break;
case 'id-at-surname':
$desc = 'SN=';
$desc = 'SN';
break;
case 'id-at-uniqueIdentifier':
$delim = '/';
$desc = 'x500UniqueIdentifier=';
$desc = 'x500UniqueIdentifier';
break;
case 'id-at-postalAddress':
$delim = '/';
$desc = 'postalAddress';
break;
default:
$delim = '/';
$desc = preg_replace('#.+-([^-]+)$#', '$1', $prop) . '=';
$desc = preg_replace('#.+-([^-]+)$#', '$1', $prop);
}
if (!$start) {
@ -2596,22 +2711,28 @@ class File_X509
if (is_array($value)) {
$value = array_pop($value); // Always strip data type.
}
} elseif (is_object($value) && $value instanceof Element) {
$callback = create_function('$x', 'return "\x" . bin2hex($x[0]);');
$value = strtoupper(preg_replace_callback('#[^\x20-\x7E]#', $callback, $value->element));
}
$output.= $desc . $value;
$output.= $desc . '=' . $value;
$result[$desc] = isset($result[$desc]) ?
array_merge((array) $dn[$prop], array($value)) :
$value;
$start = false;
}
return $output;
return $format == self::DN_OPENSSL ? $result : $output;
}
/**
* Get the Distinguished Name for a certificate/crl issuer
*
* @param Integer $format optional
* @param int $format optional
* @access public
* @return Mixed
* @return mixed
*/
function getIssuerDN($format = FILE_X509_DN_ARRAY)
function getIssuerDN($format = self::DN_ARRAY)
{
switch (true) {
case !isset($this->currentCert) || !is_array($this->currentCert):
@ -2629,11 +2750,11 @@ class File_X509
* Get the Distinguished Name for a certificate/csr subject
* Alias of getDN()
*
* @param Integer $format optional
* @param int $format optional
* @access public
* @return Mixed
* @return mixed
*/
function getSubjectDN($format = FILE_X509_DN_ARRAY)
function getSubjectDN($format = self::DN_ARRAY)
{
switch (true) {
case !empty($this->dn):
@ -2652,10 +2773,10 @@ class File_X509
/**
* Get an individual Distinguished Name property for a certificate/crl issuer
*
* @param String $propName
* @param Boolean $withType optional
* @param string $propName
* @param bool $withType optional
* @access public
* @return Mixed
* @return mixed
*/
function getIssuerDNProp($propName, $withType = false)
{
@ -2674,10 +2795,10 @@ class File_X509
/**
* Get an individual Distinguished Name property for a certificate/csr subject
*
* @param String $propName
* @param Boolean $withType optional
* @param string $propName
* @param bool $withType optional
* @access public
* @return Mixed
* @return mixed
*/
function getSubjectDNProp($propName, $withType = false)
{
@ -2699,7 +2820,7 @@ class File_X509
* Get the certificate chain for the current cert
*
* @access public
* @return Mixed
* @return mixed
*/
function getChain()
{
@ -2733,8 +2854,8 @@ class File_X509
break;
}
}
foreach ($chain as $key=>$value) {
$chain[$key] = new File_X509();
foreach ($chain as $key => $value) {
$chain[$key] = new X509();
$chain[$key]->loadX509($value);
}
return $chain;
@ -2743,11 +2864,11 @@ class File_X509
/**
* Set public key
*
* Key needs to be a Crypt_RSA object
* Key needs to be a \phpseclib\Crypt\RSA object
*
* @param Object $key
* @param object $key
* @access public
* @return Boolean
* @return bool
*/
function setPublicKey($key)
{
@ -2758,9 +2879,9 @@ class File_X509
/**
* Set private key
*
* Key needs to be a Crypt_RSA object
* Key needs to be a \phpseclib\Crypt\RSA object
*
* @param Object $key
* @param object $key
* @access public
*/
function setPrivateKey($key)
@ -2773,7 +2894,7 @@ class File_X509
*
* Used for SPKAC CSR's
*
* @param String $challenge
* @param string $challenge
* @access public
*/
function setChallenge($challenge)
@ -2784,10 +2905,10 @@ class File_X509
/**
* Gets the public key
*
* Returns a Crypt_RSA object or a false.
* Returns a \phpseclib\Crypt\RSA object or a false.
*
* @access public
* @return Mixed
* @return mixed
*/
function getPublicKey()
{
@ -2811,10 +2932,7 @@ class File_X509
switch ($keyinfo['algorithm']['algorithm']) {
case 'rsaEncryption':
if (!class_exists('Crypt_RSA')) {
include_once 'Crypt/RSA.php';
}
$publicKey = new Crypt_RSA();
$publicKey = new RSA();
$publicKey->loadKey($key);
$publicKey->setPublicKey();
break;
@ -2828,11 +2946,11 @@ class File_X509
/**
* Load a Certificate Signing Request
*
* @param String $csr
* @param string $csr
* @access public
* @return Mixed
* @return mixed
*/
function loadCSR($csr)
function loadCSR($csr, $mode = self::FORMAT_AUTO_DETECT)
{
if (is_array($csr) && isset($csr['certificationRequestInfo'])) {
unset($this->currentCert);
@ -2849,9 +2967,15 @@ class File_X509
// see http://tools.ietf.org/html/rfc2986
$asn1 = new File_ASN1();
$asn1 = new ASN1();
$csr = $this->_extractBER($csr);
if ($mode != self::FORMAT_DER) {
$newcsr = $this->_extractBER($csr);
if ($mode == self::FORMAT_PEM && $csr == $newcsr) {
return false;
}
$csr = $newcsr;
}
$orig = $csr;
if ($csr === false) {
@ -2873,8 +2997,10 @@ class File_X509
return false;
}
$this->dn = $csr['certificationRequestInfo']['subject'];
$this->_mapInAttributes($csr, 'certificationRequestInfo/attributes', $asn1);
$this->_mapInDNs($csr, 'certificationRequestInfo/subject/rdnSequence', $asn1);
$this->dn = $csr['certificationRequestInfo']['subject'];
$this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
@ -2884,10 +3010,7 @@ class File_X509
switch ($algorithm) {
case 'rsaEncryption':
if (!class_exists('Crypt_RSA')) {
include_once 'Crypt/RSA.php';
}
$this->publicKey = new Crypt_RSA();
$this->publicKey = new RSA();
$this->publicKey->loadKey($key);
$this->publicKey->setPublicKey();
break;
@ -2904,12 +3027,12 @@ class File_X509
/**
* Save CSR request
*
* @param Array $csr
* @param Integer $format optional
* @param array $csr
* @param int $format optional
* @access public
* @return String
* @return string
*/
function saveCSR($csr, $format = FILE_X509_FORMAT_PEM)
function saveCSR($csr, $format = self::FORMAT_PEM)
{
if (!is_array($csr) || !isset($csr['certificationRequestInfo'])) {
return false;
@ -2917,33 +3040,37 @@ class File_X509
switch (true) {
case !($algorithm = $this->_subArray($csr, 'certificationRequestInfo/subjectPKInfo/algorithm/algorithm')):
case is_object($csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']);
case is_object($csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']):
break;
default:
switch ($algorithm) {
case 'rsaEncryption':
$csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']
= base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'])));
$csr['certificationRequestInfo']['subjectPKInfo']['algorithm']['parameters'] = null;
$csr['signatureAlgorithm']['parameters'] = null;
$csr['certificationRequestInfo']['signature']['parameters'] = null;
}
}
$asn1 = new File_ASN1();
$asn1 = new ASN1();
$asn1->loadOIDs($this->oids);
$filters = array();
$filters['certificationRequestInfo']['subject']['rdnSequence']['value']
= array('type' => FILE_ASN1_TYPE_UTF8_STRING);
= array('type' => ASN1::TYPE_UTF8_STRING);
$asn1->loadFilters($filters);
$this->_mapOutDNs($csr, 'certificationRequestInfo/subject/rdnSequence', $asn1);
$this->_mapOutAttributes($csr, 'certificationRequestInfo/attributes', $asn1);
$csr = $asn1->encodeDER($csr, $this->CertificationRequest);
switch ($format) {
case FILE_X509_FORMAT_DER:
case self::FORMAT_DER:
return $csr;
// case FILE_X509_FORMAT_PEM:
// case self::FORMAT_PEM:
default:
return "-----BEGIN CERTIFICATE REQUEST-----\r\n" . chunk_split(base64_encode($csr), 64) . '-----END CERTIFICATE REQUEST-----';
}
@ -2956,9 +3083,9 @@ class File_X509
*
* https://developer.mozilla.org/en-US/docs/HTML/Element/keygen
*
* @param String $csr
* @param string $csr
* @access public
* @return Mixed
* @return mixed
*/
function loadSPKAC($spkac)
{
@ -2972,9 +3099,9 @@ class File_X509
// see http://www.w3.org/html/wg/drafts/html/master/forms.html#signedpublickeyandchallenge
$asn1 = new File_ASN1();
$asn1 = new ASN1();
// OpenSSL produces SPKAC's that are preceeded by the string SPKAC=
// OpenSSL produces SPKAC's that are preceded by the string SPKAC=
$temp = preg_replace('#(?:SPKAC=)|[ \r\n\\\]#', '', $spkac);
$temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
if ($temp != false) {
@ -3010,10 +3137,7 @@ class File_X509
switch ($algorithm) {
case 'rsaEncryption':
if (!class_exists('Crypt_RSA')) {
include_once 'Crypt/RSA.php';
}
$this->publicKey = new Crypt_RSA();
$this->publicKey = new RSA();
$this->publicKey->loadKey($key);
$this->publicKey->setPublicKey();
break;
@ -3030,12 +3154,12 @@ class File_X509
/**
* Save a SPKAC CSR request
*
* @param Array $csr
* @param Integer $format optional
* @param array $csr
* @param int $format optional
* @access public
* @return String
* @return string
*/
function saveSPKAC($spkac, $format = FILE_X509_FORMAT_PEM)
function saveSPKAC($spkac, $format = self::FORMAT_PEM)
{
if (!is_array($spkac) || !isset($spkac['publicKeyAndChallenge'])) {
return false;
@ -3044,7 +3168,7 @@ class File_X509
$algorithm = $this->_subArray($spkac, 'publicKeyAndChallenge/spki/algorithm/algorithm');
switch (true) {
case !$algorithm:
case is_object($spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']);
case is_object($spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']):
break;
default:
switch ($algorithm) {
@ -3054,17 +3178,17 @@ class File_X509
}
}
$asn1 = new File_ASN1();
$asn1 = new ASN1();
$asn1->loadOIDs($this->oids);
$spkac = $asn1->encodeDER($spkac, $this->SignedPublicKeyAndChallenge);
switch ($format) {
case FILE_X509_FORMAT_DER:
case self::FORMAT_DER:
return $spkac;
// case FILE_X509_FORMAT_PEM:
// case self::FORMAT_PEM:
default:
// OpenSSL's implementation of SPKAC requires the SPKAC be preceeded by SPKAC= and since there are pretty much
// OpenSSL's implementation of SPKAC requires the SPKAC be preceded by SPKAC= and since there are pretty much
// no other SPKAC decoders phpseclib will use that same format
return 'SPKAC=' . base64_encode($spkac);
}
@ -3073,11 +3197,11 @@ class File_X509
/**
* Load a Certificate Revocation List
*
* @param String $crl
* @param string $crl
* @access public
* @return Mixed
* @return mixed
*/
function loadCRL($crl)
function loadCRL($crl, $mode = self::FORMAT_AUTO_DETECT)
{
if (is_array($crl) && isset($crl['tbsCertList'])) {
$this->currentCert = $crl;
@ -3085,9 +3209,15 @@ class File_X509
return $crl;
}
$asn1 = new File_ASN1();
$asn1 = new ASN1();
$crl = $this->_extractBER($crl);
if ($mode != self::FORMAT_DER) {
$newcrl = $this->_extractBER($crl);
if ($mode == self::FORMAT_PEM && $crl == $newcrl) {
return false;
}
$crl = $newcrl;
}
$orig = $crl;
if ($crl === false) {
@ -3111,11 +3241,19 @@ class File_X509
$this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
$this->_mapInExtensions($crl, 'tbsCertList/crlExtensions', $asn1);
$rclist = &$this->_subArray($crl, 'tbsCertList/revokedCertificates');
if (is_array($rclist)) {
foreach ($rclist as $i => $extension) {
$this->_mapInExtensions($rclist, "$i/crlEntryExtensions", $asn1);
$this->_mapInDNs($crl, 'tbsCertList/issuer/rdnSequence', $asn1);
if ($this->_isSubArrayValid($crl, 'tbsCertList/crlExtensions')) {
$this->_mapInExtensions($crl, 'tbsCertList/crlExtensions', $asn1);
}
if ($this->_isSubArrayValid($crl, 'tbsCertList/revokedCertificates')) {
$rclist_ref = &$this->_subArrayUnchecked($crl, 'tbsCertList/revokedCertificates');
if ($rclist_ref) {
$rclist = $crl['tbsCertList']['revokedCertificates'];
foreach ($rclist as $i => $extension) {
if ($this->_isSubArrayValid($rclist, "$i/crlEntryExtensions", $asn1)) {
$this->_mapInExtensions($rclist_ref, "$i/crlEntryExtensions", $asn1);
}
}
}
}
@ -3128,41 +3266,42 @@ class File_X509
/**
* Save Certificate Revocation List.
*
* @param Array $crl
* @param Integer $format optional
* @param array $crl
* @param int $format optional
* @access public
* @return String
* @return string
*/
function saveCRL($crl, $format = FILE_X509_FORMAT_PEM)
function saveCRL($crl, $format = self::FORMAT_PEM)
{
if (!is_array($crl) || !isset($crl['tbsCertList'])) {
return false;
}
$asn1 = new File_ASN1();
$asn1 = new ASN1();
$asn1->loadOIDs($this->oids);
$filters = array();
$filters['tbsCertList']['issuer']['rdnSequence']['value']
= array('type' => FILE_ASN1_TYPE_UTF8_STRING);
= array('type' => ASN1::TYPE_UTF8_STRING);
$filters['tbsCertList']['signature']['parameters']
= array('type' => FILE_ASN1_TYPE_UTF8_STRING);
= array('type' => ASN1::TYPE_UTF8_STRING);
$filters['signatureAlgorithm']['parameters']
= array('type' => FILE_ASN1_TYPE_UTF8_STRING);
= array('type' => ASN1::TYPE_UTF8_STRING);
if (empty($crl['tbsCertList']['signature']['parameters'])) {
$filters['tbsCertList']['signature']['parameters']
= array('type' => FILE_ASN1_TYPE_NULL);
= array('type' => ASN1::TYPE_NULL);
}
if (empty($crl['signatureAlgorithm']['parameters'])) {
$filters['signatureAlgorithm']['parameters']
= array('type' => FILE_ASN1_TYPE_NULL);
= array('type' => ASN1::TYPE_NULL);
}
$asn1->loadFilters($filters);
$this->_mapOutDNs($crl, 'tbsCertList/issuer/rdnSequence', $asn1);
$this->_mapOutExtensions($crl, 'tbsCertList/crlExtensions', $asn1);
$rclist = &$this->_subArray($crl, 'tbsCertList/revokedCertificates');
if (is_array($rclist)) {
@ -3174,9 +3313,9 @@ class File_X509
$crl = $asn1->encodeDER($crl, $this->CertificateList);
switch ($format) {
case FILE_X509_FORMAT_DER:
case self::FORMAT_DER:
return $crl;
// case FILE_X509_FORMAT_PEM:
// case self::FORMAT_PEM:
default:
return "-----BEGIN X509 CRL-----\r\n" . chunk_split(base64_encode($crl), 64) . '-----END X509 CRL-----';
}
@ -3190,17 +3329,17 @@ class File_X509
* - 5.1.2.6 Revoked Certificates
* by choosing utcTime iff year of date given is before 2050 and generalTime else.
*
* @param String $date in format date('D, d M Y H:i:s O')
* @param string $date in format date('D, d M Y H:i:s O')
* @access private
* @return Array
* @return array
*/
function _timeField($date)
{
$year = @gmdate("Y", @strtotime($date)); // the same way ASN1.php parses this
if ($year < 2050) {
return array('utcTime' => $date);
return array('utcTime' => $date);
} else {
return array('generalTime' => $date);
return array('generalTime' => $date);
}
}
@ -3211,11 +3350,11 @@ class File_X509
* $subject can be either an existing X.509 cert (if you want to resign it),
* a CSR or something with the DN and public key explicitly set.
*
* @param File_X509 $issuer
* @param File_X509 $subject
* @param String $signatureAlgorithm optional
* @param \phpseclib\File\X509 $issuer
* @param \phpseclib\File\X509 $subject
* @param string $signatureAlgorithm optional
* @access public
* @return Mixed
* @return mixed
*/
function sign($issuer, $subject, $signatureAlgorithm = 'sha1WithRSAEncryption')
{
@ -3254,7 +3393,7 @@ class File_X509
if (isset($subject->domains)) {
$this->removeExtension('id-ce-subjectAltName');
}
} else if (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertList'])) {
} elseif (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertList'])) {
return false;
} else {
if (!isset($subject->publicKey)) {
@ -3263,7 +3402,16 @@ class File_X509
$startDate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O');
$endDate = !empty($this->endDate) ? $this->endDate : @date('D, d M Y H:i:s O', strtotime('+1 year'));
$serialNumber = !empty($this->serialNumber) ? $this->serialNumber : new Math_BigInteger();
/* "The serial number MUST be a positive integer"
"Conforming CAs MUST NOT use serialNumber values longer than 20 octets."
-- https://tools.ietf.org/html/rfc5280#section-4.1.2.2
for the integer to be positive the leading bit needs to be 0 hence the
application of a bitmap
*/
$serialNumber = !empty($this->serialNumber) ?
$this->serialNumber :
new BigInteger(Random::string(20) & ("\x7F" . str_repeat("\xFF", 19)), 256);
$this->currentCert = array(
'tbsCertificate' =>
@ -3279,8 +3427,8 @@ class File_X509
'subject' => $subject->dn,
'subjectPublicKeyInfo' => $subjectPublicKey
),
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
'signature' => false // this is going to be overwritten later
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
'signature' => false // this is going to be overwritten later
);
// Copy extensions from CSR.
@ -3301,8 +3449,7 @@ class File_X509
// )
//),
'keyIdentifier' => $issuer->currentKeyIdentifier
)
);
));
//$extensions = &$this->currentCert['tbsCertificate']['extensions'];
//if (isset($issuer->serialNumber)) {
// $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber;
@ -3317,7 +3464,7 @@ class File_X509
$altName = array();
if (isset($subject->domains) && count($subject->domains) > 1) {
$altName = array_map(array('File_X509', '_dnsName'), $subject->domains);
$altName = array_map(array('X509', '_dnsName'), $subject->domains);
}
if (isset($subject->ipAddresses) && count($subject->ipAddresses)) {
@ -3345,7 +3492,8 @@ class File_X509
$keyUsage = array();
}
$this->setExtension('id-ce-keyUsage',
$this->setExtension(
'id-ce-keyUsage',
array_values(array_unique(array_merge($keyUsage, array('cRLSign', 'keyCertSign'))))
);
@ -3354,8 +3502,11 @@ class File_X509
$basicConstraints = array();
}
$this->setExtension('id-ce-basicConstraints',
array_unique(array_merge(array('cA' => true), $basicConstraints)), true);
$this->setExtension(
'id-ce-basicConstraints',
array_unique(array_merge(array('cA' => true), $basicConstraints)),
true
);
if (!isset($subject->currentKeyIdentifier)) {
$this->setExtension('id-ce-subjectKeyIdentifier', base64_encode($this->computeKeyIdentifier($this->currentCert)), false, false);
@ -3363,7 +3514,7 @@ class File_X509
}
// resync $this->signatureSubject
// save $tbsCertificate in case there are any File_ASN1_Element objects in it
// save $tbsCertificate in case there are any \phpseclib\File\ASN1\Element objects in it
$tbsCertificate = $this->currentCert['tbsCertificate'];
$this->loadX509($this->saveX509($this->currentCert));
@ -3380,7 +3531,7 @@ class File_X509
* Sign a CSR
*
* @access public
* @return Mixed
* @return mixed
*/
function signCSR($signatureAlgorithm = 'sha1WithRSAEncryption')
{
@ -3415,13 +3566,13 @@ class File_X509
'subject' => $this->dn,
'subjectPKInfo' => $publicKey
),
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
'signature' => false // this is going to be overwritten later
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
'signature' => false // this is going to be overwritten later
);
}
// resync $this->signatureSubject
// save $certificationRequestInfo in case there are any File_ASN1_Element objects in it
// save $certificationRequestInfo in case there are any \phpseclib\File\ASN1\Element objects in it
$certificationRequestInfo = $this->currentCert['certificationRequestInfo'];
$this->loadCSR($this->saveCSR($this->currentCert));
@ -3438,7 +3589,7 @@ class File_X509
* Sign a SPKAC
*
* @access public
* @return Mixed
* @return mixed
*/
function signSPKAC($signatureAlgorithm = 'sha1WithRSAEncryption')
{
@ -3477,16 +3628,16 @@ class File_X509
// "A challenge string that is submitted along with the public key. Defaults to an empty string if not specified."
// both Firefox and OpenSSL ("openssl spkac -key private.key") behave this way
// we could alternatively do this instead if we ignored the specs:
// crypt_random_string(8) & str_repeat("\x7F", 8)
// Random::string(8) & str_repeat("\x7F", 8)
'challenge' => !empty($this->challenge) ? $this->challenge : ''
),
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
'signature' => false // this is going to be overwritten later
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
'signature' => false // this is going to be overwritten later
);
}
// resync $this->signatureSubject
// save $publicKeyAndChallenge in case there are any File_ASN1_Element objects in it
// save $publicKeyAndChallenge in case there are any \phpseclib\File\ASN1\Element objects in it
$publicKeyAndChallenge = $this->currentCert['publicKeyAndChallenge'];
$this->loadSPKAC($this->saveSPKAC($this->currentCert));
@ -3504,11 +3655,11 @@ class File_X509
*
* $issuer's private key needs to be loaded.
*
* @param File_X509 $issuer
* @param File_X509 $crl
* @param String $signatureAlgorithm optional
* @param \phpseclib\File\X509 $issuer
* @param \phpseclib\File\X509 $crl
* @param string $signatureAlgorithm optional
* @access public
* @return Mixed
* @return mixed
*/
function signCRL($issuer, $crl, $signatureAlgorithm = 'sha1WithRSAEncryption')
{
@ -3533,8 +3684,8 @@ class File_X509
'issuer' => false, // this is going to be overwritten later
'thisUpdate' => $this->_timeField($thisUpdate) // $this->setStartDate()
),
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
'signature' => false // this is going to be overwritten later
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
'signature' => false // this is going to be overwritten later
);
}
@ -3552,7 +3703,12 @@ class File_X509
$crlNumber = $this->serialNumber;
} else {
$crlNumber = $this->getExtension('id-ce-cRLNumber');
$crlNumber = $crlNumber !== false ? $crlNumber->add(new Math_BigInteger(1)) : null;
// "The CRL number is a non-critical CRL extension that conveys a
// monotonically increasing sequence number for a given CRL scope and
// CRL issuer. This extension allows users to easily determine when a
// particular CRL supersedes another CRL."
// -- https://tools.ietf.org/html/rfc5280#section-5.2.3
$crlNumber = $crlNumber !== false ? $crlNumber->add(new BigInteger(1)) : null;
}
$this->removeExtension('id-ce-authorityKeyIdentifier');
@ -3590,8 +3746,7 @@ class File_X509
// )
//),
'keyIdentifier' => $issuer->currentKeyIdentifier
)
);
));
//$extensions = &$tbsCertList['crlExtensions'];
//if (isset($issuer->serialNumber)) {
// $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber;
@ -3613,7 +3768,7 @@ class File_X509
unset($tbsCertList);
// resync $this->signatureSubject
// save $tbsCertList in case there are any File_ASN1_Element objects in it
// save $tbsCertList in case there are any \phpseclib\File\ASN1\Element objects in it
$tbsCertList = $this->currentCert['tbsCertList'];
$this->loadCRL($this->saveCRL($this->currentCert));
@ -3629,39 +3784,38 @@ class File_X509
/**
* X.509 certificate signing helper function.
*
* @param Object $key
* @param File_X509 $subject
* @param String $signatureAlgorithm
* @param object $key
* @param \phpseclib\File\X509 $subject
* @param string $signatureAlgorithm
* @access public
* @return Mixed
* @return mixed
*/
function _sign($key, $signatureAlgorithm)
{
switch (strtolower(get_class($key))) {
case 'crypt_rsa':
switch ($signatureAlgorithm) {
case 'md2WithRSAEncryption':
case 'md5WithRSAEncryption':
case 'sha1WithRSAEncryption':
case 'sha224WithRSAEncryption':
case 'sha256WithRSAEncryption':
case 'sha384WithRSAEncryption':
case 'sha512WithRSAEncryption':
$key->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm));
$key->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
if ($key instanceof RSA) {
switch ($signatureAlgorithm) {
case 'md2WithRSAEncryption':
case 'md5WithRSAEncryption':
case 'sha1WithRSAEncryption':
case 'sha224WithRSAEncryption':
case 'sha256WithRSAEncryption':
case 'sha384WithRSAEncryption':
case 'sha512WithRSAEncryption':
$key->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm));
$key->setSignatureMode(RSA::SIGNATURE_PKCS1);
$this->currentCert['signature'] = base64_encode("\0" . $key->sign($this->signatureSubject));
return $this->currentCert;
}
default:
return false;
$this->currentCert['signature'] = base64_encode("\0" . $key->sign($this->signatureSubject));
return $this->currentCert;
}
}
return false;
}
/**
* Set certificate start date
*
* @param String $date
* @param string $date
* @access public
*/
function setStartDate($date)
@ -3672,7 +3826,7 @@ class File_X509
/**
* Set certificate end date
*
* @param String $date
* @param string $date
* @access public
*/
function setEndDate($date)
@ -3686,9 +3840,9 @@ class File_X509
*/
if (strtolower($date) == 'lifetime') {
$temp = '99991231235959Z';
$asn1 = new File_ASN1();
$temp = chr(FILE_ASN1_TYPE_GENERALIZED_TIME) . $asn1->_encodeLength(strlen($temp)) . $temp;
$this->endDate = new File_ASN1_Element($temp);
$asn1 = new ASN1();
$temp = chr(ASN1::TYPE_GENERALIZED_TIME) . $asn1->_encodeLength(strlen($temp)) . $temp;
$this->endDate = new Element($temp);
} else {
$this->endDate = @date('D, d M Y H:i:s O', @strtotime($date));
}
@ -3697,13 +3851,13 @@ class File_X509
/**
* Set Serial Number
*
* @param String $serial
* @param string $serial
* @param $base optional
* @access public
*/
function setSerialNumber($serial, $base = -256)
{
$this->serialNumber = new Math_BigInteger($serial, $base);
$this->serialNumber = new BigInteger($serial, $base);
}
/**
@ -3716,14 +3870,82 @@ class File_X509
$this->caFlag = true;
}
/**
* Check for validity of subarray
*
* This is intended for use in conjunction with _subArrayUnchecked(),
* implementing the checks included in _subArray() but without copying
* a potentially large array by passing its reference by-value to is_array().
*
* @param array $root
* @param string $path
* @return boolean
* @access private
*/
function _isSubArrayValid($root, $path)
{
if (!is_array($root)) {
return false;
}
foreach (explode('/', $path) as $i) {
if (!is_array($root)) {
return false;
}
if (!isset($root[$i])) {
return true;
}
$root = $root[$i];
}
return true;
}
/**
* Get a reference to a subarray
*
* This variant of _subArray() does no is_array() checking,
* so $root should be checked with _isSubArrayValid() first.
*
* This is here for performance reasons:
* Passing a reference (i.e. $root) by-value (i.e. to is_array())
* creates a copy. If $root is an especially large array, this is expensive.
*
* @param array $root
* @param string $path absolute path with / as component separator
* @param bool $create optional
* @access private
* @return array|false
*/
function &_subArrayUnchecked(&$root, $path, $create = false)
{
$false = false;
foreach (explode('/', $path) as $i) {
if (!isset($root[$i])) {
if (!$create) {
return $false;
}
$root[$i] = array();
}
$root = &$root[$i];
}
return $root;
}
/**
* Get a reference to a subarray
*
* @param array $root
* @param String $path absolute path with / as component separator
* @param Boolean $create optional
* @param string $path absolute path with / as component separator
* @param bool $create optional
* @access private
* @return array item ref or false
* @return array|false
*/
function &_subArray(&$root, $path, $create = false)
{
@ -3756,10 +3978,10 @@ class File_X509
* Get a reference to an extension subarray
*
* @param array $root
* @param String $path optional absolute path with / as component separator
* @param Boolean $create optional
* @param string $path optional absolute path with / as component separator
* @param bool $create optional
* @access private
* @return array ref or false
* @return array|false
*/
function &_extensions(&$root, $path = null, $create = false)
{
@ -3810,10 +4032,10 @@ class File_X509
/**
* Remove an Extension
*
* @param String $id
* @param String $path optional
* @param string $id
* @param string $path optional
* @access private
* @return Boolean
* @return bool
*/
function _removeExtension($id, $path = null)
{
@ -3840,11 +4062,11 @@ class File_X509
*
* Returns the extension if it exists and false if not
*
* @param String $id
* @param Array $cert optional
* @param String $path optional
* @param string $id
* @param array $cert optional
* @param string $path optional
* @access private
* @return Mixed
* @return mixed
*/
function _getExtension($id, $cert = null, $path = null)
{
@ -3867,9 +4089,9 @@ class File_X509
* Returns a list of all extensions in use
*
* @param array $cert optional
* @param String $path optional
* @param string $path optional
* @access private
* @return Array
* @return array
*/
function _getExtensions($cert = null, $path = null)
{
@ -3888,13 +4110,13 @@ class File_X509
/**
* Set an Extension
*
* @param String $id
* @param Mixed $value
* @param Boolean $critical optional
* @param Boolean $replace optional
* @param String $path optional
* @param string $id
* @param mixed $value
* @param bool $critical optional
* @param bool $replace optional
* @param string $path optional
* @access private
* @return Boolean
* @return bool
*/
function _setExtension($id, $value, $critical = false, $replace = true, $path = null)
{
@ -3924,9 +4146,9 @@ class File_X509
/**
* Remove a certificate, CSR or CRL Extension
*
* @param String $id
* @param string $id
* @access public
* @return Boolean
* @return bool
*/
function removeExtension($id)
{
@ -3938,10 +4160,10 @@ class File_X509
*
* Returns the extension if it exists and false if not
*
* @param String $id
* @param Array $cert optional
* @param string $id
* @param array $cert optional
* @access public
* @return Mixed
* @return mixed
*/
function getExtension($id, $cert = null)
{
@ -3953,7 +4175,7 @@ class File_X509
*
* @param array $cert optional
* @access public
* @return Array
* @return array
*/
function getExtensions($cert = null)
{
@ -3963,12 +4185,12 @@ class File_X509
/**
* Set a certificate, CSR or CRL Extension
*
* @param String $id
* @param Mixed $value
* @param Boolean $critical optional
* @param Boolean $replace optional
* @param string $id
* @param mixed $value
* @param bool $critical optional
* @param bool $replace optional
* @access public
* @return Boolean
* @return bool
*/
function setExtension($id, $value, $critical = false, $replace = true)
{
@ -3978,12 +4200,12 @@ class File_X509
/**
* Remove a CSR attribute.
*
* @param String $id
* @param Integer $disposition optional
* @param string $id
* @param int $disposition optional
* @access public
* @return Boolean
* @return bool
*/
function removeAttribute($id, $disposition = FILE_X509_ATTR_ALL)
function removeAttribute($id, $disposition = self::ATTR_ALL)
{
$attributes = &$this->_subArray($this->currentCert, 'certificationRequestInfo/attributes');
@ -3996,13 +4218,13 @@ class File_X509
if ($attribute['type'] == $id) {
$n = count($attribute['value']);
switch (true) {
case $disposition == FILE_X509_ATTR_APPEND:
case $disposition == FILE_X509_ATTR_REPLACE:
case $disposition == self::ATTR_APPEND:
case $disposition == self::ATTR_REPLACE:
return false;
case $disposition >= $n:
$disposition -= $n;
break;
case $disposition == FILE_X509_ATTR_ALL:
case $disposition == self::ATTR_ALL:
case $n == 1:
unset($attributes[$key]);
$result = true;
@ -4013,7 +4235,7 @@ class File_X509
$result = true;
break;
}
if ($result && $disposition != FILE_X509_ATTR_ALL) {
if ($result && $disposition != self::ATTR_ALL) {
break;
}
}
@ -4028,13 +4250,13 @@ class File_X509
*
* Returns the attribute if it exists and false if not
*
* @param String $id
* @param Integer $disposition optional
* @param Array $csr optional
* @param string $id
* @param int $disposition optional
* @param array $csr optional
* @access public
* @return Mixed
* @return mixed
*/
function getAttribute($id, $disposition = FILE_X509_ATTR_ALL, $csr = null)
function getAttribute($id, $disposition = self::ATTR_ALL, $csr = null)
{
if (empty($csr)) {
$csr = $this->currentCert;
@ -4050,10 +4272,10 @@ class File_X509
if ($attribute['type'] == $id) {
$n = count($attribute['value']);
switch (true) {
case $disposition == FILE_X509_ATTR_APPEND:
case $disposition == FILE_X509_ATTR_REPLACE:
case $disposition == self::ATTR_APPEND:
case $disposition == self::ATTR_REPLACE:
return false;
case $disposition == FILE_X509_ATTR_ALL:
case $disposition == self::ATTR_ALL:
return $attribute['value'];
case $disposition >= $n:
$disposition -= $n;
@ -4072,7 +4294,7 @@ class File_X509
*
* @param array $csr optional
* @access public
* @return Array
* @return array
*/
function getAttributes($csr = null)
{
@ -4095,13 +4317,13 @@ class File_X509
/**
* Set a CSR attribute
*
* @param String $id
* @param Mixed $value
* @param Boolean $disposition optional
* @param string $id
* @param mixed $value
* @param bool $disposition optional
* @access public
* @return Boolean
* @return bool
*/
function setAttribute($id, $value, $disposition = FILE_X509_ATTR_ALL)
function setAttribute($id, $value, $disposition = self::ATTR_ALL)
{
$attributes = &$this->_subArray($this->currentCert, 'certificationRequestInfo/attributes', true);
@ -4110,9 +4332,9 @@ class File_X509
}
switch ($disposition) {
case FILE_X509_ATTR_REPLACE:
$disposition = FILE_X509_ATTR_APPEND;
case FILE_X509_ATTR_ALL:
case self::ATTR_REPLACE:
$disposition = self::ATTR_APPEND;
case self::ATTR_ALL:
$this->removeAttribute($id);
break;
}
@ -4121,10 +4343,10 @@ class File_X509
if ($attribute['type'] == $id) {
$n = count($attribute['value']);
switch (true) {
case $disposition == FILE_X509_ATTR_APPEND:
case $disposition == self::ATTR_APPEND:
$last = $key;
break;
case $disposition >= $n;
case $disposition >= $n:
$disposition -= $n;
break;
default:
@ -4141,7 +4363,7 @@ class File_X509
$attributes[$last]['value'][] = $value;
break;
default:
$attributes[] = array('type' => $id, 'value' => $disposition == FILE_X509_ATTR_ALL ? $value: array($value));
$attributes[] = array('type' => $id, 'value' => $disposition == self::ATTR_ALL ? $value: array($value));
break;
}
@ -4153,7 +4375,7 @@ class File_X509
*
* This is used by the id-ce-authorityKeyIdentifier and the id-ce-subjectKeyIdentifier extensions.
*
* @param String $value
* @param string $value
* @access public
*/
function setKeyIdentifier($value)
@ -4173,15 +4395,15 @@ class File_X509
* recommended methods (4.2.1.2 RFC 3280).
* Highly polymorphic: try to accept all possible forms of key:
* - Key object
* - File_X509 object with public or private key defined
* - \phpseclib\File\X509 object with public or private key defined
* - Certificate or CSR array
* - File_ASN1_Element object
* - \phpseclib\File\ASN1\Element object
* - PEM or DER string
*
* @param Mixed $key optional
* @param Integer $method optional
* @param mixed $key optional
* @param int $method optional
* @access public
* @return String binary key identifier
* @return string binary key identifier
*/
function computeKeyIdentifier($key = null, $method = 1)
{
@ -4198,23 +4420,20 @@ class File_X509
return $this->computeKeyIdentifier($key['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'], $method);
case !is_object($key):
return false;
case strtolower(get_class($key)) == 'file_asn1_element':
case $key instanceof Element:
// Assume the element is a bitstring-packed key.
$asn1 = new File_ASN1();
$asn1 = new ASN1();
$decoded = $asn1->decodeBER($key->element);
if (empty($decoded)) {
return false;
}
$raw = $asn1->asn1map($decoded[0], array('type' => FILE_ASN1_TYPE_BIT_STRING));
$raw = $asn1->asn1map($decoded[0], array('type' => ASN1::TYPE_BIT_STRING));
if (empty($raw)) {
return false;
}
$raw = base64_decode($raw);
// If the key is private, compute identifier from its corresponding public key.
if (!class_exists('Crypt_RSA')) {
include_once 'Crypt/RSA.php';
}
$key = new Crypt_RSA();
$key = new RSA();
if (!$key->loadKey($raw)) {
return false; // Not an unencrypted RSA key.
}
@ -4223,7 +4442,7 @@ class File_X509
}
$key = $raw; // Is a public key.
break;
case strtolower(get_class($key)) == 'file_x509':
case $key instanceof X509:
if (isset($key->publicKey)) {
return $this->computeKeyIdentifier($key->publicKey, $method);
}
@ -4234,8 +4453,8 @@ class File_X509
return $this->computeKeyIdentifier($key->currentCert, $method);
}
return false;
default: // Should be a key object (i.e.: Crypt_RSA).
$key = $key->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_PKCS1);
default: // Should be a key object (i.e.: \phpseclib\Crypt\RSA).
$key = $key->getPublicKey(RSA::PUBLIC_FORMAT_PKCS1);
break;
}
@ -4243,10 +4462,7 @@ class File_X509
$key = $this->_extractBER($key);
// Now we have the key string: compute its sha-1 sum.
if (!class_exists('Crypt_Hash')) {
include_once 'Crypt/Hash.php';
}
$hash = new Crypt_Hash('sha1');
$hash = new Hash('sha1');
$hash = $hash->hash($key);
if ($method == 2) {
@ -4261,33 +4477,28 @@ class File_X509
* Format a public key as appropriate
*
* @access private
* @return Array
* @return array
*/
function _formatSubjectPublicKey()
{
if (!isset($this->publicKey) || !is_object($this->publicKey)) {
return false;
if ($this->publicKey instanceof RSA) {
// the following two return statements do the same thing. i dunno.. i just prefer the later for some reason.
// the former is a good example of how to do fuzzing on the public key
//return new Element(base64_decode(preg_replace('#-.+-|[\r\n]#', '', $this->publicKey->getPublicKey())));
return array(
'algorithm' => array('algorithm' => 'rsaEncryption'),
'subjectPublicKey' => $this->publicKey->getPublicKey(RSA::PUBLIC_FORMAT_PKCS1)
);
}
switch (strtolower(get_class($this->publicKey))) {
case 'crypt_rsa':
// the following two return statements do the same thing. i dunno.. i just prefer the later for some reason.
// the former is a good example of how to do fuzzing on the public key
//return new File_ASN1_Element(base64_decode(preg_replace('#-.+-|[\r\n]#', '', $this->publicKey->getPublicKey())));
return array(
'algorithm' => array('algorithm' => 'rsaEncryption'),
'subjectPublicKey' => $this->publicKey->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_PKCS1)
);
default:
return false;
}
return false;
}
/**
* Set the domain name's which the cert is to be valid for
*
* @access public
* @return Array
* @return array
*/
function setDomain()
{
@ -4300,7 +4511,7 @@ class File_X509
* Set the IP Addresses's which the cert is to be valid for
*
* @access public
* @param String $ipAddress optional
* @param string $ipAddress optional
*/
function setIPAddress()
{
@ -4317,8 +4528,8 @@ class File_X509
* Helper function to build domain array
*
* @access private
* @param String $domain
* @return Array
* @param string $domain
* @return array
*/
function _dnsName($domain)
{
@ -4331,8 +4542,8 @@ class File_X509
* (IPv6 is not currently supported)
*
* @access private
* @param String $address
* @return Array
* @param string $address
* @return array
*/
function _iPAddress($address)
{
@ -4343,14 +4554,14 @@ class File_X509
* Get the index of a revoked certificate.
*
* @param array $rclist
* @param String $serial
* @param Boolean $create optional
* @param string $serial
* @param bool $create optional
* @access private
* @return Integer or false
* @return int|false
*/
function _revokedCertificate(&$rclist, $serial, $create = false)
{
$serial = new Math_BigInteger($serial);
$serial = new BigInteger($serial);
foreach ($rclist as $i => $rc) {
if (!($serial->compare($rc['userCertificate']))) {
@ -4371,10 +4582,10 @@ class File_X509
/**
* Revoke a certificate.
*
* @param String $serial
* @param String $date optional
* @param string $serial
* @param string $date optional
* @access public
* @return Boolean
* @return bool
*/
function revoke($serial, $date = null)
{
@ -4382,7 +4593,6 @@ class File_X509
if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) {
if ($this->_revokedCertificate($rclist, $serial) === false) { // If not yet revoked
if (($i = $this->_revokedCertificate($rclist, $serial, true)) !== false) {
if (!empty($date)) {
$rclist[$i]['revocationDate'] = $this->_timeField($date);
}
@ -4399,9 +4609,9 @@ class File_X509
/**
* Unrevoke a certificate.
*
* @param String $serial
* @param string $serial
* @access public
* @return Boolean
* @return bool
*/
function unrevoke($serial)
{
@ -4419,9 +4629,9 @@ class File_X509
/**
* Get a revoked certificate.
*
* @param String $serial
* @param string $serial
* @access public
* @return Mixed
* @return mixed
*/
function getRevoked($serial)
{
@ -4465,10 +4675,10 @@ class File_X509
/**
* Remove a Revoked Certificate Extension
*
* @param String $serial
* @param String $id
* @param string $serial
* @param string $id
* @access public
* @return Boolean
* @return bool
*/
function removeRevokedCertificateExtension($serial, $id)
{
@ -4486,11 +4696,11 @@ class File_X509
*
* Returns the extension if it exists and false if not
*
* @param String $serial
* @param String $id
* @param Array $crl optional
* @param string $serial
* @param string $id
* @param array $crl optional
* @access public
* @return Mixed
* @return mixed
*/
function getRevokedCertificateExtension($serial, $id, $crl = null)
{
@ -4510,10 +4720,10 @@ class File_X509
/**
* Returns a list of all extensions in use for a given revoked certificate
*
* @param String $serial
* @param string $serial
* @param array $crl optional
* @access public
* @return Array
* @return array
*/
function getRevokedCertificateExtensions($serial, $crl = null)
{
@ -4533,13 +4743,13 @@ class File_X509
/**
* Set a Revoked Certificate Extension
*
* @param String $serial
* @param String $id
* @param Mixed $value
* @param Boolean $critical optional
* @param Boolean $replace optional
* @param string $serial
* @param string $id
* @param mixed $value
* @param bool $critical optional
* @param bool $replace optional
* @access public
* @return Boolean
* @return bool
*/
function setRevokedCertificateExtension($serial, $id, $value, $critical = false, $replace = true)
{
@ -4558,8 +4768,8 @@ class File_X509
* Extract raw BER from Base64 encoding
*
* @access private
* @param String $str
* @return String
* @param string $str
* @return string
*/
function _extractBER($str)
{
@ -4572,7 +4782,7 @@ class File_X509
* subject=/O=organization/OU=org unit/CN=common name
* issuer=/O=organization/CN=common name
*/
$temp = preg_replace('#.*?^-+[^-]+-+#ms', '', $str, 1);
$temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1);
// remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff
$temp = preg_replace('#-+[^-]+-+#', '', $temp);
// remove new lines
@ -4580,4 +4790,31 @@ class File_X509
$temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
return $temp != false ? $temp : $str;
}
/**
* Returns the OID corresponding to a name
*
* What's returned in the associative array returned by loadX509() (or load*()) is either a name or an OID if
* no OID to name mapping is available. The problem with this is that what may be an unmapped OID in one version
* of phpseclib may not be unmapped in the next version, so apps that are looking at this OID may not be able
* to work from version to version.
*
* This method will return the OID if a name is passed to it and if no mapping is avialable it'll assume that
* what's being passed to it already is an OID and return that instead. A few examples.
*
* getOID('2.16.840.1.101.3.4.2.1') == '2.16.840.1.101.3.4.2.1'
* getOID('id-sha256') == '2.16.840.1.101.3.4.2.1'
* getOID('zzz') == 'zzz'
*
* @access public
* @return string
*/
function getOID($name)
{
static $reverseMap;
if (!isset($reverseMap)) {
$reverseMap = array_flip($this->oids);
}
return isset($reverseMap[$name]) ? $reverseMap[$name] : $name;
}
}

View file

@ -6,12 +6,12 @@
* Supports base-2, base-10, base-16, and base-256 numbers. Uses the GMP or BCMath extensions, if available,
* and an internal implementation, otherwise.
*
* PHP versions 4 and 5
* PHP version 5
*
* {@internal (all DocBlock comments regarding implementation - such as the one that follows - refer to the
* {@link MATH_BIGINTEGER_MODE_INTERNAL MATH_BIGINTEGER_MODE_INTERNAL} mode)
* {@link self::MODE_INTERNAL self::MODE_INTERNAL} mode)
*
* Math_BigInteger uses base-2**26 to perform operations such as multiplication and division and
* BigInteger uses base-2**26 to perform operations such as multiplication and division and
* base-2**52 (ie. two base 2**26 digits) to perform addition and subtraction. Because the largest possible
* value when multiplying two base-2**26 numbers together is a base-2**52 number, double precision floating
* point numbers - numbers that should be supported on most hardware and whose significand is 53 bits - are
@ -20,7 +20,7 @@
* base is being used should more than compensate.
*
* Numbers are stored in {@link http://en.wikipedia.org/wiki/Endianness little endian} format. ie.
* (new Math_BigInteger(pow(2, 26)))->value = array(0, 1)
* (new \phpseclib\Math\BigInteger(pow(2, 26)))->value = array(0, 1)
*
* Useful resources are as follows:
*
@ -31,10 +31,8 @@
* Here's an example of how to use this library:
* <code>
* <?php
* include 'Math/BigInteger.php';
*
* $a = new Math_BigInteger(2);
* $b = new Math_BigInteger(3);
* $a = new \phpseclib\Math\BigInteger(2);
* $b = new \phpseclib\Math\BigInteger(3);
*
* $c = $a->add($b);
*
@ -42,143 +40,153 @@
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Math
* @package Math_BigInteger
* @package BigInteger
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2006 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://pear.php.net/package/Math_BigInteger
*/
/**#@+
* Reduction constants
*
* @access private
* @see Math_BigInteger::_reduce()
*/
/**
* @see Math_BigInteger::_montgomery()
* @see Math_BigInteger::_prepMontgomery()
*/
define('MATH_BIGINTEGER_MONTGOMERY', 0);
/**
* @see Math_BigInteger::_barrett()
*/
define('MATH_BIGINTEGER_BARRETT', 1);
/**
* @see Math_BigInteger::_mod2()
*/
define('MATH_BIGINTEGER_POWEROF2', 2);
/**
* @see Math_BigInteger::_remainder()
*/
define('MATH_BIGINTEGER_CLASSIC', 3);
/**
* @see Math_BigInteger::__clone()
*/
define('MATH_BIGINTEGER_NONE', 4);
/**#@-*/
namespace phpseclib\Math;
/**#@+
* Array constants
*
* Rather than create a thousands and thousands of new Math_BigInteger objects in repeated function calls to add() and
* multiply() or whatever, we'll just work directly on arrays, taking them in as parameters and returning them.
*
* @access private
*/
/**
* $result[MATH_BIGINTEGER_VALUE] contains the value.
*/
define('MATH_BIGINTEGER_VALUE', 0);
/**
* $result[MATH_BIGINTEGER_SIGN] contains the sign.
*/
define('MATH_BIGINTEGER_SIGN', 1);
/**#@-*/
/**#@+
* @access private
* @see Math_BigInteger::_montgomery()
* @see Math_BigInteger::_barrett()
*/
/**
* Cache constants
*
* $cache[MATH_BIGINTEGER_VARIABLE] tells us whether or not the cached data is still valid.
*/
define('MATH_BIGINTEGER_VARIABLE', 0);
/**
* $cache[MATH_BIGINTEGER_DATA] contains the cached data.
*/
define('MATH_BIGINTEGER_DATA', 1);
/**#@-*/
/**#@+
* Mode constants.
*
* @access private
* @see Math_BigInteger::Math_BigInteger()
*/
/**
* To use the pure-PHP implementation
*/
define('MATH_BIGINTEGER_MODE_INTERNAL', 1);
/**
* To use the BCMath library
*
* (if enabled; otherwise, the internal implementation will be used)
*/
define('MATH_BIGINTEGER_MODE_BCMATH', 2);
/**
* To use the GMP library
*
* (if present; otherwise, either the BCMath or the internal implementation will be used)
*/
define('MATH_BIGINTEGER_MODE_GMP', 3);
/**#@-*/
/**
* Karatsuba Cutoff
*
* At what point do we switch between Karatsuba multiplication and schoolbook long multiplication?
*
* @access private
*/
define('MATH_BIGINTEGER_KARATSUBA_CUTOFF', 25);
use phpseclib\Crypt\Random;
/**
* Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256
* numbers.
*
* @package Math_BigInteger
* @package BigInteger
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Math_BigInteger
class BigInteger
{
/**#@+
* Reduction constants
*
* @access private
* @see BigInteger::_reduce()
*/
/**
* @see BigInteger::_montgomery()
* @see BigInteger::_prepMontgomery()
*/
const MONTGOMERY = 0;
/**
* @see BigInteger::_barrett()
*/
const BARRETT = 1;
/**
* @see BigInteger::_mod2()
*/
const POWEROF2 = 2;
/**
* @see BigInteger::_remainder()
*/
const CLASSIC = 3;
/**
* @see BigInteger::__clone()
*/
const NONE = 4;
/**#@-*/
/**#@+
* Array constants
*
* Rather than create a thousands and thousands of new BigInteger objects in repeated function calls to add() and
* multiply() or whatever, we'll just work directly on arrays, taking them in as parameters and returning them.
*
* @access private
*/
/**
* $result[self::VALUE] contains the value.
*/
const VALUE = 0;
/**
* $result[self::SIGN] contains the sign.
*/
const SIGN = 1;
/**#@-*/
/**#@+
* @access private
* @see BigInteger::_montgomery()
* @see BigInteger::_barrett()
*/
/**
* Cache constants
*
* $cache[self::VARIABLE] tells us whether or not the cached data is still valid.
*/
const VARIABLE = 0;
/**
* $cache[self::DATA] contains the cached data.
*/
const DATA = 1;
/**#@-*/
/**#@+
* Mode constants.
*
* @access private
* @see BigInteger::__construct()
*/
/**
* To use the pure-PHP implementation
*/
const MODE_INTERNAL = 1;
/**
* To use the BCMath library
*
* (if enabled; otherwise, the internal implementation will be used)
*/
const MODE_BCMATH = 2;
/**
* To use the GMP library
*
* (if present; otherwise, either the BCMath or the internal implementation will be used)
*/
const MODE_GMP = 3;
/**#@-*/
/**
* Karatsuba Cutoff
*
* At what point do we switch between Karatsuba multiplication and schoolbook long multiplication?
*
* @access private
*/
const KARATSUBA_CUTOFF = 25;
/**#@+
* Static properties used by the pure-PHP implementation.
*
* @see __construct()
*/
protected static $base;
protected static $baseFull;
protected static $maxDigit;
protected static $msb;
/**
* $max10 in greatest $max10Len satisfying
* $max10 = 10**$max10Len <= 2**$base.
*/
protected static $max10;
/**
* $max10Len in greatest $max10Len satisfying
* $max10 = 10**$max10Len <= 2**$base.
*/
protected static $max10Len;
protected static $maxDigit2;
/**#@-*/
/**
* Holds the BigInteger's value.
*
* @var Array
* @var array
* @access private
*/
var $value;
@ -186,23 +194,15 @@ class Math_BigInteger
/**
* Holds the BigInteger's magnitude.
*
* @var Boolean
* @var bool
* @access private
*/
var $is_negative = false;
/**
* Random number generator function
*
* @see setRandomGenerator()
* @access private
*/
var $generator = 'mt_rand';
/**
* Precision
*
* @see setPrecision()
* @see self::setPrecision()
* @access private
*/
var $precision = -1;
@ -210,7 +210,7 @@ class Math_BigInteger
/**
* Precision Bitmask
*
* @see setPrecision()
* @see self::setPrecision()
* @access private
*/
var $bitmask = false;
@ -222,9 +222,9 @@ class Math_BigInteger
* a variable that'll be serializable regardless of whether or not extensions are being used. Unlike $this->value,
* however, $this->hex is only calculated when $this->__sleep() is called.
*
* @see __sleep()
* @see __wakeup()
* @var String
* @see self::__sleep()
* @see self::__wakeup()
* @var string
* @access private
*/
var $hex;
@ -238,35 +238,33 @@ class Math_BigInteger
* Here's an example:
* <code>
* <?php
* include 'Math/BigInteger.php';
*
* $a = new Math_BigInteger('0x32', 16); // 50 in base-16
* $a = new \phpseclib\Math\BigInteger('0x32', 16); // 50 in base-16
*
* echo $a->toString(); // outputs 50
* ?>
* </code>
*
* @param optional $x base-10 number or base-$base number if $base set.
* @param optional integer $base
* @return Math_BigInteger
* @param $x base-10 number or base-$base number if $base set.
* @param int $base
* @return \phpseclib\Math\BigInteger
* @access public
*/
function Math_BigInteger($x = 0, $base = 10)
function __construct($x = 0, $base = 10)
{
if ( !defined('MATH_BIGINTEGER_MODE') ) {
if (!defined('MATH_BIGINTEGER_MODE')) {
switch (true) {
case extension_loaded('gmp'):
define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_GMP);
define('MATH_BIGINTEGER_MODE', self::MODE_GMP);
break;
case extension_loaded('bcmath'):
define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_BCMATH);
define('MATH_BIGINTEGER_MODE', self::MODE_BCMATH);
break;
default:
define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_INTERNAL);
define('MATH_BIGINTEGER_MODE', self::MODE_INTERNAL);
}
}
if (function_exists('openssl_public_encrypt') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
if (extension_loaded('openssl') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
// some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
ob_start();
@phpinfo();
@ -294,6 +292,7 @@ class Math_BigInteger
case !isset($versions['Header']):
case !isset($versions['Library']):
case $versions['Header'] == $versions['Library']:
case version_compare($versions['Header'], '1.0.0') >= 0 && version_compare($versions['Library'], '1.0.0') >= 0:
define('MATH_BIGINTEGER_OPENSSL_ENABLED', true);
break;
default:
@ -305,47 +304,41 @@ class Math_BigInteger
define('PHP_INT_SIZE', 4);
}
if (!defined('MATH_BIGINTEGER_BASE') && MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_INTERNAL) {
if (empty(self::$base) && MATH_BIGINTEGER_MODE == self::MODE_INTERNAL) {
switch (PHP_INT_SIZE) {
case 8: // use 64-bit integers if int size is 8 bytes
define('MATH_BIGINTEGER_BASE', 31);
define('MATH_BIGINTEGER_BASE_FULL', 0x80000000);
define('MATH_BIGINTEGER_MAX_DIGIT', 0x7FFFFFFF);
define('MATH_BIGINTEGER_MSB', 0x40000000);
// 10**9 is the closest we can get to 2**31 without passing it
define('MATH_BIGINTEGER_MAX10', 1000000000);
define('MATH_BIGINTEGER_MAX10_LEN', 9);
// the largest digit that may be used in addition / subtraction
define('MATH_BIGINTEGER_MAX_DIGIT2', pow(2, 62));
self::$base = 31;
self::$baseFull = 0x80000000;
self::$maxDigit = 0x7FFFFFFF;
self::$msb = 0x40000000;
self::$max10 = 1000000000;
self::$max10Len = 9;
self::$maxDigit2 = pow(2, 62);
break;
//case 4: // use 64-bit floats if int size is 4 bytes
default:
define('MATH_BIGINTEGER_BASE', 26);
define('MATH_BIGINTEGER_BASE_FULL', 0x4000000);
define('MATH_BIGINTEGER_MAX_DIGIT', 0x3FFFFFF);
define('MATH_BIGINTEGER_MSB', 0x2000000);
// 10**7 is the closest to 2**26 without passing it
define('MATH_BIGINTEGER_MAX10', 10000000);
define('MATH_BIGINTEGER_MAX10_LEN', 7);
// the largest digit that may be used in addition / subtraction
// we do pow(2, 52) instead of using 4503599627370496 directly because some
// PHP installations will truncate 4503599627370496.
define('MATH_BIGINTEGER_MAX_DIGIT2', pow(2, 52));
self::$base = 26;
self::$baseFull = 0x4000000;
self::$maxDigit = 0x3FFFFFF;
self::$msb = 0x2000000;
self::$max10 = 10000000;
self::$max10Len = 7;
self::$maxDigit2 = pow(2, 52); // pow() prevents truncation
}
}
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
switch (true) {
case is_resource($x) && get_resource_type($x) == 'GMP integer':
// PHP 5.6 switched GMP from using resources to objects
case is_object($x) && get_class($x) == 'GMP':
case $x instanceof \GMP:
$this->value = $x;
return;
}
$this->value = gmp_init(0);
break;
case MATH_BIGINTEGER_MODE_BCMATH:
case self::MODE_BCMATH:
$this->value = '0';
break;
default:
@ -364,13 +357,13 @@ class Math_BigInteger
$x = ~$x;
$this->is_negative = true;
}
case 256:
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
case 256:
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
$sign = $this->is_negative ? '-' : '';
$this->value = gmp_init($sign . '0x' . bin2hex($x));
break;
case MATH_BIGINTEGER_MODE_BCMATH:
case self::MODE_BCMATH:
// round $len to the nearest 4 (thanks, DavidMJ!)
$len = (strlen($x) + 3) & 0xFFFFFFFC;
@ -389,19 +382,19 @@ class Math_BigInteger
// converts a base-2**8 (big endian / msb) number to base-2**26 (little endian / lsb)
default:
while (strlen($x)) {
$this->value[] = $this->_bytes2int($this->_base256_rshift($x, MATH_BIGINTEGER_BASE));
$this->value[] = $this->_bytes2int($this->_base256_rshift($x, self::$base));
}
}
if ($this->is_negative) {
if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL) {
if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) {
$this->is_negative = false;
}
$temp = $this->add(new Math_BigInteger('-1'));
$temp = $this->add(new static('-1'));
$this->value = $temp->value;
}
break;
case 16:
case 16:
case -16:
if ($base > 0 && $x[0] == '-') {
$this->is_negative = true;
@ -416,67 +409,67 @@ class Math_BigInteger
$x = bin2hex(~pack('H*', $x));
}
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
$temp = $this->is_negative ? '-0x' . $x : '0x' . $x;
$this->value = gmp_init($temp);
$this->is_negative = false;
break;
case MATH_BIGINTEGER_MODE_BCMATH:
$x = ( strlen($x) & 1 ) ? '0' . $x : $x;
$temp = new Math_BigInteger(pack('H*', $x), 256);
case self::MODE_BCMATH:
$x = (strlen($x) & 1) ? '0' . $x : $x;
$temp = new static(pack('H*', $x), 256);
$this->value = $this->is_negative ? '-' . $temp->value : $temp->value;
$this->is_negative = false;
break;
default:
$x = ( strlen($x) & 1 ) ? '0' . $x : $x;
$temp = new Math_BigInteger(pack('H*', $x), 256);
$x = (strlen($x) & 1) ? '0' . $x : $x;
$temp = new static(pack('H*', $x), 256);
$this->value = $temp->value;
}
if ($is_negative) {
$temp = $this->add(new Math_BigInteger('-1'));
$temp = $this->add(new static('-1'));
$this->value = $temp->value;
}
break;
case 10:
case 10:
case -10:
// (?<!^)(?:-).*: find any -'s that aren't at the beginning and then any characters that follow that
// (?<=^|-)0*: find any 0's that are preceded by the start of the string or by a - (ie. octals)
// [^-0-9].*: find any non-numeric characters and then any characters that follow that
$x = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x);
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
$this->value = gmp_init($x);
break;
case MATH_BIGINTEGER_MODE_BCMATH:
case self::MODE_BCMATH:
// explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different
// results then doing it on '-1' does (modInverse does $x[0])
$this->value = $x === '-' ? '0' : (string) $x;
break;
default:
$temp = new Math_BigInteger();
$temp = new static();
$multiplier = new Math_BigInteger();
$multiplier->value = array(MATH_BIGINTEGER_MAX10);
$multiplier = new static();
$multiplier->value = array(self::$max10);
if ($x[0] == '-') {
$this->is_negative = true;
$x = substr($x, 1);
}
$x = str_pad($x, strlen($x) + ((MATH_BIGINTEGER_MAX10_LEN - 1) * strlen($x)) % MATH_BIGINTEGER_MAX10_LEN, 0, STR_PAD_LEFT);
$x = str_pad($x, strlen($x) + ((self::$max10Len - 1) * strlen($x)) % self::$max10Len, 0, STR_PAD_LEFT);
while (strlen($x)) {
$temp = $temp->multiply($multiplier);
$temp = $temp->add(new Math_BigInteger($this->_int2bytes(substr($x, 0, MATH_BIGINTEGER_MAX10_LEN)), 256));
$x = substr($x, MATH_BIGINTEGER_MAX10_LEN);
$temp = $temp->add(new static($this->_int2bytes(substr($x, 0, self::$max10Len)), 256));
$x = substr($x, self::$max10Len);
}
$this->value = $temp->value;
}
break;
case 2: // base-2 support originally implemented by Lluis Pamies - thanks!
case 2: // base-2 support originally implemented by Lluis Pamies - thanks!
case -2:
if ($base > 0 && $x[0] == '-') {
$this->is_negative = true;
@ -497,7 +490,7 @@ class Math_BigInteger
$str = '-' . $str;
}
$temp = new Math_BigInteger($str, 8 * $base); // ie. either -16 or +16
$temp = new static($str, 8 * $base); // ie. either -16 or +16
$this->value = $temp->value;
$this->is_negative = $temp->is_negative;
@ -516,28 +509,26 @@ class Math_BigInteger
* Here's an example:
* <code>
* <?php
* include 'Math/BigInteger.php';
*
* $a = new Math_BigInteger('65');
* $a = new \phpseclib\Math\BigInteger('65');
*
* echo $a->toBytes(); // outputs chr(65)
* ?>
* </code>
*
* @param Boolean $twos_compliment
* @return String
* @param bool $twos_compliment
* @return string
* @access public
* @internal Converts a base-2**26 number to base-2**8
*/
function toBytes($twos_compliment = false)
{
if ($twos_compliment) {
$comparison = $this->compare(new Math_BigInteger());
$comparison = $this->compare(new static());
if ($comparison == 0) {
return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
}
$temp = $comparison < 0 ? $this->add(new Math_BigInteger(1)) : $this->copy();
$temp = $comparison < 0 ? $this->add(new static(1)) : $this->copy();
$bytes = $temp->toBytes();
if (empty($bytes)) { // eg. if the number we're trying to convert is -1
@ -551,20 +542,20 @@ class Math_BigInteger
return $comparison < 0 ? ~$bytes : $bytes;
}
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
if (gmp_cmp($this->value, gmp_init(0)) == 0) {
return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
}
$temp = gmp_strval(gmp_abs($this->value), 16);
$temp = ( strlen($temp) & 1 ) ? '0' . $temp : $temp;
$temp = (strlen($temp) & 1) ? '0' . $temp : $temp;
$temp = pack('H*', $temp);
return $this->precision > 0 ?
substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :
ltrim($temp, chr(0));
case MATH_BIGINTEGER_MODE_BCMATH:
case self::MODE_BCMATH:
if ($this->value === '0') {
return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
}
@ -595,7 +586,7 @@ class Math_BigInteger
$temp = $this->copy();
for ($i = count($temp->value) - 2; $i >= 0; --$i) {
$temp->_base256_lshift($result, MATH_BIGINTEGER_BASE);
$temp->_base256_lshift($result, self::$base);
$result = $result | str_pad($temp->_int2bytes($temp->value[$i]), strlen($result), chr(0), STR_PAD_LEFT);
}
@ -613,16 +604,14 @@ class Math_BigInteger
* Here's an example:
* <code>
* <?php
* include 'Math/BigInteger.php';
*
* $a = new Math_BigInteger('65');
* $a = new \phpseclib\Math\BigInteger('65');
*
* echo $a->toHex(); // outputs '41'
* ?>
* </code>
*
* @param Boolean $twos_compliment
* @return String
* @param bool $twos_compliment
* @return string
* @access public
* @internal Converts a base-2**26 number to base-2**8
*/
@ -640,16 +629,14 @@ class Math_BigInteger
* Here's an example:
* <code>
* <?php
* include 'Math/BigInteger.php';
*
* $a = new Math_BigInteger('65');
* $a = new \phpseclib\Math\BigInteger('65');
*
* echo $a->toBits(); // outputs '1000001'
* ?>
* </code>
*
* @param Boolean $twos_compliment
* @return String
* @param bool $twos_compliment
* @return string
* @access public
* @internal Converts a base-2**26 number to base-2**2
*/
@ -665,7 +652,7 @@ class Math_BigInteger
}
$result = $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0');
if ($twos_compliment && $this->compare(new Math_BigInteger()) > 0 && $this->precision <= 0) {
if ($twos_compliment && $this->compare(new static()) > 0 && $this->precision <= 0) {
return '0' . $result;
}
@ -678,24 +665,22 @@ class Math_BigInteger
* Here's an example:
* <code>
* <?php
* include 'Math/BigInteger.php';
*
* $a = new Math_BigInteger('50');
* $a = new \phpseclib\Math\BigInteger('50');
*
* echo $a->toString(); // outputs 50
* ?>
* </code>
*
* @return String
* @return string
* @access public
* @internal Converts a base-2**26 number to base-10**7 (which is pretty much base-10)
*/
function toString()
{
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
return gmp_strval($this->value);
case MATH_BIGINTEGER_MODE_BCMATH:
case self::MODE_BCMATH:
if ($this->value === '0') {
return '0';
}
@ -710,12 +695,12 @@ class Math_BigInteger
$temp = $this->copy();
$temp->is_negative = false;
$divisor = new Math_BigInteger();
$divisor->value = array(MATH_BIGINTEGER_MAX10);
$divisor = new static();
$divisor->value = array(self::$max10);
$result = '';
while (count($temp->value)) {
list($temp, $mod) = $temp->divide($divisor);
$result = str_pad(isset($mod->value[0]) ? $mod->value[0] : '', MATH_BIGINTEGER_MAX10_LEN, '0', STR_PAD_LEFT) . $result;
$result = str_pad(isset($mod->value[0]) ? $mod->value[0] : '', self::$max10Len, '0', STR_PAD_LEFT) . $result;
}
$result = ltrim($result, '0');
if (empty($result)) {
@ -738,15 +723,14 @@ class Math_BigInteger
* {@link http://php.net/language.oop5.basic#51624}
*
* @access public
* @see __clone()
* @return Math_BigInteger
* @see self::__clone()
* @return \phpseclib\Math\BigInteger
*/
function copy()
{
$temp = new Math_BigInteger();
$temp = new static();
$temp->value = $this->value;
$temp->is_negative = $this->is_negative;
$temp->generator = $this->generator;
$temp->precision = $this->precision;
$temp->bitmask = $this->bitmask;
return $temp;
@ -769,14 +753,14 @@ class Math_BigInteger
/**
* __clone() magic method
*
* Although you can call Math_BigInteger::__toString() directly in PHP5, you cannot call Math_BigInteger::__clone()
* directly in PHP5. You can in PHP4 since it's not a magic method, but in PHP5, you have to call it by using the PHP5
* only syntax of $y = clone $x. As such, if you're trying to write an application that works on both PHP4 and PHP5,
* call Math_BigInteger::copy(), instead.
* Although you can call BigInteger::__toString() directly in PHP5, you cannot call BigInteger::__clone() directly
* in PHP5. You can in PHP4 since it's not a magic method, but in PHP5, you have to call it by using the PHP5
* only syntax of $y = clone $x. As such, if you're trying to write an application that works on both PHP4 and
* PHP5, call BigInteger::copy(), instead.
*
* @access public
* @see copy()
* @return Math_BigInteger
* @see self::copy()
* @return \phpseclib\Math\BigInteger
*/
function __clone()
{
@ -786,55 +770,81 @@ class Math_BigInteger
/**
* __sleep() magic method
*
* Will be called, automatically, when serialize() is called on a Math_BigInteger object.
* Will be called, automatically, when serialize() is called on a BigInteger object.
*
* @see __wakeup()
* @see self::__wakeup()
* @access public
*/
function __sleep()
{
$this->hex = $this->toHex(true);
$vars = array('hex');
if ($this->generator != 'mt_rand') {
$vars[] = 'generator';
}
if ($this->precision > 0) {
$vars[] = 'precision';
}
return $vars;
}
/**
* __wakeup() magic method
*
* Will be called, automatically, when unserialize() is called on a Math_BigInteger object.
* Will be called, automatically, when unserialize() is called on a BigInteger object.
*
* @see __sleep()
* @see self::__sleep()
* @access public
*/
function __wakeup()
{
$temp = new Math_BigInteger($this->hex, -16);
$temp = new static($this->hex, -16);
$this->value = $temp->value;
$this->is_negative = $temp->is_negative;
$this->setRandomGenerator($this->generator);
if ($this->precision > 0) {
// recalculate $this->bitmask
$this->setPrecision($this->precision);
}
}
/**
* __debugInfo() magic method
*
* Will be called, automatically, when print_r() or var_dump() are called
*
* @access public
*/
function __debugInfo()
{
$opts = array();
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
$engine = 'gmp';
break;
case self::MODE_BCMATH:
$engine = 'bcmath';
break;
case self::MODE_INTERNAL:
$engine = 'internal';
$opts[] = PHP_INT_SIZE == 8 ? '64-bit' : '32-bit';
}
if (MATH_BIGINTEGER_MODE != self::MODE_GMP && defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
$opts[] = 'OpenSSL';
}
if (!empty($opts)) {
$engine.= ' (' . implode($opts, ', ') . ')';
}
return array(
'value' => '0x' . $this->toHex(true),
'engine' => $engine
);
}
/**
* Adds two BigIntegers.
*
* Here's an example:
* <code>
* <?php
* include 'Math/BigInteger.php';
*
* $a = new Math_BigInteger('10');
* $b = new Math_BigInteger('20');
* $a = new \phpseclib\Math\BigInteger('10');
* $b = new \phpseclib\Math\BigInteger('20');
*
* $c = $a->add($b);
*
@ -842,21 +852,21 @@ class Math_BigInteger
* ?>
* </code>
*
* @param Math_BigInteger $y
* @return Math_BigInteger
* @param \phpseclib\Math\BigInteger $y
* @return \phpseclib\Math\BigInteger
* @access public
* @internal Performs base-2**52 addition
*/
function add($y)
{
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
$temp = new Math_BigInteger();
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
$temp = new static();
$temp->value = gmp_add($this->value, $y->value);
return $this->_normalize($temp);
case MATH_BIGINTEGER_MODE_BCMATH:
$temp = new Math_BigInteger();
case self::MODE_BCMATH:
$temp = new static();
$temp->value = bcadd($this->value, $y->value, 0);
return $this->_normalize($temp);
@ -864,9 +874,9 @@ class Math_BigInteger
$temp = $this->_add($this->value, $this->is_negative, $y->value, $y->is_negative);
$result = new Math_BigInteger();
$result->value = $temp[MATH_BIGINTEGER_VALUE];
$result->is_negative = $temp[MATH_BIGINTEGER_SIGN];
$result = new static();
$result->value = $temp[self::VALUE];
$result->is_negative = $temp[self::SIGN];
return $this->_normalize($result);
}
@ -874,11 +884,11 @@ class Math_BigInteger
/**
* Performs addition.
*
* @param Array $x_value
* @param Boolean $x_negative
* @param Array $y_value
* @param Boolean $y_negative
* @return Array
* @param array $x_value
* @param bool $x_negative
* @param array $y_value
* @param bool $y_negative
* @return array
* @access private
*/
function _add($x_value, $x_negative, $y_value, $y_negative)
@ -888,27 +898,27 @@ class Math_BigInteger
if ($x_size == 0) {
return array(
MATH_BIGINTEGER_VALUE => $y_value,
MATH_BIGINTEGER_SIGN => $y_negative
self::VALUE => $y_value,
self::SIGN => $y_negative
);
} else if ($y_size == 0) {
} elseif ($y_size == 0) {
return array(
MATH_BIGINTEGER_VALUE => $x_value,
MATH_BIGINTEGER_SIGN => $x_negative
self::VALUE => $x_value,
self::SIGN => $x_negative
);
}
// subtract, if appropriate
if ( $x_negative != $y_negative ) {
if ( $x_value == $y_value ) {
if ($x_negative != $y_negative) {
if ($x_value == $y_value) {
return array(
MATH_BIGINTEGER_VALUE => array(),
MATH_BIGINTEGER_SIGN => false
self::VALUE => array(),
self::SIGN => false
);
}
$temp = $this->_subtract($x_value, false, $y_value, false);
$temp[MATH_BIGINTEGER_SIGN] = $this->_compare($x_value, false, $y_value, false) > 0 ?
$temp[self::SIGN] = $this->_compare($x_value, false, $y_value, false) > 0 ?
$x_negative : $y_negative;
return $temp;
@ -926,33 +936,33 @@ class Math_BigInteger
$carry = 0;
for ($i = 0, $j = 1; $j < $size; $i+=2, $j+=2) {
$sum = $x_value[$j] * MATH_BIGINTEGER_BASE_FULL + $x_value[$i] + $y_value[$j] * MATH_BIGINTEGER_BASE_FULL + $y_value[$i] + $carry;
$carry = $sum >= MATH_BIGINTEGER_MAX_DIGIT2; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
$sum = $carry ? $sum - MATH_BIGINTEGER_MAX_DIGIT2 : $sum;
$sum = $x_value[$j] * self::$baseFull + $x_value[$i] + $y_value[$j] * self::$baseFull + $y_value[$i] + $carry;
$carry = $sum >= self::$maxDigit2; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
$sum = $carry ? $sum - self::$maxDigit2 : $sum;
$temp = MATH_BIGINTEGER_BASE === 26 ? intval($sum / 0x4000000) : ($sum >> 31);
$temp = self::$base === 26 ? intval($sum / 0x4000000) : ($sum >> 31);
$value[$i] = (int) ($sum - MATH_BIGINTEGER_BASE_FULL * $temp); // eg. a faster alternative to fmod($sum, 0x4000000)
$value[$i] = (int) ($sum - self::$baseFull * $temp); // eg. a faster alternative to fmod($sum, 0x4000000)
$value[$j] = $temp;
}
if ($j == $size) { // ie. if $y_size is odd
$sum = $x_value[$i] + $y_value[$i] + $carry;
$carry = $sum >= MATH_BIGINTEGER_BASE_FULL;
$value[$i] = $carry ? $sum - MATH_BIGINTEGER_BASE_FULL : $sum;
$carry = $sum >= self::$baseFull;
$value[$i] = $carry ? $sum - self::$baseFull : $sum;
++$i; // ie. let $i = $j since we've just done $value[$i]
}
if ($carry) {
for (; $value[$i] == MATH_BIGINTEGER_MAX_DIGIT; ++$i) {
for (; $value[$i] == self::$maxDigit; ++$i) {
$value[$i] = 0;
}
++$value[$i];
}
return array(
MATH_BIGINTEGER_VALUE => $this->_trim($value),
MATH_BIGINTEGER_SIGN => $x_negative
self::VALUE => $this->_trim($value),
self::SIGN => $x_negative
);
}
@ -962,10 +972,8 @@ class Math_BigInteger
* Here's an example:
* <code>
* <?php
* include 'Math/BigInteger.php';
*
* $a = new Math_BigInteger('10');
* $b = new Math_BigInteger('20');
* $a = new \phpseclib\Math\BigInteger('10');
* $b = new \phpseclib\Math\BigInteger('20');
*
* $c = $a->subtract($b);
*
@ -973,21 +981,21 @@ class Math_BigInteger
* ?>
* </code>
*
* @param Math_BigInteger $y
* @return Math_BigInteger
* @param \phpseclib\Math\BigInteger $y
* @return \phpseclib\Math\BigInteger
* @access public
* @internal Performs base-2**52 subtraction
*/
function subtract($y)
{
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
$temp = new Math_BigInteger();
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
$temp = new static();
$temp->value = gmp_sub($this->value, $y->value);
return $this->_normalize($temp);
case MATH_BIGINTEGER_MODE_BCMATH:
$temp = new Math_BigInteger();
case self::MODE_BCMATH:
$temp = new static();
$temp->value = bcsub($this->value, $y->value, 0);
return $this->_normalize($temp);
@ -995,9 +1003,9 @@ class Math_BigInteger
$temp = $this->_subtract($this->value, $this->is_negative, $y->value, $y->is_negative);
$result = new Math_BigInteger();
$result->value = $temp[MATH_BIGINTEGER_VALUE];
$result->is_negative = $temp[MATH_BIGINTEGER_SIGN];
$result = new static();
$result->value = $temp[self::VALUE];
$result->is_negative = $temp[self::SIGN];
return $this->_normalize($result);
}
@ -1005,11 +1013,11 @@ class Math_BigInteger
/**
* Performs subtraction.
*
* @param Array $x_value
* @param Boolean $x_negative
* @param Array $y_value
* @param Boolean $y_negative
* @return Array
* @param array $x_value
* @param bool $x_negative
* @param array $y_value
* @param bool $y_negative
* @return array
* @access private
*/
function _subtract($x_value, $x_negative, $y_value, $y_negative)
@ -1019,35 +1027,35 @@ class Math_BigInteger
if ($x_size == 0) {
return array(
MATH_BIGINTEGER_VALUE => $y_value,
MATH_BIGINTEGER_SIGN => !$y_negative
self::VALUE => $y_value,
self::SIGN => !$y_negative
);
} else if ($y_size == 0) {
} elseif ($y_size == 0) {
return array(
MATH_BIGINTEGER_VALUE => $x_value,
MATH_BIGINTEGER_SIGN => $x_negative
self::VALUE => $x_value,
self::SIGN => $x_negative
);
}
// add, if appropriate (ie. -$x - +$y or +$x - -$y)
if ( $x_negative != $y_negative ) {
if ($x_negative != $y_negative) {
$temp = $this->_add($x_value, false, $y_value, false);
$temp[MATH_BIGINTEGER_SIGN] = $x_negative;
$temp[self::SIGN] = $x_negative;
return $temp;
}
$diff = $this->_compare($x_value, $x_negative, $y_value, $y_negative);
if ( !$diff ) {
if (!$diff) {
return array(
MATH_BIGINTEGER_VALUE => array(),
MATH_BIGINTEGER_SIGN => false
self::VALUE => array(),
self::SIGN => false
);
}
// switch $x and $y around, if appropriate.
if ( (!$x_negative && $diff < 0) || ($x_negative && $diff > 0) ) {
if ((!$x_negative && $diff < 0) || ($x_negative && $diff > 0)) {
$temp = $x_value;
$x_value = $y_value;
$y_value = $temp;
@ -1062,33 +1070,33 @@ class Math_BigInteger
$carry = 0;
for ($i = 0, $j = 1; $j < $y_size; $i+=2, $j+=2) {
$sum = $x_value[$j] * MATH_BIGINTEGER_BASE_FULL + $x_value[$i] - $y_value[$j] * MATH_BIGINTEGER_BASE_FULL - $y_value[$i] - $carry;
$sum = $x_value[$j] * self::$baseFull + $x_value[$i] - $y_value[$j] * self::$baseFull - $y_value[$i] - $carry;
$carry = $sum < 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
$sum = $carry ? $sum + MATH_BIGINTEGER_MAX_DIGIT2 : $sum;
$sum = $carry ? $sum + self::$maxDigit2 : $sum;
$temp = MATH_BIGINTEGER_BASE === 26 ? intval($sum / 0x4000000) : ($sum >> 31);
$temp = self::$base === 26 ? intval($sum / 0x4000000) : ($sum >> 31);
$x_value[$i] = (int) ($sum - MATH_BIGINTEGER_BASE_FULL * $temp);
$x_value[$i] = (int) ($sum - self::$baseFull * $temp);
$x_value[$j] = $temp;
}
if ($j == $y_size) { // ie. if $y_size is odd
$sum = $x_value[$i] - $y_value[$i] - $carry;
$carry = $sum < 0;
$x_value[$i] = $carry ? $sum + MATH_BIGINTEGER_BASE_FULL : $sum;
$x_value[$i] = $carry ? $sum + self::$baseFull : $sum;
++$i;
}
if ($carry) {
for (; !$x_value[$i]; ++$i) {
$x_value[$i] = MATH_BIGINTEGER_MAX_DIGIT;
$x_value[$i] = self::$maxDigit;
}
--$x_value[$i];
}
return array(
MATH_BIGINTEGER_VALUE => $this->_trim($x_value),
MATH_BIGINTEGER_SIGN => $x_negative
self::VALUE => $this->_trim($x_value),
self::SIGN => $x_negative
);
}
@ -1098,10 +1106,8 @@ class Math_BigInteger
* Here's an example:
* <code>
* <?php
* include 'Math/BigInteger.php';
*
* $a = new Math_BigInteger('10');
* $b = new Math_BigInteger('20');
* $a = new \phpseclib\Math\BigInteger('10');
* $b = new \phpseclib\Math\BigInteger('20');
*
* $c = $a->multiply($b);
*
@ -1109,20 +1115,20 @@ class Math_BigInteger
* ?>
* </code>
*
* @param Math_BigInteger $x
* @return Math_BigInteger
* @param \phpseclib\Math\BigInteger $x
* @return \phpseclib\Math\BigInteger
* @access public
*/
function multiply($x)
{
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
$temp = new Math_BigInteger();
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
$temp = new static();
$temp->value = gmp_mul($this->value, $x->value);
return $this->_normalize($temp);
case MATH_BIGINTEGER_MODE_BCMATH:
$temp = new Math_BigInteger();
case self::MODE_BCMATH:
$temp = new static();
$temp->value = bcmul($this->value, $x->value, 0);
return $this->_normalize($temp);
@ -1130,9 +1136,9 @@ class Math_BigInteger
$temp = $this->_multiply($this->value, $this->is_negative, $x->value, $x->is_negative);
$product = new Math_BigInteger();
$product->value = $temp[MATH_BIGINTEGER_VALUE];
$product->is_negative = $temp[MATH_BIGINTEGER_SIGN];
$product = new static();
$product->value = $temp[self::VALUE];
$product->is_negative = $temp[self::SIGN];
return $this->_normalize($product);
}
@ -1140,37 +1146,37 @@ class Math_BigInteger
/**
* Performs multiplication.
*
* @param Array $x_value
* @param Boolean $x_negative
* @param Array $y_value
* @param Boolean $y_negative
* @return Array
* @param array $x_value
* @param bool $x_negative
* @param array $y_value
* @param bool $y_negative
* @return array
* @access private
*/
function _multiply($x_value, $x_negative, $y_value, $y_negative)
{
//if ( $x_value == $y_value ) {
// return array(
// MATH_BIGINTEGER_VALUE => $this->_square($x_value),
// MATH_BIGINTEGER_SIGN => $x_sign != $y_value
// self::VALUE => $this->_square($x_value),
// self::SIGN => $x_sign != $y_value
// );
//}
$x_length = count($x_value);
$y_length = count($y_value);
if ( !$x_length || !$y_length ) { // a 0 is being multiplied
if (!$x_length || !$y_length) { // a 0 is being multiplied
return array(
MATH_BIGINTEGER_VALUE => array(),
MATH_BIGINTEGER_SIGN => false
self::VALUE => array(),
self::SIGN => false
);
}
return array(
MATH_BIGINTEGER_VALUE => min($x_length, $y_length) < 2 * MATH_BIGINTEGER_KARATSUBA_CUTOFF ?
self::VALUE => min($x_length, $y_length) < 2 * self::KARATSUBA_CUTOFF ?
$this->_trim($this->_regularMultiply($x_value, $y_value)) :
$this->_trim($this->_karatsuba($x_value, $y_value)),
MATH_BIGINTEGER_SIGN => $x_negative != $y_negative
self::SIGN => $x_negative != $y_negative
);
}
@ -1179,9 +1185,9 @@ class Math_BigInteger
*
* Modeled after 'multiply' in MutableBigInteger.java.
*
* @param Array $x_value
* @param Array $y_value
* @return Array
* @param array $x_value
* @param array $y_value
* @return array
* @access private
*/
function _regularMultiply($x_value, $y_value)
@ -1189,11 +1195,11 @@ class Math_BigInteger
$x_length = count($x_value);
$y_length = count($y_value);
if ( !$x_length || !$y_length ) { // a 0 is being multiplied
if (!$x_length || !$y_length) { // a 0 is being multiplied
return array();
}
if ( $x_length < $y_length ) {
if ($x_length < $y_length) {
$temp = $x_value;
$x_value = $y_value;
$y_value = $temp;
@ -1214,8 +1220,8 @@ class Math_BigInteger
for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0
$temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
$carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
$product_value[$j] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
$carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
$product_value[$j] = (int) ($temp - self::$baseFull * $carry);
}
$product_value[$j] = $carry;
@ -1227,8 +1233,8 @@ class Math_BigInteger
for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) {
$temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
$carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
$product_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
$carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
$product_value[$k] = (int) ($temp - self::$baseFull * $carry);
}
$product_value[$k] = $carry;
@ -1243,16 +1249,16 @@ class Math_BigInteger
* See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
* {@link http://math.libtomcrypt.com/files/tommath.pdf#page=120 MPM 5.2.3}.
*
* @param Array $x_value
* @param Array $y_value
* @return Array
* @param array $x_value
* @param array $y_value
* @return array
* @access private
*/
function _karatsuba($x_value, $y_value)
{
$m = min(count($x_value) >> 1, count($y_value) >> 1);
if ($m < MATH_BIGINTEGER_KARATSUBA_CUTOFF) {
if ($m < self::KARATSUBA_CUTOFF) {
return $this->_regularMultiply($x_value, $y_value);
}
@ -1266,29 +1272,29 @@ class Math_BigInteger
$z1 = $this->_add($x1, false, $x0, false);
$temp = $this->_add($y1, false, $y0, false);
$z1 = $this->_karatsuba($z1[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_VALUE]);
$z1 = $this->_karatsuba($z1[self::VALUE], $temp[self::VALUE]);
$temp = $this->_add($z2, false, $z0, false);
$z1 = $this->_subtract($z1, false, $temp[MATH_BIGINTEGER_VALUE], false);
$z1 = $this->_subtract($z1, false, $temp[self::VALUE], false);
$z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
$z1[MATH_BIGINTEGER_VALUE] = array_merge(array_fill(0, $m, 0), $z1[MATH_BIGINTEGER_VALUE]);
$z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]);
$xy = $this->_add($z2, false, $z1[MATH_BIGINTEGER_VALUE], $z1[MATH_BIGINTEGER_SIGN]);
$xy = $this->_add($xy[MATH_BIGINTEGER_VALUE], $xy[MATH_BIGINTEGER_SIGN], $z0, false);
$xy = $this->_add($z2, false, $z1[self::VALUE], $z1[self::SIGN]);
$xy = $this->_add($xy[self::VALUE], $xy[self::SIGN], $z0, false);
return $xy[MATH_BIGINTEGER_VALUE];
return $xy[self::VALUE];
}
/**
* Performs squaring
*
* @param Array $x
* @return Array
* @param array $x
* @return array
* @access private
*/
function _square($x = false)
{
return count($x) < 2 * MATH_BIGINTEGER_KARATSUBA_CUTOFF ?
return count($x) < 2 * self::KARATSUBA_CUTOFF ?
$this->_trim($this->_baseSquare($x)) :
$this->_trim($this->_karatsubaSquare($x));
}
@ -1300,13 +1306,13 @@ class Math_BigInteger
* {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} /
* {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information.
*
* @param Array $value
* @return Array
* @param array $value
* @return array
* @access private
*/
function _baseSquare($value)
{
if ( empty($value) ) {
if (empty($value)) {
return array();
}
$square_value = $this->_array_repeat(0, 2 * count($value));
@ -1315,14 +1321,14 @@ class Math_BigInteger
$i2 = $i << 1;
$temp = $square_value[$i2] + $value[$i] * $value[$i];
$carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
$square_value[$i2] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
$carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
$square_value[$i2] = (int) ($temp - self::$baseFull * $carry);
// note how we start from $i+1 instead of 0 as we do in multiplication.
for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; ++$j, ++$k) {
$temp = $square_value[$k] + 2 * $value[$j] * $value[$i] + $carry;
$carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
$square_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
$carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
$square_value[$k] = (int) ($temp - self::$baseFull * $carry);
}
// the following line can yield values larger 2**15. at this point, PHP should switch
@ -1339,15 +1345,15 @@ class Math_BigInteger
* See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
* {@link http://math.libtomcrypt.com/files/tommath.pdf#page=151 MPM 5.3.4}.
*
* @param Array $value
* @return Array
* @param array $value
* @return array
* @access private
*/
function _karatsubaSquare($value)
{
$m = count($value) >> 1;
if ($m < MATH_BIGINTEGER_KARATSUBA_CUTOFF) {
if ($m < self::KARATSUBA_CUTOFF) {
return $this->_baseSquare($value);
}
@ -1358,17 +1364,17 @@ class Math_BigInteger
$z0 = $this->_karatsubaSquare($x0);
$z1 = $this->_add($x1, false, $x0, false);
$z1 = $this->_karatsubaSquare($z1[MATH_BIGINTEGER_VALUE]);
$z1 = $this->_karatsubaSquare($z1[self::VALUE]);
$temp = $this->_add($z2, false, $z0, false);
$z1 = $this->_subtract($z1, false, $temp[MATH_BIGINTEGER_VALUE], false);
$z1 = $this->_subtract($z1, false, $temp[self::VALUE], false);
$z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
$z1[MATH_BIGINTEGER_VALUE] = array_merge(array_fill(0, $m, 0), $z1[MATH_BIGINTEGER_VALUE]);
$z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]);
$xx = $this->_add($z2, false, $z1[MATH_BIGINTEGER_VALUE], $z1[MATH_BIGINTEGER_SIGN]);
$xx = $this->_add($xx[MATH_BIGINTEGER_VALUE], $xx[MATH_BIGINTEGER_SIGN], $z0, false);
$xx = $this->_add($z2, false, $z1[self::VALUE], $z1[self::SIGN]);
$xx = $this->_add($xx[self::VALUE], $xx[self::SIGN], $z0, false);
return $xx[MATH_BIGINTEGER_VALUE];
return $xx[self::VALUE];
}
/**
@ -1382,10 +1388,8 @@ class Math_BigInteger
* Here's an example:
* <code>
* <?php
* include 'Math/BigInteger.php';
*
* $a = new Math_BigInteger('10');
* $b = new Math_BigInteger('20');
* $a = new \phpseclib\Math\BigInteger('10');
* $b = new \phpseclib\Math\BigInteger('20');
*
* list($quotient, $remainder) = $a->divide($b);
*
@ -1395,17 +1399,17 @@ class Math_BigInteger
* ?>
* </code>
*
* @param Math_BigInteger $y
* @return Array
* @param \phpseclib\Math\BigInteger $y
* @return array
* @access public
* @internal This function is based off of {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}.
*/
function divide($y)
{
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
$quotient = new Math_BigInteger();
$remainder = new Math_BigInteger();
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
$quotient = new static();
$remainder = new static();
list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value);
@ -1414,9 +1418,9 @@ class Math_BigInteger
}
return array($this->_normalize($quotient), $this->_normalize($remainder));
case MATH_BIGINTEGER_MODE_BCMATH:
$quotient = new Math_BigInteger();
$remainder = new Math_BigInteger();
case self::MODE_BCMATH:
$quotient = new static();
$remainder = new static();
$quotient->value = bcdiv($this->value, $y->value, 0);
$remainder->value = bcmod($this->value, $y->value);
@ -1430,8 +1434,8 @@ class Math_BigInteger
if (count($y->value) == 1) {
list($q, $r) = $this->_divide_digit($this->value, $y->value[0]);
$quotient = new Math_BigInteger();
$remainder = new Math_BigInteger();
$quotient = new static();
$remainder = new static();
$quotient->value = $q;
$remainder->value = array($r);
$quotient->is_negative = $this->is_negative != $y->is_negative;
@ -1439,8 +1443,8 @@ class Math_BigInteger
}
static $zero;
if ( !isset($zero) ) {
$zero = new Math_BigInteger();
if (!isset($zero)) {
$zero = new static();
}
$x = $this->copy();
@ -1453,24 +1457,24 @@ class Math_BigInteger
$diff = $x->compare($y);
if ( !$diff ) {
$temp = new Math_BigInteger();
if (!$diff) {
$temp = new static();
$temp->value = array(1);
$temp->is_negative = $x_sign != $y_sign;
return array($this->_normalize($temp), $this->_normalize(new Math_BigInteger()));
return array($this->_normalize($temp), $this->_normalize(new static()));
}
if ( $diff < 0 ) {
if ($diff < 0) {
// if $x is negative, "add" $y.
if ( $x_sign ) {
if ($x_sign) {
$x = $y->subtract($x);
}
return array($this->_normalize(new Math_BigInteger()), $this->_normalize($x));
return array($this->_normalize(new static()), $this->_normalize($x));
}
// normalize $x and $y as described in HAC 14.23 / 14.24
$msb = $y->value[count($y->value) - 1];
for ($shift = 0; !($msb & MATH_BIGINTEGER_MSB); ++$shift) {
for ($shift = 0; !($msb & self::$msb); ++$shift) {
$msb <<= 1;
}
$x->_lshift($shift);
@ -1480,15 +1484,15 @@ class Math_BigInteger
$x_max = count($x->value) - 1;
$y_max = count($y->value) - 1;
$quotient = new Math_BigInteger();
$quotient = new static();
$quotient_value = &$quotient->value;
$quotient_value = $this->_array_repeat(0, $x_max - $y_max + 1);
static $temp, $lhs, $rhs;
if (!isset($temp)) {
$temp = new Math_BigInteger();
$lhs = new Math_BigInteger();
$rhs = new Math_BigInteger();
$temp = new static();
$lhs = new static();
$rhs = new static();
}
$temp_value = &$temp->value;
$rhs_value = &$rhs->value;
@ -1496,7 +1500,7 @@ class Math_BigInteger
// $temp = $y << ($x_max - $y_max-1) in base 2**26
$temp_value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y_value);
while ( $x->compare($temp) >= 0 ) {
while ($x->compare($temp) >= 0) {
// calculate the "common residue"
++$quotient_value[$x_max - $y_max];
$x = $x->subtract($temp);
@ -1512,15 +1516,15 @@ class Math_BigInteger
);
$y_window = array(
$y_value[$y_max],
( $y_max > 0 ) ? $y_value[$y_max - 1] : 0
($y_max > 0) ? $y_value[$y_max - 1] : 0
);
$q_index = $i - $y_max - 1;
if ($x_window[0] == $y_window[0]) {
$quotient_value[$q_index] = MATH_BIGINTEGER_MAX_DIGIT;
$quotient_value[$q_index] = self::$maxDigit;
} else {
$quotient_value[$q_index] = $this->_safe_divide(
$x_window[0] * MATH_BIGINTEGER_BASE_FULL + $x_window[1],
$x_window[0] * self::$baseFull + $x_window[1],
$y_window[0]
);
}
@ -1532,7 +1536,7 @@ class Math_BigInteger
$rhs_value = array($x_window[2], $x_window[1], $x_window[0]);
while ( $lhs->compare($rhs) > 0 ) {
while ($lhs->compare($rhs) > 0) {
--$quotient_value[$q_index];
$lhs->value = array($quotient_value[$q_index]);
@ -1563,7 +1567,7 @@ class Math_BigInteger
$quotient->is_negative = $x_sign != $y_sign;
// calculate the "common residue", if appropriate
if ( $x_sign ) {
if ($x_sign) {
$y->_rshift($shift);
$x = $y->subtract($x);
}
@ -1576,9 +1580,9 @@ class Math_BigInteger
*
* abc / x = a00 / x + b0 / x + c / x
*
* @param Array $dividend
* @param Array $divisor
* @return Array
* @param array $dividend
* @param array $divisor
* @return array
* @access private
*/
function _divide_digit($dividend, $divisor)
@ -1587,7 +1591,7 @@ class Math_BigInteger
$result = array();
for ($i = count($dividend) - 1; $i >= 0; --$i) {
$temp = MATH_BIGINTEGER_BASE_FULL * $carry + $dividend[$i];
$temp = self::$baseFull * $carry + $dividend[$i];
$result[$i] = $this->_safe_divide($temp, $divisor);
$carry = (int) ($temp - $divisor * $result[$i]);
}
@ -1601,11 +1605,9 @@ class Math_BigInteger
* Here's an example:
* <code>
* <?php
* include 'Math/BigInteger.php';
*
* $a = new Math_BigInteger('10');
* $b = new Math_BigInteger('20');
* $c = new Math_BigInteger('30');
* $a = new \phpseclib\Math\BigInteger('10');
* $b = new \phpseclib\Math\BigInteger('20');
* $c = new \phpseclib\Math\BigInteger('30');
*
* $c = $a->modPow($b, $c);
*
@ -1613,9 +1615,9 @@ class Math_BigInteger
* ?>
* </code>
*
* @param Math_BigInteger $e
* @param Math_BigInteger $n
* @return Math_BigInteger
* @param \phpseclib\Math\BigInteger $e
* @param \phpseclib\Math\BigInteger $n
* @return \phpseclib\Math\BigInteger
* @access public
* @internal The most naive approach to modular exponentiation has very unreasonable requirements, and
* and although the approach involving repeated squaring does vastly better, it, too, is impractical
@ -1641,7 +1643,7 @@ class Math_BigInteger
{
$n = $this->bitmask !== false && $this->bitmask->compare($n) < 0 ? $this->bitmask : $n->abs();
if ($e->compare(new Math_BigInteger()) < 0) {
if ($e->compare(new static()) < 0) {
$e = $e->abs();
$temp = $this->modInverse($n);
@ -1652,14 +1654,14 @@ class Math_BigInteger
return $this->_normalize($temp->modPow($e, $n));
}
if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP ) {
$temp = new Math_BigInteger();
if (MATH_BIGINTEGER_MODE == self::MODE_GMP) {
$temp = new static();
$temp->value = gmp_powm($this->value, $e->value, $n->value);
return $this->_normalize($temp);
}
if ($this->compare(new Math_BigInteger()) < 0 || $this->compare($n) > 0) {
if ($this->compare(new static()) < 0 || $this->compare($n) > 0) {
list(, $temp) = $this->divide($n);
return $temp->modPow($e, $n);
}
@ -1675,17 +1677,23 @@ class Math_BigInteger
'publicExponent' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['publicExponent'])), $components['publicExponent'])
);
$RSAPublicKey = pack('Ca*a*a*',
48, $this->_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])),
$components['modulus'], $components['publicExponent']
$RSAPublicKey = pack(
'Ca*a*a*',
48,
$this->_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])),
$components['modulus'],
$components['publicExponent']
);
$rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
$RSAPublicKey = chr(0) . $RSAPublicKey;
$RSAPublicKey = chr(3) . $this->_encodeASN1Length(strlen($RSAPublicKey)) . $RSAPublicKey;
$encapsulated = pack('Ca*a*',
48, $this->_encodeASN1Length(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey
$encapsulated = pack(
'Ca*a*',
48,
$this->_encodeASN1Length(strlen($rsaOID . $RSAPublicKey)),
$rsaOID . $RSAPublicKey
);
$RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
@ -1695,36 +1703,36 @@ class Math_BigInteger
$plaintext = str_pad($this->toBytes(), strlen($n->toBytes(true)) - 1, "\0", STR_PAD_LEFT);
if (openssl_public_encrypt($plaintext, $result, $RSAPublicKey, OPENSSL_NO_PADDING)) {
return new Math_BigInteger($result, 256);
return new static($result, 256);
}
}
if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH ) {
$temp = new Math_BigInteger();
$temp->value = bcpowmod($this->value, $e->value, $n->value, 0);
if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) {
$temp = new static();
$temp->value = bcpowmod($this->value, $e->value, $n->value, 0);
return $this->_normalize($temp);
return $this->_normalize($temp);
}
if ( empty($e->value) ) {
$temp = new Math_BigInteger();
if (empty($e->value)) {
$temp = new static();
$temp->value = array(1);
return $this->_normalize($temp);
}
if ( $e->value == array(1) ) {
if ($e->value == array(1)) {
list(, $temp) = $this->divide($n);
return $this->_normalize($temp);
}
if ( $e->value == array(2) ) {
$temp = new Math_BigInteger();
if ($e->value == array(2)) {
$temp = new static();
$temp->value = $this->_square($this->value);
list(, $temp) = $temp->divide($n);
return $this->_normalize($temp);
}
return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_BARRETT));
return $this->_normalize($this->_slidingWindow($e, $n, self::BARRETT));
// the following code, although not callable, can be run independently of the above code
// although the above code performed better in my benchmarks the following could might
@ -1732,14 +1740,14 @@ class Math_BigInteger
// made uncallable
// is the modulo odd?
if ( $n->value[0] & 1 ) {
return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_MONTGOMERY));
if ($n->value[0] & 1) {
return $this->_normalize($this->_slidingWindow($e, $n, self::MONTGOMERY));
}
// if it's not, it's even
// find the lowest set bit (eg. the max pow of 2 that divides $n)
for ($i = 0; $i < count($n->value); ++$i) {
if ( $n->value[$i] ) {
if ($n->value[$i]) {
$temp = decbin($n->value[$i]);
$j = strlen($temp) - strrpos($temp, '1') - 1;
$j+= 26 * $i;
@ -1750,12 +1758,12 @@ class Math_BigInteger
$mod1 = $n->copy();
$mod1->_rshift($j);
$mod2 = new Math_BigInteger();
$mod2 = new static();
$mod2->value = array(1);
$mod2->_lshift($j);
$part1 = ( $mod1->value != array(1) ) ? $this->_slidingWindow($e, $mod1, MATH_BIGINTEGER_MONTGOMERY) : new Math_BigInteger();
$part2 = $this->_slidingWindow($e, $mod2, MATH_BIGINTEGER_POWEROF2);
$part1 = ($mod1->value != array(1)) ? $this->_slidingWindow($e, $mod1, self::MONTGOMERY) : new static();
$part2 = $this->_slidingWindow($e, $mod2, self::POWEROF2);
$y1 = $mod2->modInverse($mod1);
$y2 = $mod1->modInverse($mod2);
@ -1775,11 +1783,11 @@ class Math_BigInteger
/**
* Performs modular exponentiation.
*
* Alias for Math_BigInteger::modPow()
* Alias for modPow().
*
* @param Math_BigInteger $e
* @param Math_BigInteger $n
* @return Math_BigInteger
* @param \phpseclib\Math\BigInteger $e
* @param \phpseclib\Math\BigInteger $n
* @return \phpseclib\Math\BigInteger
* @access public
*/
function powMod($e, $n)
@ -1795,10 +1803,10 @@ class Math_BigInteger
* however, this function performs a modular reduction after every multiplication and squaring operation.
* As such, this function has the same preconditions that the reductions being used do.
*
* @param Math_BigInteger $e
* @param Math_BigInteger $n
* @param Integer $mode
* @return Math_BigInteger
* @param \phpseclib\Math\BigInteger $e
* @param \phpseclib\Math\BigInteger $n
* @param int $mode
* @return \phpseclib\Math\BigInteger
* @access private
*/
function _slidingWindow($e, $n, $mode)
@ -1810,14 +1818,15 @@ class Math_BigInteger
$e_length = count($e_value) - 1;
$e_bits = decbin($e_value[$e_length]);
for ($i = $e_length - 1; $i >= 0; --$i) {
$e_bits.= str_pad(decbin($e_value[$i]), MATH_BIGINTEGER_BASE, '0', STR_PAD_LEFT);
$e_bits.= str_pad(decbin($e_value[$i]), self::$base, '0', STR_PAD_LEFT);
}
$e_length = strlen($e_bits);
// calculate the appropriate window size.
// $window_size == 3 if $window_ranges is between 25 and 81, for example.
for ($i = 0, $window_size = 1; $e_length > $window_ranges[$i] && $i < count($window_ranges); ++$window_size, ++$i);
for ($i = 0, $window_size = 1; $i < count($window_ranges) && $e_length > $window_ranges[$i]; ++$window_size, ++$i) {
}
$n_value = $n->value;
@ -1837,28 +1846,29 @@ class Math_BigInteger
$result = array(1);
$result = $this->_prepareReduce($result, $n_value, $mode);
for ($i = 0; $i < $e_length; ) {
if ( !$e_bits[$i] ) {
for ($i = 0; $i < $e_length;) {
if (!$e_bits[$i]) {
$result = $this->_squareReduce($result, $n_value, $mode);
++$i;
} else {
for ($j = $window_size - 1; $j > 0; --$j) {
if ( !empty($e_bits[$i + $j]) ) {
if (!empty($e_bits[$i + $j])) {
break;
}
}
for ($k = 0; $k <= $j; ++$k) {// eg. the length of substr($e_bits, $i, $j+1)
// eg. the length of substr($e_bits, $i, $j + 1)
for ($k = 0; $k <= $j; ++$k) {
$result = $this->_squareReduce($result, $n_value, $mode);
}
$result = $this->_multiplyReduce($result, $powers[bindec(substr($e_bits, $i, $j + 1))], $n_value, $mode);
$i+=$j + 1;
$i += $j + 1;
}
}
$temp = new Math_BigInteger();
$temp = new static();
$temp->value = $this->_reduce($result, $n_value, $mode);
return $temp;
@ -1869,34 +1879,34 @@ class Math_BigInteger
*
* For most $modes this will return the remainder.
*
* @see _slidingWindow()
* @see self::_slidingWindow()
* @access private
* @param Array $x
* @param Array $n
* @param Integer $mode
* @return Array
* @param array $x
* @param array $n
* @param int $mode
* @return array
*/
function _reduce($x, $n, $mode)
{
switch ($mode) {
case MATH_BIGINTEGER_MONTGOMERY:
case self::MONTGOMERY:
return $this->_montgomery($x, $n);
case MATH_BIGINTEGER_BARRETT:
case self::BARRETT:
return $this->_barrett($x, $n);
case MATH_BIGINTEGER_POWEROF2:
$lhs = new Math_BigInteger();
case self::POWEROF2:
$lhs = new static();
$lhs->value = $x;
$rhs = new Math_BigInteger();
$rhs = new static();
$rhs->value = $n;
return $x->_mod2($n);
case MATH_BIGINTEGER_CLASSIC:
$lhs = new Math_BigInteger();
case self::CLASSIC:
$lhs = new static();
$lhs->value = $x;
$rhs = new Math_BigInteger();
$rhs = new static();
$rhs->value = $n;
list(, $temp) = $lhs->divide($rhs);
return $temp->value;
case MATH_BIGINTEGER_NONE:
case self::NONE:
return $x;
default:
// an invalid $mode was provided
@ -1906,16 +1916,16 @@ class Math_BigInteger
/**
* Modular reduction preperation
*
* @see _slidingWindow()
* @see self::_slidingWindow()
* @access private
* @param Array $x
* @param Array $n
* @param Integer $mode
* @return Array
* @param array $x
* @param array $n
* @param int $mode
* @return array
*/
function _prepareReduce($x, $n, $mode)
{
if ($mode == MATH_BIGINTEGER_MONTGOMERY) {
if ($mode == self::MONTGOMERY) {
return $this->_prepMontgomery($x, $n);
}
return $this->_reduce($x, $n, $mode);
@ -1924,36 +1934,36 @@ class Math_BigInteger
/**
* Modular multiply
*
* @see _slidingWindow()
* @see self::_slidingWindow()
* @access private
* @param Array $x
* @param Array $y
* @param Array $n
* @param Integer $mode
* @return Array
* @param array $x
* @param array $y
* @param array $n
* @param int $mode
* @return array
*/
function _multiplyReduce($x, $y, $n, $mode)
{
if ($mode == MATH_BIGINTEGER_MONTGOMERY) {
if ($mode == self::MONTGOMERY) {
return $this->_montgomeryMultiply($x, $y, $n);
}
$temp = $this->_multiply($x, false, $y, false);
return $this->_reduce($temp[MATH_BIGINTEGER_VALUE], $n, $mode);
return $this->_reduce($temp[self::VALUE], $n, $mode);
}
/**
* Modular square
*
* @see _slidingWindow()
* @see self::_slidingWindow()
* @access private
* @param Array $x
* @param Array $n
* @param Integer $mode
* @return Array
* @param array $x
* @param array $n
* @param int $mode
* @return array
*/
function _squareReduce($x, $n, $mode)
{
if ($mode == MATH_BIGINTEGER_MONTGOMERY) {
if ($mode == self::MONTGOMERY) {
return $this->_montgomeryMultiply($x, $x, $n);
}
return $this->_reduce($this->_square($x), $n, $mode);
@ -1965,14 +1975,14 @@ class Math_BigInteger
* Calculates $x%$n, where $n = 2**$e, for some $e. Since this is basically the same as doing $x & ($n-1),
* we'll just use this function as a wrapper for doing that.
*
* @see _slidingWindow()
* @see self::_slidingWindow()
* @access private
* @param Math_BigInteger
* @return Math_BigInteger
* @param \phpseclib\Math\BigInteger
* @return \phpseclib\Math\BigInteger
*/
function _mod2($n)
{
$temp = new Math_BigInteger();
$temp = new static();
$temp->value = array(1);
return $this->bitwise_and($n->subtract($temp));
}
@ -1995,25 +2005,25 @@ class Math_BigInteger
* (x >> 1) + (x >> 1) != x / 2 + x / 2. If x is even, they're the same, but if x is odd, they're not. See the in-line
* comments for details.
*
* @see _slidingWindow()
* @see self::_slidingWindow()
* @access private
* @param Array $n
* @param Array $m
* @return Array
* @param array $n
* @param array $m
* @return array
*/
function _barrett($n, $m)
{
static $cache = array(
MATH_BIGINTEGER_VARIABLE => array(),
MATH_BIGINTEGER_DATA => array()
self::VARIABLE => array(),
self::DATA => array()
);
$m_length = count($m);
// if ($this->_compare($n, $this->_square($m)) >= 0) {
if (count($n) > 2 * $m_length) {
$lhs = new Math_BigInteger();
$rhs = new Math_BigInteger();
$lhs = new static();
$rhs = new static();
$lhs->value = $n;
$rhs->value = $m;
list(, $temp) = $lhs->divide($rhs);
@ -2027,27 +2037,27 @@ class Math_BigInteger
// n = 2 * m.length
if ( ($key = array_search($m, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
$key = count($cache[MATH_BIGINTEGER_VARIABLE]);
$cache[MATH_BIGINTEGER_VARIABLE][] = $m;
if (($key = array_search($m, $cache[self::VARIABLE])) === false) {
$key = count($cache[self::VARIABLE]);
$cache[self::VARIABLE][] = $m;
$lhs = new Math_BigInteger();
$lhs = new static();
$lhs_value = &$lhs->value;
$lhs_value = $this->_array_repeat(0, $m_length + ($m_length >> 1));
$lhs_value[] = 1;
$rhs = new Math_BigInteger();
$rhs = new static();
$rhs->value = $m;
list($u, $m1) = $lhs->divide($rhs);
$u = $u->value;
$m1 = $m1->value;
$cache[MATH_BIGINTEGER_DATA][] = array(
$cache[self::DATA][] = array(
'u' => $u, // m.length >> 1 (technically (m.length >> 1) + 1)
'm1'=> $m1 // m.length
);
} else {
extract($cache[MATH_BIGINTEGER_DATA][$key]);
extract($cache[self::DATA][$key]);
}
$cutoff = $m_length + ($m_length >> 1);
@ -2055,20 +2065,20 @@ class Math_BigInteger
$msd = array_slice($n, $cutoff); // m.length >> 1
$lsd = $this->_trim($lsd);
$temp = $this->_multiply($msd, false, $m1, false);
$n = $this->_add($lsd, false, $temp[MATH_BIGINTEGER_VALUE], false); // m.length + (m.length >> 1) + 1
$n = $this->_add($lsd, false, $temp[self::VALUE], false); // m.length + (m.length >> 1) + 1
if ($m_length & 1) {
return $this->_regularBarrett($n[MATH_BIGINTEGER_VALUE], $m);
return $this->_regularBarrett($n[self::VALUE], $m);
}
// (m.length + (m.length >> 1) + 1) - (m.length - 1) == (m.length >> 1) + 2
$temp = array_slice($n[MATH_BIGINTEGER_VALUE], $m_length - 1);
$temp = array_slice($n[self::VALUE], $m_length - 1);
// if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2
// if odd: ((m.length >> 1) + 2) + (m.length >> 1) == (m.length - 1) + 2 == m.length + 1
$temp = $this->_multiply($temp, false, $u, false);
// if even: (m.length + 2) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) + 1
// if odd: (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1)
$temp = array_slice($temp[MATH_BIGINTEGER_VALUE], ($m_length >> 1) + 1);
$temp = array_slice($temp[self::VALUE], ($m_length >> 1) + 1);
// if even: (m.length - (m.length >> 1) + 1) + m.length = 2 * m.length - (m.length >> 1) + 1
// if odd: (m.length - (m.length >> 1)) + m.length = 2 * m.length - (m.length >> 1)
$temp = $this->_multiply($temp, false, $m, false);
@ -2077,64 +2087,64 @@ class Math_BigInteger
// number from a m.length + (m.length >> 1) + 1 digit number. ie. there'd be an extra digit and the while loop
// following this comment would loop a lot (hence our calling _regularBarrett() in that situation).
$result = $this->_subtract($n[MATH_BIGINTEGER_VALUE], false, $temp[MATH_BIGINTEGER_VALUE], false);
$result = $this->_subtract($n[self::VALUE], false, $temp[self::VALUE], false);
while ($this->_compare($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $m, false) >= 0) {
$result = $this->_subtract($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $m, false);
while ($this->_compare($result[self::VALUE], $result[self::SIGN], $m, false) >= 0) {
$result = $this->_subtract($result[self::VALUE], $result[self::SIGN], $m, false);
}
return $result[MATH_BIGINTEGER_VALUE];
return $result[self::VALUE];
}
/**
* (Regular) Barrett Modular Reduction
*
* For numbers with more than four digits Math_BigInteger::_barrett() is faster. The difference between that and this
* For numbers with more than four digits BigInteger::_barrett() is faster. The difference between that and this
* is that this function does not fold the denominator into a smaller form.
*
* @see _slidingWindow()
* @see self::_slidingWindow()
* @access private
* @param Array $x
* @param Array $n
* @return Array
* @param array $x
* @param array $n
* @return array
*/
function _regularBarrett($x, $n)
{
static $cache = array(
MATH_BIGINTEGER_VARIABLE => array(),
MATH_BIGINTEGER_DATA => array()
self::VARIABLE => array(),
self::DATA => array()
);
$n_length = count($n);
if (count($x) > 2 * $n_length) {
$lhs = new Math_BigInteger();
$rhs = new Math_BigInteger();
$lhs = new static();
$rhs = new static();
$lhs->value = $x;
$rhs->value = $n;
list(, $temp) = $lhs->divide($rhs);
return $temp->value;
}
if ( ($key = array_search($n, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
$key = count($cache[MATH_BIGINTEGER_VARIABLE]);
$cache[MATH_BIGINTEGER_VARIABLE][] = $n;
$lhs = new Math_BigInteger();
if (($key = array_search($n, $cache[self::VARIABLE])) === false) {
$key = count($cache[self::VARIABLE]);
$cache[self::VARIABLE][] = $n;
$lhs = new static();
$lhs_value = &$lhs->value;
$lhs_value = $this->_array_repeat(0, 2 * $n_length);
$lhs_value[] = 1;
$rhs = new Math_BigInteger();
$rhs = new static();
$rhs->value = $n;
list($temp, ) = $lhs->divide($rhs); // m.length
$cache[MATH_BIGINTEGER_DATA][] = $temp->value;
$cache[self::DATA][] = $temp->value;
}
// 2 * m.length - (m.length - 1) = m.length + 1
$temp = array_slice($x, $n_length - 1);
// (m.length + 1) + m.length = 2 * m.length + 1
$temp = $this->_multiply($temp, false, $cache[MATH_BIGINTEGER_DATA][$key], false);
$temp = $this->_multiply($temp, false, $cache[self::DATA][$key], false);
// (2 * m.length + 1) - (m.length - 1) = m.length + 2
$temp = array_slice($temp[MATH_BIGINTEGER_VALUE], $n_length + 1);
$temp = array_slice($temp[self::VALUE], $n_length + 1);
// m.length + 1
$result = array_slice($x, 0, $n_length + 1);
@ -2142,20 +2152,20 @@ class Math_BigInteger
$temp = $this->_multiplyLower($temp, false, $n, false, $n_length + 1);
// $temp == array_slice($temp->_multiply($temp, false, $n, false)->value, 0, $n_length + 1)
if ($this->_compare($result, false, $temp[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_SIGN]) < 0) {
if ($this->_compare($result, false, $temp[self::VALUE], $temp[self::SIGN]) < 0) {
$corrector_value = $this->_array_repeat(0, $n_length + 1);
$corrector_value[count($corrector_value)] = 1;
$result = $this->_add($result, false, $corrector_value, false);
$result = $result[MATH_BIGINTEGER_VALUE];
$result = $result[self::VALUE];
}
// at this point, we're subtracting a number with m.length + 1 digits from another number with m.length + 1 digits
$result = $this->_subtract($result, false, $temp[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_SIGN]);
while ($this->_compare($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $n, false) > 0) {
$result = $this->_subtract($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $n, false);
$result = $this->_subtract($result, false, $temp[self::VALUE], $temp[self::SIGN]);
while ($this->_compare($result[self::VALUE], $result[self::SIGN], $n, false) > 0) {
$result = $this->_subtract($result[self::VALUE], $result[self::SIGN], $n, false);
}
return $result[MATH_BIGINTEGER_VALUE];
return $result[self::VALUE];
}
/**
@ -2163,13 +2173,13 @@ class Math_BigInteger
*
* If you're going to be doing array_slice($product->value, 0, $stop), some cycles can be saved.
*
* @see _regularBarrett()
* @param Array $x_value
* @param Boolean $x_negative
* @param Array $y_value
* @param Boolean $y_negative
* @param Integer $stop
* @return Array
* @see self::_regularBarrett()
* @param array $x_value
* @param bool $x_negative
* @param array $y_value
* @param bool $y_negative
* @param int $stop
* @return array
* @access private
*/
function _multiplyLower($x_value, $x_negative, $y_value, $y_negative, $stop)
@ -2177,14 +2187,14 @@ class Math_BigInteger
$x_length = count($x_value);
$y_length = count($y_value);
if ( !$x_length || !$y_length ) { // a 0 is being multiplied
if (!$x_length || !$y_length) { // a 0 is being multiplied
return array(
MATH_BIGINTEGER_VALUE => array(),
MATH_BIGINTEGER_SIGN => false
self::VALUE => array(),
self::SIGN => false
);
}
if ( $x_length < $y_length ) {
if ($x_length < $y_length) {
$temp = $x_value;
$x_value = $y_value;
$y_value = $temp;
@ -2205,8 +2215,8 @@ class Math_BigInteger
for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0, $k = $i
$temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
$carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
$product_value[$j] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
$carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
$product_value[$j] = (int) ($temp - self::$baseFull * $carry);
}
if ($j < $stop) {
@ -2221,8 +2231,8 @@ class Math_BigInteger
for ($j = 0, $k = $i; $j < $x_length && $k < $stop; ++$j, ++$k) {
$temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
$carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
$product_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
$carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
$product_value[$k] = (int) ($temp - self::$baseFull * $carry);
}
if ($k < $stop) {
@ -2231,8 +2241,8 @@ class Math_BigInteger
}
return array(
MATH_BIGINTEGER_VALUE => $this->_trim($product_value),
MATH_BIGINTEGER_SIGN => $x_negative != $y_negative
self::VALUE => $this->_trim($product_value),
self::SIGN => $x_negative != $y_negative
);
}
@ -2244,45 +2254,45 @@ class Math_BigInteger
* improved upon (basically, by using the comba method). gcd($n, 2) must be equal to one for this function
* to work correctly.
*
* @see _prepMontgomery()
* @see _slidingWindow()
* @see self::_prepMontgomery()
* @see self::_slidingWindow()
* @access private
* @param Array $x
* @param Array $n
* @return Array
* @param array $x
* @param array $n
* @return array
*/
function _montgomery($x, $n)
{
static $cache = array(
MATH_BIGINTEGER_VARIABLE => array(),
MATH_BIGINTEGER_DATA => array()
self::VARIABLE => array(),
self::DATA => array()
);
if ( ($key = array_search($n, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
$key = count($cache[MATH_BIGINTEGER_VARIABLE]);
$cache[MATH_BIGINTEGER_VARIABLE][] = $x;
$cache[MATH_BIGINTEGER_DATA][] = $this->_modInverse67108864($n);
if (($key = array_search($n, $cache[self::VARIABLE])) === false) {
$key = count($cache[self::VARIABLE]);
$cache[self::VARIABLE][] = $x;
$cache[self::DATA][] = $this->_modInverse67108864($n);
}
$k = count($n);
$result = array(MATH_BIGINTEGER_VALUE => $x);
$result = array(self::VALUE => $x);
for ($i = 0; $i < $k; ++$i) {
$temp = $result[MATH_BIGINTEGER_VALUE][$i] * $cache[MATH_BIGINTEGER_DATA][$key];
$temp = $temp - MATH_BIGINTEGER_BASE_FULL * (MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31));
$temp = $result[self::VALUE][$i] * $cache[self::DATA][$key];
$temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31));
$temp = $this->_regularMultiply(array($temp), $n);
$temp = array_merge($this->_array_repeat(0, $i), $temp);
$result = $this->_add($result[MATH_BIGINTEGER_VALUE], false, $temp, false);
$result = $this->_add($result[self::VALUE], false, $temp, false);
}
$result[MATH_BIGINTEGER_VALUE] = array_slice($result[MATH_BIGINTEGER_VALUE], $k);
$result[self::VALUE] = array_slice($result[self::VALUE], $k);
if ($this->_compare($result, false, $n, false) >= 0) {
$result = $this->_subtract($result[MATH_BIGINTEGER_VALUE], false, $n, false);
$result = $this->_subtract($result[self::VALUE], false, $n, false);
}
return $result[MATH_BIGINTEGER_VALUE];
return $result[self::VALUE];
}
/**
@ -2291,18 +2301,18 @@ class Math_BigInteger
* Interleaves the montgomery reduction and long multiplication algorithms together as described in
* {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36}
*
* @see _prepMontgomery()
* @see _montgomery()
* @see self::_prepMontgomery()
* @see self::_montgomery()
* @access private
* @param Array $x
* @param Array $y
* @param Array $m
* @return Array
* @param array $x
* @param array $y
* @param array $m
* @return array
*/
function _montgomeryMultiply($x, $y, $m)
{
$temp = $this->_multiply($x, false, $y, false);
return $this->_montgomery($temp[MATH_BIGINTEGER_VALUE], $m);
return $this->_montgomery($temp[self::VALUE], $m);
// the following code, although not callable, can be run independently of the above code
// although the above code performed better in my benchmarks the following could might
@ -2310,51 +2320,51 @@ class Math_BigInteger
// made uncallable
static $cache = array(
MATH_BIGINTEGER_VARIABLE => array(),
MATH_BIGINTEGER_DATA => array()
self::VARIABLE => array(),
self::DATA => array()
);
if ( ($key = array_search($m, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
$key = count($cache[MATH_BIGINTEGER_VARIABLE]);
$cache[MATH_BIGINTEGER_VARIABLE][] = $m;
$cache[MATH_BIGINTEGER_DATA][] = $this->_modInverse67108864($m);
if (($key = array_search($m, $cache[self::VARIABLE])) === false) {
$key = count($cache[self::VARIABLE]);
$cache[self::VARIABLE][] = $m;
$cache[self::DATA][] = $this->_modInverse67108864($m);
}
$n = max(count($x), count($y), count($m));
$x = array_pad($x, $n, 0);
$y = array_pad($y, $n, 0);
$m = array_pad($m, $n, 0);
$a = array(MATH_BIGINTEGER_VALUE => $this->_array_repeat(0, $n + 1));
$a = array(self::VALUE => $this->_array_repeat(0, $n + 1));
for ($i = 0; $i < $n; ++$i) {
$temp = $a[MATH_BIGINTEGER_VALUE][0] + $x[$i] * $y[0];
$temp = $temp - MATH_BIGINTEGER_BASE_FULL * (MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31));
$temp = $temp * $cache[MATH_BIGINTEGER_DATA][$key];
$temp = $temp - MATH_BIGINTEGER_BASE_FULL * (MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31));
$temp = $a[self::VALUE][0] + $x[$i] * $y[0];
$temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31));
$temp = $temp * $cache[self::DATA][$key];
$temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31));
$temp = $this->_add($this->_regularMultiply(array($x[$i]), $y), false, $this->_regularMultiply(array($temp), $m), false);
$a = $this->_add($a[MATH_BIGINTEGER_VALUE], false, $temp[MATH_BIGINTEGER_VALUE], false);
$a[MATH_BIGINTEGER_VALUE] = array_slice($a[MATH_BIGINTEGER_VALUE], 1);
$a = $this->_add($a[self::VALUE], false, $temp[self::VALUE], false);
$a[self::VALUE] = array_slice($a[self::VALUE], 1);
}
if ($this->_compare($a[MATH_BIGINTEGER_VALUE], false, $m, false) >= 0) {
$a = $this->_subtract($a[MATH_BIGINTEGER_VALUE], false, $m, false);
if ($this->_compare($a[self::VALUE], false, $m, false) >= 0) {
$a = $this->_subtract($a[self::VALUE], false, $m, false);
}
return $a[MATH_BIGINTEGER_VALUE];
return $a[self::VALUE];
}
/**
* Prepare a number for use in Montgomery Modular Reductions
*
* @see _montgomery()
* @see _slidingWindow()
* @see self::_montgomery()
* @see self::_slidingWindow()
* @access private
* @param Array $x
* @param Array $n
* @return Array
* @param array $x
* @param array $n
* @return array
*/
function _prepMontgomery($x, $n)
{
$lhs = new Math_BigInteger();
$lhs = new static();
$lhs->value = array_merge($this->_array_repeat(0, count($n)), $x);
$rhs = new Math_BigInteger();
$rhs = new static();
$rhs->value = $n;
list(, $temp) = $lhs->divide($rhs);
@ -2382,10 +2392,10 @@ class Math_BigInteger
*
* Thanks to Pedro Gimeno Fortea for input!
*
* @see _montgomery()
* @see self::_montgomery()
* @access private
* @param Array $x
* @return Integer
* @param array $x
* @return int
*/
function _modInverse67108864($x) // 2**26 == 67,108,864
{
@ -2394,8 +2404,8 @@ class Math_BigInteger
$result = ($result * (2 - $x * $result)) & 0xF; // x**-1 mod 2**4
$result = ($result * (2 - ($x & 0xFF) * $result)) & 0xFF; // x**-1 mod 2**8
$result = ($result * ((2 - ($x & 0xFFFF) * $result) & 0xFFFF)) & 0xFFFF; // x**-1 mod 2**16
$result = fmod($result * (2 - fmod($x * $result, MATH_BIGINTEGER_BASE_FULL)), MATH_BIGINTEGER_BASE_FULL); // x**-1 mod 2**26
return $result & MATH_BIGINTEGER_MAX_DIGIT;
$result = fmod($result * (2 - fmod($x * $result, self::$baseFull)), self::$baseFull); // x**-1 mod 2**26
return $result & self::$maxDigit;
}
/**
@ -2406,10 +2416,8 @@ class Math_BigInteger
* Here's an example:
* <code>
* <?php
* include 'Math/BigInteger.php';
*
* $a = new Math_BigInteger(30);
* $b = new Math_BigInteger(17);
* $a = new \phpseclib\Math\BigInteger(30);
* $b = new \phpseclib\Math\BigInteger(17);
*
* $c = $a->modInverse($b);
* echo $c->toString(); // outputs 4
@ -2422,25 +2430,25 @@ class Math_BigInteger
* ?>
* </code>
*
* @param Math_BigInteger $n
* @return mixed false, if no modular inverse exists, Math_BigInteger, otherwise.
* @param \phpseclib\Math\BigInteger $n
* @return \phpseclib\Math\BigInteger|false
* @access public
* @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=21 HAC 14.64} for more information.
*/
function modInverse($n)
{
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
$temp = new Math_BigInteger();
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
$temp = new static();
$temp->value = gmp_invert($this->value, $n->value);
return ( $temp->value === false ) ? false : $this->_normalize($temp);
return ($temp->value === false) ? false : $this->_normalize($temp);
}
static $zero, $one;
if (!isset($zero)) {
$zero = new Math_BigInteger();
$one = new Math_BigInteger(1);
$zero = new static();
$one = new static(1);
}
// $x mod -$n == $x mod $n.
@ -2468,16 +2476,14 @@ class Math_BigInteger
*
* Say you have 693 and 609. The GCD is 21. Bezout's identity states that there exist integers x and y such that
* 693*x + 609*y == 21. In point of fact, there are actually an infinite number of x and y combinations and which
* combination is returned is dependant upon which mode is in use. See
* combination is returned is dependent upon which mode is in use. See
* {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information.
*
* Here's an example:
* <code>
* <?php
* include 'Math/BigInteger.php';
*
* $a = new Math_BigInteger(693);
* $b = new Math_BigInteger(609);
* $a = new \phpseclib\Math\BigInteger(693);
* $b = new \phpseclib\Math\BigInteger(609);
*
* extract($a->extendedGCD($b));
*
@ -2486,8 +2492,8 @@ class Math_BigInteger
* ?>
* </code>
*
* @param Math_BigInteger $n
* @return Math_BigInteger
* @param \phpseclib\Math\BigInteger $n
* @return \phpseclib\Math\BigInteger
* @access public
* @internal Calculates the GCD using the binary xGCD algorithim described in
* {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=19 HAC 14.61}. As the text above 14.61 notes,
@ -2495,16 +2501,16 @@ class Math_BigInteger
*/
function extendedGCD($n)
{
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
extract(gmp_gcdext($this->value, $n->value));
return array(
'gcd' => $this->_normalize(new Math_BigInteger($g)),
'x' => $this->_normalize(new Math_BigInteger($s)),
'y' => $this->_normalize(new Math_BigInteger($t))
'gcd' => $this->_normalize(new static($g)),
'x' => $this->_normalize(new static($s)),
'y' => $this->_normalize(new static($t))
);
case MATH_BIGINTEGER_MODE_BCMATH:
case self::MODE_BCMATH:
// it might be faster to use the binary xGCD algorithim here, as well, but (1) that algorithim works
// best when the base is a power of 2 and (2) i don't think it'd make much difference, anyway. as is,
// the basic extended euclidean algorithim is what we're using.
@ -2534,18 +2540,18 @@ class Math_BigInteger
}
return array(
'gcd' => $this->_normalize(new Math_BigInteger($u)),
'x' => $this->_normalize(new Math_BigInteger($a)),
'y' => $this->_normalize(new Math_BigInteger($b))
'gcd' => $this->_normalize(new static($u)),
'x' => $this->_normalize(new static($a)),
'y' => $this->_normalize(new static($b))
);
}
$y = $n->copy();
$x = $this->copy();
$g = new Math_BigInteger();
$g = new static();
$g->value = array(1);
while ( !(($x->value[0] & 1)|| ($y->value[0] & 1)) ) {
while (!(($x->value[0] & 1)|| ($y->value[0] & 1))) {
$x->_rshift(1);
$y->_rshift(1);
$g->_lshift(1);
@ -2554,18 +2560,18 @@ class Math_BigInteger
$u = $x->copy();
$v = $y->copy();
$a = new Math_BigInteger();
$b = new Math_BigInteger();
$c = new Math_BigInteger();
$d = new Math_BigInteger();
$a = new static();
$b = new static();
$c = new static();
$d = new static();
$a->value = $d->value = $g->value = array(1);
$b->value = $c->value = array();
while ( !empty($u->value) ) {
while ( !($u->value[0] & 1) ) {
while (!empty($u->value)) {
while (!($u->value[0] & 1)) {
$u->_rshift(1);
if ( (!empty($a->value) && ($a->value[0] & 1)) || (!empty($b->value) && ($b->value[0] & 1)) ) {
if ((!empty($a->value) && ($a->value[0] & 1)) || (!empty($b->value) && ($b->value[0] & 1))) {
$a = $a->add($y);
$b = $b->subtract($x);
}
@ -2573,9 +2579,9 @@ class Math_BigInteger
$b->_rshift(1);
}
while ( !($v->value[0] & 1) ) {
while (!($v->value[0] & 1)) {
$v->_rshift(1);
if ( (!empty($d->value) && ($d->value[0] & 1)) || (!empty($c->value) && ($c->value[0] & 1)) ) {
if ((!empty($d->value) && ($d->value[0] & 1)) || (!empty($c->value) && ($c->value[0] & 1))) {
$c = $c->add($y);
$d = $d->subtract($x);
}
@ -2609,10 +2615,8 @@ class Math_BigInteger
* Here's an example:
* <code>
* <?php
* include 'Math/BigInteger.php';
*
* $a = new Math_BigInteger(693);
* $b = new Math_BigInteger(609);
* $a = new \phpseclib\Math\BigInteger(693);
* $b = new \phpseclib\Math\BigInteger(609);
*
* $gcd = a->extendedGCD($b);
*
@ -2620,8 +2624,8 @@ class Math_BigInteger
* ?>
* </code>
*
* @param Math_BigInteger $n
* @return Math_BigInteger
* @param \phpseclib\Math\BigInteger $n
* @return \phpseclib\Math\BigInteger
* @access public
*/
function gcd($n)
@ -2633,18 +2637,18 @@ class Math_BigInteger
/**
* Absolute value.
*
* @return Math_BigInteger
* @return \phpseclib\Math\BigInteger
* @access public
*/
function abs()
{
$temp = new Math_BigInteger();
$temp = new static();
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
$temp->value = gmp_abs($this->value);
break;
case MATH_BIGINTEGER_MODE_BCMATH:
case self::MODE_BCMATH:
$temp->value = (bccomp($this->value, '0', 0) < 0) ? substr($this->value, 1) : $this->value;
break;
default:
@ -2666,18 +2670,18 @@ class Math_BigInteger
*
* Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y).
*
* @param Math_BigInteger $y
* @return Integer < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
* @param \phpseclib\Math\BigInteger $y
* @return int < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
* @access public
* @see equals()
* @see self::equals()
* @internal Could return $this->subtract($x), but that's not as fast as what we do do.
*/
function compare($y)
{
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
return gmp_cmp($this->value, $y->value);
case MATH_BIGINTEGER_MODE_BCMATH:
case self::MODE_BCMATH:
return bccomp($this->value, $y->value, 0);
}
@ -2687,24 +2691,24 @@ class Math_BigInteger
/**
* Compares two numbers.
*
* @param Array $x_value
* @param Boolean $x_negative
* @param Array $y_value
* @param Boolean $y_negative
* @return Integer
* @see compare()
* @param array $x_value
* @param bool $x_negative
* @param array $y_value
* @param bool $y_negative
* @return int
* @see self::compare()
* @access private
*/
function _compare($x_value, $x_negative, $y_value, $y_negative)
{
if ( $x_negative != $y_negative ) {
return ( !$x_negative && $y_negative ) ? 1 : -1;
if ($x_negative != $y_negative) {
return (!$x_negative && $y_negative) ? 1 : -1;
}
$result = $x_negative ? -1 : 1;
if ( count($x_value) != count($y_value) ) {
return ( count($x_value) > count($y_value) ) ? $result : -$result;
if (count($x_value) != count($y_value)) {
return (count($x_value) > count($y_value)) ? $result : -$result;
}
$size = max(count($x_value), count($y_value));
@ -2713,7 +2717,7 @@ class Math_BigInteger
for ($i = count($x_value) - 1; $i >= 0; --$i) {
if ($x_value[$i] != $y_value[$i]) {
return ( $x_value[$i] > $y_value[$i] ) ? $result : -$result;
return ($x_value[$i] > $y_value[$i]) ? $result : -$result;
}
}
@ -2723,17 +2727,17 @@ class Math_BigInteger
/**
* Tests the equality of two numbers.
*
* If you need to see if one number is greater than or less than another number, use Math_BigInteger::compare()
* If you need to see if one number is greater than or less than another number, use BigInteger::compare()
*
* @param Math_BigInteger $x
* @return Boolean
* @param \phpseclib\Math\BigInteger $x
* @return bool
* @access public
* @see compare()
* @see self::compare()
*/
function equals($x)
{
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
return gmp_cmp($this->value, $x->value) == 0;
default:
return $this->value === $x->value && $this->is_negative == $x->is_negative;
@ -2746,16 +2750,16 @@ class Math_BigInteger
* Some bitwise operations give different results depending on the precision being used. Examples include left
* shift, not, and rotates.
*
* @param Integer $bits
* @param int $bits
* @access public
*/
function setPrecision($bits)
{
$this->precision = $bits;
if ( MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_BCMATH ) {
$this->bitmask = new Math_BigInteger(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xFF), $bits >> 3), 256);
if (MATH_BIGINTEGER_MODE != self::MODE_BCMATH) {
$this->bitmask = new static(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xFF), $bits >> 3), 256);
} else {
$this->bitmask = new Math_BigInteger(bcpow('2', $bits, 0));
$this->bitmask = new static(bcpow('2', $bits, 0));
}
$temp = $this->_normalize($this);
@ -2765,20 +2769,20 @@ class Math_BigInteger
/**
* Logical And
*
* @param Math_BigInteger $x
* @param \phpseclib\Math\BigInteger $x
* @access public
* @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
* @return Math_BigInteger
* @return \phpseclib\Math\BigInteger
*/
function bitwise_and($x)
{
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
$temp = new Math_BigInteger();
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
$temp = new static();
$temp->value = gmp_and($this->value, $x->value);
return $this->_normalize($temp);
case MATH_BIGINTEGER_MODE_BCMATH:
case self::MODE_BCMATH:
$left = $this->toBytes();
$right = $x->toBytes();
@ -2787,7 +2791,7 @@ class Math_BigInteger
$left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
$right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
return $this->_normalize(new Math_BigInteger($left & $right, 256));
return $this->_normalize(new static($left & $right, 256));
}
$result = $this->copy();
@ -2806,20 +2810,20 @@ class Math_BigInteger
/**
* Logical Or
*
* @param Math_BigInteger $x
* @param \phpseclib\Math\BigInteger $x
* @access public
* @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
* @return Math_BigInteger
* @return \phpseclib\Math\BigInteger
*/
function bitwise_or($x)
{
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
$temp = new Math_BigInteger();
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
$temp = new static();
$temp->value = gmp_or($this->value, $x->value);
return $this->_normalize($temp);
case MATH_BIGINTEGER_MODE_BCMATH:
case self::MODE_BCMATH:
$left = $this->toBytes();
$right = $x->toBytes();
@ -2828,7 +2832,7 @@ class Math_BigInteger
$left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
$right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
return $this->_normalize(new Math_BigInteger($left | $right, 256));
return $this->_normalize(new static($left | $right, 256));
}
$length = max(count($this->value), count($x->value));
@ -2846,20 +2850,20 @@ class Math_BigInteger
/**
* Logical Exclusive-Or
*
* @param Math_BigInteger $x
* @param \phpseclib\Math\BigInteger $x
* @access public
* @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
* @return Math_BigInteger
* @return \phpseclib\Math\BigInteger
*/
function bitwise_xor($x)
{
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
$temp = new Math_BigInteger();
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
$temp = new static();
$temp->value = gmp_xor($this->value, $x->value);
return $this->_normalize($temp);
case MATH_BIGINTEGER_MODE_BCMATH:
case self::MODE_BCMATH:
$left = $this->toBytes();
$right = $x->toBytes();
@ -2868,7 +2872,7 @@ class Math_BigInteger
$left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
$right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
return $this->_normalize(new Math_BigInteger($left ^ $right, 256));
return $this->_normalize(new static($left ^ $right, 256));
}
$length = max(count($this->value), count($x->value));
@ -2888,13 +2892,16 @@ class Math_BigInteger
*
* @access public
* @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
* @return Math_BigInteger
* @return \phpseclib\Math\BigInteger
*/
function bitwise_not()
{
// calculuate "not" without regard to $this->precision
// (will always result in a smaller number. ie. ~1 isn't 1111 1110 - it's 0)
$temp = $this->toBytes();
if ($temp == '') {
return '';
}
$pre_msb = decbin(ord($temp[0]));
$temp = ~$temp;
$msb = decbin(ord($temp[0]));
@ -2907,7 +2914,7 @@ class Math_BigInteger
$current_bits = strlen($pre_msb) + 8 * strlen($temp) - 8;
$new_bits = $this->precision - $current_bits;
if ($new_bits <= 0) {
return $this->_normalize(new Math_BigInteger($temp, 256));
return $this->_normalize(new static($temp, 256));
}
// generate as many leading 1's as we need to.
@ -2916,7 +2923,7 @@ class Math_BigInteger
$temp = str_pad($temp, strlen($leading_ones), chr(0), STR_PAD_LEFT);
return $this->_normalize(new Math_BigInteger($leading_ones | $temp, 256));
return $this->_normalize(new static($leading_ones | $temp, 256));
}
/**
@ -2924,17 +2931,17 @@ class Math_BigInteger
*
* Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.
*
* @param Integer $shift
* @return Math_BigInteger
* @param int $shift
* @return \phpseclib\Math\BigInteger
* @access public
* @internal The only version that yields any speed increases is the internal version.
*/
function bitwise_rightShift($shift)
{
$temp = new Math_BigInteger();
$temp = new static();
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
static $two;
if (!isset($two)) {
@ -2944,7 +2951,7 @@ class Math_BigInteger
$temp->value = gmp_div_q($this->value, gmp_pow($two, $shift));
break;
case MATH_BIGINTEGER_MODE_BCMATH:
case self::MODE_BCMATH:
$temp->value = bcdiv($this->value, bcpow('2', $shift, 0), 0);
break;
@ -2962,17 +2969,17 @@ class Math_BigInteger
*
* Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
*
* @param Integer $shift
* @return Math_BigInteger
* @param int $shift
* @return \phpseclib\Math\BigInteger
* @access public
* @internal The only version that yields any speed increases is the internal version.
*/
function bitwise_leftShift($shift)
{
$temp = new Math_BigInteger();
$temp = new static();
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
static $two;
if (!isset($two)) {
@ -2982,7 +2989,7 @@ class Math_BigInteger
$temp->value = gmp_mul($this->value, gmp_pow($two, $shift));
break;
case MATH_BIGINTEGER_MODE_BCMATH:
case self::MODE_BCMATH:
$temp->value = bcmul($this->value, bcpow('2', $shift, 0), 0);
break;
@ -3000,8 +3007,8 @@ class Math_BigInteger
*
* Instead of the top x bits being dropped they're appended to the shifted bit string.
*
* @param Integer $shift
* @return Math_BigInteger
* @param int $shift
* @return \phpseclib\Math\BigInteger
* @access public
*/
function bitwise_leftRotate($shift)
@ -3010,15 +3017,16 @@ class Math_BigInteger
if ($this->precision > 0) {
$precision = $this->precision;
if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH ) {
$mask = $this->bitmask->subtract(new Math_BigInteger(1));
if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) {
$mask = $this->bitmask->subtract(new static(1));
$mask = $mask->toBytes();
} else {
$mask = $this->bitmask->toBytes();
}
} else {
$temp = ord($bits[0]);
for ($i = 0; $temp >> $i; ++$i);
for ($i = 0; $temp >> $i; ++$i) {
}
$precision = 8 * strlen($bits) - 8 + $i;
$mask = chr((1 << ($precision & 0x7)) - 1) . str_repeat(chr(0xFF), $precision >> 3);
}
@ -3033,9 +3041,9 @@ class Math_BigInteger
}
$left = $this->bitwise_leftShift($shift);
$left = $left->bitwise_and(new Math_BigInteger($mask, 256));
$left = $left->bitwise_and(new static($mask, 256));
$right = $this->bitwise_rightShift($precision - $shift);
$result = MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_BCMATH ? $left->bitwise_or($right) : $left->add($right);
$result = MATH_BIGINTEGER_MODE != self::MODE_BCMATH ? $left->bitwise_or($right) : $left->add($right);
return $this->_normalize($result);
}
@ -3044,8 +3052,8 @@ class Math_BigInteger
*
* Instead of the bottom x bits being dropped they're prepended to the shifted bit string.
*
* @param Integer $shift
* @return Math_BigInteger
* @param int $shift
* @return \phpseclib\Math\BigInteger
* @access public
*/
function bitwise_rightRotate($shift)
@ -3053,31 +3061,19 @@ class Math_BigInteger
return $this->bitwise_leftRotate(-$shift);
}
/**
* Set random number generator function
*
* This function is deprecated.
*
* @param String $generator
* @access public
*/
function setRandomGenerator($generator)
{
}
/**
* Generates a random BigInteger
*
* Byte length is equal to $length. Uses crypt_random if it's loaded and mt_rand if it's not.
* Byte length is equal to $length. Uses \phpseclib\Crypt\Random if it's loaded and mt_rand if it's not.
*
* @param Integer $length
* @return Math_BigInteger
* @param int $length
* @return \phpseclib\Math\BigInteger
* @access private
*/
function _random_number_helper($size)
{
if (function_exists('crypt_random_string')) {
$random = crypt_random_string($size);
if (class_exists('\phpseclib\Crypt\Random')) {
$random = Random::string($size);
} else {
$random = '';
@ -3092,7 +3088,7 @@ class Math_BigInteger
}
}
return new Math_BigInteger($random, 256);
return new static($random, 256);
}
/**
@ -3104,11 +3100,11 @@ class Math_BigInteger
* $min->random($max)
* $max->random($min)
*
* @param Math_BigInteger $arg1
* @param optional Math_BigInteger $arg2
* @return Math_BigInteger
* @param \phpseclib\Math\BigInteger $arg1
* @param \phpseclib\Math\BigInteger $arg2
* @return \phpseclib\Math\BigInteger
* @access public
* @internal The API for creating random numbers used to be $a->random($min, $max), where $a was a Math_BigInteger object.
* @internal The API for creating random numbers used to be $a->random($min, $max), where $a was a BigInteger object.
* That method is still supported for BC purposes.
*/
function random($arg1, $arg2 = false)
@ -3129,7 +3125,7 @@ class Math_BigInteger
if (!$compare) {
return $this->_normalize($min);
} else if ($compare < 0) {
} elseif ($compare < 0) {
// if $min is bigger then $max, swap $min and $max
$temp = $max;
$max = $min;
@ -3138,7 +3134,7 @@ class Math_BigInteger
static $one;
if (!isset($one)) {
$one = new Math_BigInteger(1);
$one = new static(1);
}
$max = $max->subtract($min->subtract($one));
@ -3159,7 +3155,7 @@ class Math_BigInteger
http://crypto.stackexchange.com/questions/5708/creating-a-small-number-from-a-cryptographically-secure-random-string
*/
$random_max = new Math_BigInteger(chr(1) . str_repeat("\0", $size), 256);
$random_max = new static(chr(1) . str_repeat("\0", $size), 256);
$random = $this->_random_number_helper($size);
list($max_multiple) = $random_max->divide($max);
@ -3182,13 +3178,13 @@ class Math_BigInteger
/**
* Generate a random prime number.
*
* If there's not a prime within the given range, false will be returned. If more than $timeout seconds have elapsed,
* give up and return false.
* If there's not a prime within the given range, false will be returned.
* If more than $timeout seconds have elapsed, give up and return false.
*
* @param Math_BigInteger $arg1
* @param optional Math_BigInteger $arg2
* @param optional Integer $timeout
* @return Mixed
* @param \phpseclib\Math\BigInteger $arg1
* @param \phpseclib\Math\BigInteger $arg2
* @param int $timeout
* @return Math_BigInteger|false
* @access public
* @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=15 HAC 4.44}.
*/
@ -3210,7 +3206,7 @@ class Math_BigInteger
if (!$compare) {
return $min->isPrime() ? $min : false;
} else if ($compare < 0) {
} elseif ($compare < 0) {
// if $min is bigger then $max, swap $min and $max
$temp = $max;
$max = $min;
@ -3219,8 +3215,8 @@ class Math_BigInteger
static $one, $two;
if (!isset($one)) {
$one = new Math_BigInteger(1);
$two = new Math_BigInteger(2);
$one = new static(1);
$two = new static(2);
}
$start = time();
@ -3228,8 +3224,8 @@ class Math_BigInteger
$x = $this->random($min, $max);
// gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>.
if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP && function_exists('gmp_nextprime') ) {
$p = new Math_BigInteger();
if (MATH_BIGINTEGER_MODE == self::MODE_GMP && extension_loaded('gmp')) {
$p = new static();
$p->value = gmp_nextprime($x->value);
if ($p->compare($max) <= 0) {
@ -3289,16 +3285,16 @@ class Math_BigInteger
*
* If the current number is odd it'll be unchanged. If it's even, one will be added to it.
*
* @see randomPrime()
* @see self::randomPrime()
* @access private
*/
function _make_odd()
{
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
gmp_setbit($this->value, 0);
break;
case MATH_BIGINTEGER_MODE_BCMATH:
case self::MODE_BCMATH:
if ($this->value[strlen($this->value) - 1] % 2 == 0) {
$this->value = bcadd($this->value, '1');
}
@ -3312,11 +3308,11 @@ class Math_BigInteger
* Checks a numer to see if it's prime
*
* Assuming the $t parameter is not set, this function has an error rate of 2**-80. The main motivation for the
* $t parameter is distributability. Math_BigInteger::randomPrime() can be distributed across multiple pageloads
* $t parameter is distributability. BigInteger::randomPrime() can be distributed across multiple pageloads
* on a website instead of just one.
*
* @param optional Math_BigInteger $t
* @return Boolean
* @param \phpseclib\Math\BigInteger $t
* @return bool
* @access public
* @internal Uses the
* {@link http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Miller-Rabin primality test}. See
@ -3346,10 +3342,10 @@ class Math_BigInteger
// ie. gmp_testbit($this, 0)
// ie. isEven() or !isOdd()
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
return gmp_prob_prime($this->value, $t) != 0;
case MATH_BIGINTEGER_MODE_BCMATH:
case self::MODE_BCMATH:
if ($this->value === '2') {
return true;
}
@ -3383,15 +3379,15 @@ class Math_BigInteger
953, 967, 971, 977, 983, 991, 997
);
if ( MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL ) {
if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) {
for ($i = 0; $i < count($primes); ++$i) {
$primes[$i] = new Math_BigInteger($primes[$i]);
$primes[$i] = new static($primes[$i]);
}
}
$zero = new Math_BigInteger();
$one = new Math_BigInteger(1);
$two = new Math_BigInteger(2);
$zero = new static();
$one = new static(1);
$two = new static(2);
}
if ($this->equals($one)) {
@ -3399,7 +3395,7 @@ class Math_BigInteger
}
// see HAC 4.4.1 "Random search for probable primes"
if ( MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL ) {
if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) {
foreach ($primes as $prime) {
list(, $r) = $this->divide($prime);
if ($r->equals($zero)) {
@ -3423,7 +3419,7 @@ class Math_BigInteger
$r = $n_1->copy();
$r_value = $r->value;
// ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s));
if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH ) {
if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) {
$s = 0;
// if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals($one) check earlier
while ($r->value[strlen($r->value) - 1] % 2 == 0) {
@ -3433,7 +3429,8 @@ class Math_BigInteger
} else {
for ($i = 0, $r_length = count($r_value); $i < $r_length; ++$i) {
$temp = ~$r_value[$i] & 0xFFFFFF;
for ($j = 1; ($temp >> $j) & 1; ++$j);
for ($j = 1; ($temp >> $j) & 1; ++$j) {
}
if ($j != 25) {
break;
}
@ -3467,28 +3464,28 @@ class Math_BigInteger
*
* Shifts BigInteger's by $shift bits.
*
* @param Integer $shift
* @param int $shift
* @access private
*/
function _lshift($shift)
{
if ( $shift == 0 ) {
if ($shift == 0) {
return;
}
$num_digits = (int) ($shift / MATH_BIGINTEGER_BASE);
$shift %= MATH_BIGINTEGER_BASE;
$num_digits = (int) ($shift / self::$base);
$shift %= self::$base;
$shift = 1 << $shift;
$carry = 0;
for ($i = 0; $i < count($this->value); ++$i) {
$temp = $this->value[$i] * $shift + $carry;
$carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
$this->value[$i] = (int) ($temp - $carry * MATH_BIGINTEGER_BASE_FULL);
$carry = self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
$this->value[$i] = (int) ($temp - $carry * self::$baseFull);
}
if ( $carry ) {
if ($carry) {
$this->value[count($this->value)] = $carry;
}
@ -3502,7 +3499,7 @@ class Math_BigInteger
*
* Shifts BigInteger's by $shift bits.
*
* @param Integer $shift
* @param int $shift
* @access private
*/
function _rshift($shift)
@ -3511,12 +3508,12 @@ class Math_BigInteger
return;
}
$num_digits = (int) ($shift / MATH_BIGINTEGER_BASE);
$shift %= MATH_BIGINTEGER_BASE;
$carry_shift = MATH_BIGINTEGER_BASE - $shift;
$num_digits = (int) ($shift / self::$base);
$shift %= self::$base;
$carry_shift = self::$base - $shift;
$carry_mask = (1 << $shift) - 1;
if ( $num_digits ) {
if ($num_digits) {
$this->value = array_slice($this->value, $num_digits);
}
@ -3536,9 +3533,9 @@ class Math_BigInteger
*
* Removes leading zeros and truncates (if necessary) to maintain the appropriate precision
*
* @param Math_BigInteger
* @return Math_BigInteger
* @see _trim()
* @param \phpseclib\Math\BigInteger
* @return \phpseclib\Math\BigInteger
* @see self::_trim()
* @access private
*/
function _normalize($result)
@ -3546,14 +3543,14 @@ class Math_BigInteger
$result->precision = $this->precision;
$result->bitmask = $this->bitmask;
switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP:
if (!empty($result->bitmask->value)) {
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
if ($this->bitmask !== false) {
$result->value = gmp_and($result->value, $result->bitmask->value);
}
return $result;
case MATH_BIGINTEGER_MODE_BCMATH:
case self::MODE_BCMATH:
if (!empty($result->bitmask->value)) {
$result->value = bcmod($result->value, $result->bitmask->value);
}
@ -3563,7 +3560,7 @@ class Math_BigInteger
$value = &$result->value;
if ( !count($value) ) {
if (!count($value)) {
return $result;
}
@ -3586,14 +3583,14 @@ class Math_BigInteger
*
* Removes leading zeros
*
* @param Array $value
* @return Math_BigInteger
* @param array $value
* @return \phpseclib\Math\BigInteger
* @access private
*/
function _trim($value)
{
for ($i = count($value) - 1; $i >= 0; --$i) {
if ( $value[$i] ) {
if ($value[$i]) {
break;
}
unset($value[$i]);
@ -3607,7 +3604,7 @@ class Math_BigInteger
*
* @param $input Array
* @param $multiplier mixed
* @return Array
* @return array
* @access private
*/
function _array_repeat($input, $multiplier)
@ -3622,7 +3619,7 @@ class Math_BigInteger
*
* @param $x String
* @param $shift Integer
* @return String
* @return string
* @access private
*/
function _base256_lshift(&$x, $shift)
@ -3651,7 +3648,7 @@ class Math_BigInteger
*
* @param $x String
* @param $shift Integer
* @return String
* @return string
* @access private
*/
function _base256_rshift(&$x, $shift)
@ -3691,8 +3688,8 @@ class Math_BigInteger
/**
* Converts 32-bit integers to bytes.
*
* @param Integer $x
* @return String
* @param int $x
* @return string
* @access private
*/
function _int2bytes($x)
@ -3703,8 +3700,8 @@ class Math_BigInteger
/**
* Converts bytes to 32-bit integers
*
* @param String $x
* @return Integer
* @param string $x
* @return int
* @access private
*/
function _bytes2int($x)
@ -3718,10 +3715,10 @@ class Math_BigInteger
*
* The ability to DER-encode integers is needed to create RSA public keys for use with OpenSSL
*
* @see modPow()
* @see self::modPow()
* @access private
* @param Integer $length
* @return String
* @param int $length
* @return string
*/
function _encodeASN1Length($length)
{
@ -3742,17 +3739,17 @@ class Math_BigInteger
* we'll guarantee that the dividend is divisible by first subtracting the remainder.
*
* @access private
* @param Integer $x
* @param Integer $y
* @return Integer
* @param int $x
* @param int $y
* @return int
*/
function _safe_divide($x, $y)
{
if (MATH_BIGINTEGER_BASE === 26) {
if (self::$base === 26) {
return (int) ($x / $y);
}
// MATH_BIGINTEGER_BASE === 31
// self::$base === 31
return ($x - ($x % $y)) / $y;
}
}

View file

@ -3,94 +3,77 @@
/**
* Pure-PHP implementation of SCP.
*
* PHP versions 4 and 5
* PHP version 5
*
* The API for this library is modeled after the API from PHP's {@link http://php.net/book.ftp FTP extension}.
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Net/SCP.php';
* include 'Net/SSH2.php';
* include 'vendor/autoload.php';
*
* $ssh = new Net_SSH2('www.domain.tld');
* $ssh = new \phpseclib\Net\SSH2('www.domain.tld');
* if (!$ssh->login('username', 'password')) {
* exit('bad login');
* }
* $scp = new Net_SCP($ssh);
* $scp = new \phpseclib\Net\SCP($ssh);
*
* $scp->put('abcd', str_repeat('x', 1024*1024));
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Net
* @package Net_SCP
* @package SCP
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2010 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**#@+
* @access public
* @see Net_SCP::put()
*/
/**
* Reads data from a local file.
*/
define('NET_SCP_LOCAL_FILE', 1);
/**
* Reads data from a string.
*/
define('NET_SCP_STRING', 2);
/**#@-*/
/**#@+
* @access private
* @see Net_SCP::_send()
* @see Net_SCP::_receive()
*/
/**
* SSH1 is being used.
*/
define('NET_SCP_SSH1', 1);
/**
* SSH2 is being used.
*/
define('NET_SCP_SSH2', 2);
/**#@-*/
namespace phpseclib\Net;
/**
* Pure-PHP implementations of SCP.
*
* @package Net_SCP
* @package SCP
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Net_SCP
class SCP
{
/**#@+
* @access public
* @see \phpseclib\Net\SCP::put()
*/
/**
* Reads data from a local file.
*/
const SOURCE_LOCAL_FILE = 1;
/**
* Reads data from a string.
*/
const SOURCE_STRING = 2;
/**#@-*/
/**#@+
* @access private
* @see \phpseclib\Net\SCP::_send()
* @see \phpseclib\Net\SCP::_receive()
*/
/**
* SSH1 is being used.
*/
const MODE_SSH1 = 1;
/**
* SSH2 is being used.
*/
const MODE_SSH2 = 2;
/**#@-*/
/**
* SSH Object
*
* @var Object
* @var object
* @access private
*/
var $ssh;
@ -98,7 +81,7 @@ class Net_SCP
/**
* Packet Size
*
* @var Integer
* @var int
* @access private
*/
var $packet_size;
@ -106,7 +89,7 @@ class Net_SCP
/**
* Mode
*
* @var Integer
* @var int
* @access private
*/
var $mode;
@ -116,55 +99,46 @@ class Net_SCP
*
* Connects to an SSH server
*
* @param String $host
* @param optional Integer $port
* @param optional Integer $timeout
* @return Net_SCP
* @param \phpseclib\Net\SSH1|\phpseclin\Net\SSH2 $ssh
* @return \phpseclib\Net\SCP
* @access public
*/
function Net_SCP($ssh)
function __construct($ssh)
{
if (!is_object($ssh)) {
if ($ssh instanceof SSH2) {
$this->mode = self::MODE_SSH2;
} elseif ($ssh instanceof SSH1) {
$this->packet_size = 50000;
$this->mode = self::MODE_SSH1;
} else {
return;
}
switch (strtolower(get_class($ssh))) {
case 'net_ssh2':
$this->mode = NET_SCP_SSH2;
break;
case 'net_ssh1':
$this->packet_size = 50000;
$this->mode = NET_SCP_SSH1;
break;
default:
return;
}
$this->ssh = $ssh;
}
/**
* Uploads a file to the SCP server.
*
* By default, Net_SCP::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
* So, for example, if you set $data to 'filename.ext' and then do Net_SCP::get(), you will get a file, twelve bytes
* By default, \phpseclib\Net\SCP::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
* So, for example, if you set $data to 'filename.ext' and then do \phpseclib\Net\SCP::get(), you will get a file, twelve bytes
* long, containing 'filename.ext' as its contents.
*
* Setting $mode to NET_SCP_LOCAL_FILE will change the above behavior. With NET_SCP_LOCAL_FILE, $remote_file will
* Setting $mode to self::SOURCE_LOCAL_FILE will change the above behavior. With self::SOURCE_LOCAL_FILE, $remote_file will
* contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
* large $remote_file will be, as well.
*
* Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
* care of that, yourself.
*
* @param String $remote_file
* @param String $data
* @param optional Integer $mode
* @param optional Callable $callback
* @return Boolean
* @param string $remote_file
* @param string $data
* @param int $mode
* @param callable $callback
* @return bool
* @access public
*/
function put($remote_file, $data, $mode = NET_SCP_STRING, $callback = null)
function put($remote_file, $data, $mode = self::SOURCE_STRING, $callback = null)
{
if (!isset($this->ssh)) {
return false;
@ -179,13 +153,13 @@ class Net_SCP
return false;
}
if ($this->mode == NET_SCP_SSH2) {
$this->packet_size = $this->ssh->packet_size_client_to_server[NET_SSH2_CHANNEL_EXEC] - 4;
if ($this->mode == self::MODE_SSH2) {
$this->packet_size = $this->ssh->packet_size_client_to_server[SSH2::CHANNEL_EXEC] - 4;
}
$remote_file = basename($remote_file);
if ($mode == NET_SCP_STRING) {
if ($mode == self::SOURCE_STRING) {
$size = strlen($data);
} else {
if (!is_file($data)) {
@ -209,7 +183,7 @@ class Net_SCP
$sent = 0;
while ($sent < $size) {
$temp = $mode & NET_SCP_STRING ? substr($data, $sent, $this->packet_size) : fread($fp, $this->packet_size);
$temp = $mode & self::SOURCE_STRING ? substr($data, $sent, $this->packet_size) : fread($fp, $this->packet_size);
$this->_send($temp);
$sent+= strlen($temp);
@ -219,7 +193,7 @@ class Net_SCP
}
$this->_close();
if ($mode != NET_SCP_STRING) {
if ($mode != self::SOURCE_STRING) {
fclose($fp);
}
@ -233,9 +207,9 @@ class Net_SCP
* the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the
* operation
*
* @param String $remote_file
* @param optional String $local_file
* @return Mixed
* @param string $remote_file
* @param string $local_file
* @return mixed
* @access public
*/
function get($remote_file, $local_file = false)
@ -291,42 +265,42 @@ class Net_SCP
/**
* Sends a packet to an SSH server
*
* @param String $data
* @param string $data
* @access private
*/
function _send($data)
{
switch ($this->mode) {
case NET_SCP_SSH2:
$this->ssh->_send_channel_packet(NET_SSH2_CHANNEL_EXEC, $data);
case self::MODE_SSH2:
$this->ssh->_send_channel_packet(SSH2::CHANNEL_EXEC, $data);
break;
case NET_SCP_SSH1:
case self::MODE_SSH1:
$data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($data), $data);
$this->ssh->_send_binary_packet($data);
}
}
}
/**
* Receives a packet from an SSH server
*
* @return String
* @return string
* @access private
*/
function _receive()
{
switch ($this->mode) {
case NET_SCP_SSH2:
return $this->ssh->_get_channel_packet(NET_SSH2_CHANNEL_EXEC, true);
case NET_SCP_SSH1:
case self::MODE_SSH2:
return $this->ssh->_get_channel_packet(SSH2::CHANNEL_EXEC, true);
case self::MODE_SSH1:
if (!$this->ssh->bitmap) {
return false;
}
while (true) {
$response = $this->ssh->_get_binary_packet();
switch ($response[NET_SSH1_RESPONSE_TYPE]) {
switch ($response[SSH1::RESPONSE_TYPE]) {
case NET_SSH1_SMSG_STDOUT_DATA:
extract(unpack('Nlength', $response[NET_SSH1_RESPONSE_DATA]));
return $this->ssh->_string_shift($response[NET_SSH1_RESPONSE_DATA], $length);
extract(unpack('Nlength', $response[SSH1::RESPONSE_DATA]));
return $this->ssh->_string_shift($response[SSH1::RESPONSE_DATA], $length);
case NET_SSH1_SMSG_STDERR_DATA:
break;
case NET_SSH1_SMSG_EXITSTATUS:
@ -339,7 +313,7 @@ class Net_SCP
return false;
}
}
}
}
}
/**
@ -350,11 +324,11 @@ class Net_SCP
function _close()
{
switch ($this->mode) {
case NET_SCP_SSH2:
$this->ssh->_close_channel(NET_SSH2_CHANNEL_EXEC, true);
case self::MODE_SSH2:
$this->ssh->_close_channel(SSH2::CHANNEL_EXEC, true);
break;
case NET_SCP_SSH1:
case self::MODE_SSH1:
$this->ssh->disconnect();
}
}
}
}

View file

@ -3,7 +3,7 @@
/**
* Pure-PHP implementation of SFTP.
*
* PHP versions 4 and 5
* PHP version 5
*
* Currently only supports SFTPv2 and v3, which, according to wikipedia.org, "is the most widely used version,
* implemented by the popular OpenSSH SFTP server". If you want SFTPv4/5/6 support, provide me with access
@ -14,9 +14,9 @@
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Net/SFTP.php';
* include 'vendor/autoload.php';
*
* $sftp = new Net_SFTP('www.domain.tld');
* $sftp = new \phpseclib\Net\SFTP('www.domain.tld');
* if (!$sftp->login('username', 'password')) {
* exit('Login Failed');
* }
@ -27,105 +27,69 @@
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Net
* @package Net_SFTP
* @package SFTP
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2009 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Net_SSH2
*/
if (!class_exists('Net_SSH2')) {
include_once 'SSH2.php';
}
/**#@+
* @access public
* @see Net_SFTP::getLog()
*/
/**
* Returns the message numbers
*/
define('NET_SFTP_LOG_SIMPLE', NET_SSH2_LOG_SIMPLE);
/**
* Returns the message content
*/
define('NET_SFTP_LOG_COMPLEX', NET_SSH2_LOG_COMPLEX);
/**
* Outputs the message content in real-time.
*/
define('NET_SFTP_LOG_REALTIME', 3);
/**#@-*/
/**
* SFTP channel constant
*
* Net_SSH2::exec() uses 0 and Net_SSH2::read() / Net_SSH2::write() use 1.
*
* @see Net_SSH2::_send_channel_packet()
* @see Net_SSH2::_get_channel_packet()
* @access private
*/
define('NET_SFTP_CHANNEL', 0x100);
/**#@+
* @access public
* @see Net_SFTP::put()
*/
/**
* Reads data from a local file.
*/
define('NET_SFTP_LOCAL_FILE', 1);
/**
* Reads data from a string.
*/
// this value isn't really used anymore but i'm keeping it reserved for historical reasons
define('NET_SFTP_STRING', 2);
/**
* Resumes an upload
*/
define('NET_SFTP_RESUME', 4);
/**
* Append a local file to an already existing remote file
*/
define('NET_SFTP_RESUME_START', 8);
/**#@-*/
namespace phpseclib\Net;
/**
* Pure-PHP implementations of SFTP.
*
* @package Net_SFTP
* @package SFTP
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Net_SFTP extends Net_SSH2
class SFTP extends SSH2
{
/**
* SFTP channel constant
*
* \phpseclib\Net\SSH2::exec() uses 0 and \phpseclib\Net\SSH2::read() / \phpseclib\Net\SSH2::write() use 1.
*
* @see \phpseclib\Net\SSH2::_send_channel_packet()
* @see \phpseclib\Net\SSH2::_get_channel_packet()
* @access private
*/
const CHANNEL = 0x100;
/**#@+
* @access public
* @see \phpseclib\Net\SFTP::put()
*/
/**
* Reads data from a local file.
*/
const SOURCE_LOCAL_FILE = 1;
/**
* Reads data from a string.
*/
// this value isn't really used anymore but i'm keeping it reserved for historical reasons
const SOURCE_STRING = 2;
/**
* Reads data from callback:
* function callback($length) returns string to proceed, null for EOF
*/
const SOURCE_CALLBACK = 16;
/**
* Resumes an upload
*/
const RESUME = 4;
/**
* Append a local file to an already existing remote file
*/
const RESUME_START = 8;
/**#@-*/
/**
* Packet Types
*
* @see Net_SFTP::Net_SFTP()
* @var Array
* @see self::__construct()
* @var array
* @access private
*/
var $packet_types = array();
@ -133,8 +97,8 @@ class Net_SFTP extends Net_SSH2
/**
* Status Codes
*
* @see Net_SFTP::Net_SFTP()
* @var Array
* @see self::__construct()
* @var array
* @access private
*/
var $status_codes = array();
@ -145,8 +109,8 @@ class Net_SFTP extends Net_SSH2
* The request ID exists in the off chance that a packet is sent out-of-order. Of course, this library doesn't support
* concurrent actions, so it's somewhat academic, here.
*
* @var Integer
* @see Net_SFTP::_send_sftp_packet()
* @var int
* @see self::_send_sftp_packet()
* @access private
*/
var $request_id = false;
@ -157,8 +121,8 @@ class Net_SFTP extends Net_SSH2
* The request ID exists in the off chance that a packet is sent out-of-order. Of course, this library doesn't support
* concurrent actions, so it's somewhat academic, here.
*
* @var Integer
* @see Net_SFTP::_get_sftp_packet()
* @var int
* @see self::_get_sftp_packet()
* @access private
*/
var $packet_type = -1;
@ -166,8 +130,8 @@ class Net_SFTP extends Net_SSH2
/**
* Packet Buffer
*
* @var String
* @see Net_SFTP::_get_sftp_packet()
* @var string
* @see self::_get_sftp_packet()
* @access private
*/
var $packet_buffer = '';
@ -175,8 +139,8 @@ class Net_SFTP extends Net_SSH2
/**
* Extensions supported by the server
*
* @var Array
* @see Net_SFTP::_initChannel()
* @var array
* @see self::_initChannel()
* @access private
*/
var $extensions = array();
@ -184,8 +148,8 @@ class Net_SFTP extends Net_SSH2
/**
* Server SFTP version
*
* @var Integer
* @see Net_SFTP::_initChannel()
* @var int
* @see self::_initChannel()
* @access private
*/
var $version;
@ -193,9 +157,9 @@ class Net_SFTP extends Net_SSH2
/**
* Current working directory
*
* @var String
* @see Net_SFTP::_realpath()
* @see Net_SFTP::chdir()
* @var string
* @see self::_realpath()
* @see self::chdir()
* @access private
*/
var $pwd = false;
@ -203,8 +167,8 @@ class Net_SFTP extends Net_SSH2
/**
* Packet Type Log
*
* @see Net_SFTP::getLog()
* @var Array
* @see self::getLog()
* @var array
* @access private
*/
var $packet_type_log = array();
@ -212,8 +176,8 @@ class Net_SFTP extends Net_SSH2
/**
* Packet Log
*
* @see Net_SFTP::getLog()
* @var Array
* @see self::getLog()
* @var array
* @access private
*/
var $packet_log = array();
@ -221,9 +185,9 @@ class Net_SFTP extends Net_SSH2
/**
* Error information
*
* @see Net_SFTP::getSFTPErrors()
* @see Net_SFTP::getLastSFTPError()
* @var String
* @see self::getSFTPErrors()
* @see self::getLastSFTPError()
* @var string
* @access private
*/
var $sftp_errors = array();
@ -234,10 +198,10 @@ class Net_SFTP extends Net_SSH2
* Rather than always having to open a directory and close it immediately there after to see if a file is a directory
* we'll cache the results.
*
* @see Net_SFTP::_update_stat_cache()
* @see Net_SFTP::_remove_from_stat_cache()
* @see Net_SFTP::_query_stat_cache()
* @var Array
* @see self::_update_stat_cache()
* @see self::_remove_from_stat_cache()
* @see self::_query_stat_cache()
* @var array
* @access private
*/
var $stat_cache = array();
@ -245,9 +209,9 @@ class Net_SFTP extends Net_SSH2
/**
* Max SFTP Packet Size
*
* @see Net_SFTP::Net_SFTP()
* @see Net_SFTP::get()
* @var Array
* @see self::__construct()
* @see self::get()
* @var array
* @access private
*/
var $max_sftp_packet;
@ -255,9 +219,9 @@ class Net_SFTP extends Net_SSH2
/**
* Stat Cache Flag
*
* @see Net_SFTP::disableStatCache()
* @see Net_SFTP::enableStatCache()
* @var Boolean
* @see self::disableStatCache()
* @see self::enableStatCache()
* @var bool
* @access private
*/
var $use_stat_cache = true;
@ -265,9 +229,9 @@ class Net_SFTP extends Net_SSH2
/**
* Sort Options
*
* @see Net_SFTP::_comparator()
* @see Net_SFTP::setListOrder()
* @var Array
* @see self::_comparator()
* @see self::setListOrder()
* @var array
* @access private
*/
var $sortOptions = array();
@ -277,15 +241,15 @@ class Net_SFTP extends Net_SSH2
*
* Connects to an SFTP server
*
* @param String $host
* @param optional Integer $port
* @param optional Integer $timeout
* @return Net_SFTP
* @param string $host
* @param int $port
* @param int $timeout
* @return \phpseclib\Net\SFTP
* @access public
*/
function Net_SFTP($host, $port = 22, $timeout = 10)
function __construct($host, $port = 22, $timeout = 10)
{
parent::Net_SSH2($host, $port, $timeout);
parent::__construct($host, $port, $timeout);
$this->max_sftp_packet = 1 << 15;
@ -361,7 +325,7 @@ class Net_SFTP extends Net_SSH2
31 => 'NET_SFTP_STATUS_NO_MATCHING_BYTE_RANGE_LOCK'
);
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-7.1
// the order, in this case, matters quite a lot - see Net_SFTP::_parseAttributes() to understand why
// the order, in this case, matters quite a lot - see \phpseclib\Net\SFTP::_parseAttributes() to understand why
$this->attributes = array(
0x00000001 => 'NET_SFTP_ATTR_SIZE',
0x00000002 => 'NET_SFTP_ATTR_UIDGID', // defined in SFTPv3, removed in SFTPv4+
@ -375,7 +339,7 @@ class Net_SFTP extends Net_SSH2
);
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3
// the flag definitions change somewhat in SFTPv5+. if SFTPv5+ support is added to this library, maybe name
// the array for that $this->open5_flags and similarily alter the constant names.
// the array for that $this->open5_flags and similarly alter the constant names.
$this->open_flags = array(
0x00000001 => 'NET_SFTP_OPEN_READ',
0x00000002 => 'NET_SFTP_OPEN_WRITE',
@ -385,7 +349,7 @@ class Net_SFTP extends Net_SSH2
0x00000020 => 'NET_SFTP_OPEN_EXCL'
);
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2
// see Net_SFTP::_parseLongname() for an explanation
// see \phpseclib\Net\SFTP::_parseLongname() for an explanation
$this->file_types = array(
1 => 'NET_SFTP_TYPE_REGULAR',
2 => 'NET_SFTP_TYPE_DIRECTORY',
@ -415,9 +379,9 @@ class Net_SFTP extends Net_SSH2
/**
* Login
*
* @param String $username
* @param optional String $password
* @return Boolean
* @param string $username
* @param string $password
* @return bool
* @access public
*/
function login($username)
@ -427,31 +391,46 @@ class Net_SFTP extends Net_SSH2
return false;
}
$this->window_size_server_to_client[NET_SFTP_CHANNEL] = $this->window_size;
$this->window_size_server_to_client[self::CHANNEL] = $this->window_size;
$packet = pack('CNa*N3',
NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', NET_SFTP_CHANNEL, $this->window_size, 0x4000);
$packet = pack(
'CNa*N3',
NET_SSH2_MSG_CHANNEL_OPEN,
strlen('session'),
'session',
self::CHANNEL,
$this->window_size,
0x4000
);
if (!$this->_send_binary_packet($packet)) {
return false;
}
$this->channel_status[NET_SFTP_CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN;
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN;
$response = $this->_get_channel_packet(NET_SFTP_CHANNEL);
$response = $this->_get_channel_packet(self::CHANNEL);
if ($response === false) {
return false;
}
$packet = pack('CNNa*CNa*',
NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SFTP_CHANNEL], strlen('subsystem'), 'subsystem', 1, strlen('sftp'), 'sftp');
$packet = pack(
'CNNa*CNa*',
NET_SSH2_MSG_CHANNEL_REQUEST,
$this->server_channels[self::CHANNEL],
strlen('subsystem'),
'subsystem',
1,
strlen('sftp'),
'sftp'
);
if (!$this->_send_binary_packet($packet)) {
return false;
}
$this->channel_status[NET_SFTP_CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
$response = $this->_get_channel_packet(NET_SFTP_CHANNEL);
$response = $this->_get_channel_packet(self::CHANNEL);
if ($response === false) {
// from PuTTY's psftp.exe
$command = "test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server\n" .
@ -459,21 +438,29 @@ class Net_SFTP extends Net_SSH2
"exec sftp-server";
// we don't do $this->exec($command, false) because exec() operates on a different channel and plus the SSH_MSG_CHANNEL_OPEN that exec() does
// is redundant
$packet = pack('CNNa*CNa*',
NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SFTP_CHANNEL], strlen('exec'), 'exec', 1, strlen($command), $command);
$packet = pack(
'CNNa*CNa*',
NET_SSH2_MSG_CHANNEL_REQUEST,
$this->server_channels[self::CHANNEL],
strlen('exec'),
'exec',
1,
strlen($command),
$command
);
if (!$this->_send_binary_packet($packet)) {
return false;
}
$this->channel_status[NET_SFTP_CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
$response = $this->_get_channel_packet(NET_SFTP_CHANNEL);
$response = $this->_get_channel_packet(self::CHANNEL);
if ($response === false) {
return false;
}
}
$this->channel_status[NET_SFTP_CHANNEL] = NET_SSH2_MSG_CHANNEL_DATA;
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_DATA;
if (!$this->_send_sftp_packet(NET_SFTP_INIT, "\0\0\0\3")) {
return false;
@ -531,7 +518,7 @@ class Net_SFTP extends Net_SSH2
So what do you do if you have a client whose initial SSH_FXP_INIT packet says it implements v3 and
a server whose initial SSH_FXP_VERSION reply says it implements v4 and only v4? If it only implements
v4, the "versions" extension is likely not going to have been sent so version re-negotiation as discussed
in draft-ietf-secsh-filexfer-13 would be quite impossible. As such, what Net_SFTP would do is close the
in draft-ietf-secsh-filexfer-13 would be quite impossible. As such, what \phpseclib\Net\SFTP would do is close the
channel and reopen it with a new and updated SSH_FXP_INIT packet.
*/
switch ($this->version) {
@ -582,7 +569,7 @@ class Net_SFTP extends Net_SSH2
/**
* Returns the current directory name
*
* @return Mixed
* @return mixed
* @access public
*/
function pwd()
@ -593,8 +580,8 @@ class Net_SFTP extends Net_SSH2
/**
* Logs errors
*
* @param String $response
* @param optional Integer $status
* @param string $response
* @param int $status
* @access public
*/
function _logError($response, $status = -1)
@ -613,15 +600,30 @@ class Net_SFTP extends Net_SSH2
}
}
/**
* Returns canonicalized absolute pathname
*
* realpath() expands all symbolic links and resolves references to '/./', '/../' and extra '/' characters in the input
* path and returns the canonicalized absolute pathname.
*
* @param string $path
* @return mixed
* @access public
*/
function realpath($path)
{
return $this->_realpath($path);
}
/**
* Canonicalize the Server-Side Path Name
*
* SFTP doesn't provide a mechanism by which the current working directory can be changed, so we'll emulate it. Returns
* the absolute (canonicalized) path.
*
* @see Net_SFTP::chdir()
* @param String $path
* @return Mixed
* @see self::chdir()
* @param string $path
* @return mixed
* @access private
*/
function _realpath($path)
@ -676,13 +678,13 @@ class Net_SFTP extends Net_SSH2
/**
* Changes the current directory
*
* @param String $dir
* @return Boolean
* @param string $dir
* @return bool
* @access public
*/
function chdir($dir)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
return false;
}
@ -711,7 +713,7 @@ class Net_SFTP extends Net_SSH2
return false;
}
// see Net_SFTP::nlist() for a more thorough explanation of the following
// see \phpseclib\Net\SFTP::nlist() for a more thorough explanation of the following
$response = $this->_get_sftp_packet();
switch ($this->packet_type) {
case NET_SFTP_HANDLE:
@ -738,9 +740,9 @@ class Net_SFTP extends Net_SSH2
/**
* Returns a list of files in the given directory
*
* @param optional String $dir
* @param optional Boolean $recursive
* @return Mixed
* @param string $dir
* @param bool $recursive
* @return mixed
* @access public
*/
function nlist($dir = '.', $recursive = false)
@ -751,17 +753,17 @@ class Net_SFTP extends Net_SSH2
/**
* Helper method for nlist
*
* @param String $dir
* @param Boolean $recursive
* @param String $relativeDir
* @return Mixed
* @param string $dir
* @param bool $recursive
* @param string $relativeDir
* @return mixed
* @access private
*/
function _nlist_helper($dir, $recursive, $relativeDir)
{
$files = $this->_list($dir, false);
if (!$recursive) {
if (!$recursive || $files === false) {
return $files;
}
@ -787,9 +789,9 @@ class Net_SFTP extends Net_SSH2
/**
* Returns a detailed list of files in the given directory
*
* @param optional String $dir
* @param optional Boolean $recursive
* @return Mixed
* @param string $dir
* @param bool $recursive
* @return mixed
* @access public
*/
function rawlist($dir = '.', $recursive = false)
@ -801,7 +803,7 @@ class Net_SFTP extends Net_SSH2
static $depth = 0;
foreach ($files as $key=>$value) {
foreach ($files as $key => $value) {
if ($depth != 0 && $key == '..') {
unset($files[$key]);
continue;
@ -821,14 +823,14 @@ class Net_SFTP extends Net_SSH2
/**
* Reads a list, be it detailed or not, of files in the given directory
*
* @param String $dir
* @param optional Boolean $raw
* @return Mixed
* @param string $dir
* @param bool $raw
* @return mixed
* @access private
*/
function _list($dir, $raw = true)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
return false;
}
@ -896,7 +898,7 @@ class Net_SFTP extends Net_SSH2
} else {
$temp = $dir . '/' . $shortname;
}
$this->_update_stat_cache($temp, (object) $attributes);
$this->_update_stat_cache($temp, (object) array('lstat' => $attributes));
}
// SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the
// final SSH_FXP_STATUS packet should tell us that, already.
@ -931,9 +933,9 @@ class Net_SFTP extends Net_SSH2
*
* Intended for use with uasort()
*
* @param Array $a
* @param Array $b
* @return Integer
* @param array $a
* @param array $b
* @return int
* @access private
*/
function _comparator($a, $b)
@ -1031,13 +1033,13 @@ class Net_SFTP extends Net_SSH2
*
* Files larger than 4GB will show up as being exactly 4GB.
*
* @param String $filename
* @return Mixed
* @param string $filename
* @return mixed
* @access public
*/
function size($filename)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
return false;
}
@ -1051,22 +1053,40 @@ class Net_SFTP extends Net_SSH2
/**
* Save files / directories to cache
*
* @param String $path
* @param Mixed $value
* @param string $path
* @param mixed $value
* @access private
*/
function _update_stat_cache($path, $value)
{
if ($this->use_stat_cache === false) {
return;
}
// preg_replace('#^/|/(?=/)|/$#', '', $dir) == str_replace('//', '/', trim($path, '/'))
$dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path));
$temp = &$this->stat_cache;
$max = count($dirs) - 1;
foreach ($dirs as $i=>$dir) {
foreach ($dirs as $i => $dir) {
// if $temp is an object that means one of two things.
// 1. a file was deleted and changed to a directory behind phpseclib's back
// 2. it's a symlink. when lstat is done it's unclear what it's a symlink to
if (is_object($temp)) {
$temp = array();
}
if (!isset($temp[$dir])) {
$temp[$dir] = array();
}
if ($i === $max) {
if (is_object($temp[$dir])) {
if (!isset($value->stat) && isset($temp[$dir]->stat)) {
$value->stat = $temp[$dir]->stat;
}
if (!isset($value->lstat) && isset($temp[$dir]->lstat)) {
$value->lstat = $temp[$dir]->lstat;
}
}
$temp[$dir] = $value;
break;
}
@ -1077,8 +1097,8 @@ class Net_SFTP extends Net_SSH2
/**
* Remove files / directories from cache
*
* @param String $path
* @return Boolean
* @param string $path
* @return bool
* @access private
*/
function _remove_from_stat_cache($path)
@ -1087,7 +1107,7 @@ class Net_SFTP extends Net_SSH2
$temp = &$this->stat_cache;
$max = count($dirs) - 1;
foreach ($dirs as $i=>$dir) {
foreach ($dirs as $i => $dir) {
if ($i === $max) {
unset($temp[$dir]);
return true;
@ -1104,8 +1124,8 @@ class Net_SFTP extends Net_SSH2
*
* Mainly used by file_exists
*
* @param String $dir
* @return Mixed
* @param string $dir
* @return mixed
* @access private
*/
function _query_stat_cache($path)
@ -1127,13 +1147,13 @@ class Net_SFTP extends Net_SSH2
*
* Returns an array on success and false otherwise.
*
* @param String $filename
* @return Mixed
* @param string $filename
* @return mixed
* @access public
*/
function stat($filename)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
return false;
}
@ -1144,11 +1164,11 @@ class Net_SFTP extends Net_SSH2
if ($this->use_stat_cache) {
$result = $this->_query_stat_cache($filename);
if (is_array($result) && isset($result['.'])) {
return (array) $result['.'];
if (is_array($result) && isset($result['.']) && isset($result['.']->stat)) {
return $result['.']->stat;
}
if (is_object($result)) {
return (array) $result;
if (is_object($result) && isset($result->stat)) {
return $result->stat;
}
}
@ -1161,7 +1181,7 @@ class Net_SFTP extends Net_SSH2
if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) {
$filename.= '/.';
}
$this->_update_stat_cache($filename, (object) $stat);
$this->_update_stat_cache($filename, (object) array('stat' => $stat));
return $stat;
}
@ -1174,7 +1194,7 @@ class Net_SFTP extends Net_SSH2
if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) {
$filename.= '/.';
}
$this->_update_stat_cache($filename, (object) $stat);
$this->_update_stat_cache($filename, (object) array('stat' => $stat));
return $stat;
}
@ -1184,13 +1204,13 @@ class Net_SFTP extends Net_SSH2
*
* Returns an array on success and false otherwise.
*
* @param String $filename
* @return Mixed
* @param string $filename
* @return mixed
* @access public
*/
function lstat($filename)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
return false;
}
@ -1201,11 +1221,11 @@ class Net_SFTP extends Net_SSH2
if ($this->use_stat_cache) {
$result = $this->_query_stat_cache($filename);
if (is_array($result) && isset($result['.'])) {
return (array) $result['.'];
if (is_array($result) && isset($result['.']) && isset($result['.']->lstat)) {
return $result['.']->lstat;
}
if (is_object($result)) {
return (array) $result;
if (is_object($result) && isset($result->lstat)) {
return $result->lstat;
}
}
@ -1218,7 +1238,7 @@ class Net_SFTP extends Net_SSH2
if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) {
$filename.= '/.';
}
$this->_update_stat_cache($filename, (object) $lstat);
$this->_update_stat_cache($filename, (object) array('lstat' => $lstat));
return $lstat;
}
@ -1226,7 +1246,7 @@ class Net_SFTP extends Net_SSH2
if ($lstat != $stat) {
$lstat = array_merge($lstat, array('type' => NET_SFTP_TYPE_SYMLINK));
$this->_update_stat_cache($filename, (object) $lstat);
$this->_update_stat_cache($filename, (object) array('lstat' => $lstat));
return $stat;
}
@ -1239,7 +1259,7 @@ class Net_SFTP extends Net_SSH2
if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) {
$filename.= '/.';
}
$this->_update_stat_cache($filename, (object) $lstat);
$this->_update_stat_cache($filename, (object) array('lstat' => $lstat));
return $lstat;
}
@ -1247,12 +1267,12 @@ class Net_SFTP extends Net_SSH2
/**
* Returns general information about a file or symbolic link
*
* Determines information without calling Net_SFTP::_realpath().
* Determines information without calling \phpseclib\Net\SFTP::_realpath().
* The second parameter can be either NET_SFTP_STAT or NET_SFTP_LSTAT.
*
* @param String $filename
* @param Integer $type
* @return Mixed
* @param string $filename
* @param int $type
* @return mixed
* @access private
*/
function _stat($filename, $type)
@ -1279,9 +1299,9 @@ class Net_SFTP extends Net_SSH2
/**
* Truncates a file to a given length
*
* @param String $filename
* @param Integer $new_size
* @return Boolean
* @param string $filename
* @param int $new_size
* @return bool
* @access public
*/
function truncate($filename, $new_size)
@ -1296,15 +1316,15 @@ class Net_SFTP extends Net_SSH2
*
* If the file does not exist, it will be created.
*
* @param String $filename
* @param optional Integer $time
* @param optional Integer $atime
* @return Boolean
* @param string $filename
* @param int $time
* @param int $atime
* @return bool
* @access public
*/
function touch($filename, $time = null, $atime = null)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
return false;
}
@ -1347,10 +1367,10 @@ class Net_SFTP extends Net_SSH2
*
* Returns true on success or false on error.
*
* @param String $filename
* @param Integer $uid
* @param optional Boolean $recursive
* @return Boolean
* @param string $filename
* @param int $uid
* @param bool $recursive
* @return bool
* @access public
*/
function chown($filename, $uid, $recursive = false)
@ -1367,10 +1387,10 @@ class Net_SFTP extends Net_SSH2
*
* Returns true on success or false on error.
*
* @param String $filename
* @param Integer $gid
* @param optional Boolean $recursive
* @return Boolean
* @param string $filename
* @param int $gid
* @param bool $recursive
* @return bool
* @access public
*/
function chgrp($filename, $gid, $recursive = false)
@ -1386,10 +1406,10 @@ class Net_SFTP extends Net_SSH2
* Returns the new file permissions on success or false on error.
* If $recursive is true than this just returns true or false.
*
* @param Integer $mode
* @param String $filename
* @param optional Boolean $recursive
* @return Mixed
* @param int $mode
* @param string $filename
* @param bool $recursive
* @return mixed
* @access public
*/
function chmod($mode, $filename, $recursive = false)
@ -1408,6 +1428,7 @@ class Net_SFTP extends Net_SSH2
return true;
}
$filename = $this->_realPath($filename);
// rather than return what the permissions *should* be, we'll return what they actually are. this will also
// tell us if the file actually exists.
// incidentally, SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
@ -1433,15 +1454,15 @@ class Net_SFTP extends Net_SSH2
/**
* Sets information about a file
*
* @param String $filename
* @param String $attr
* @param Boolean $recursive
* @return Boolean
* @param string $filename
* @param string $attr
* @param bool $recursive
* @return bool
* @access private
*/
function _setstat($filename, $attr, $recursive)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
return false;
}
@ -1492,10 +1513,10 @@ class Net_SFTP extends Net_SSH2
*
* Minimizes directory lookups and SSH_FXP_STATUS requests for speed.
*
* @param String $path
* @param String $attr
* @param Integer $i
* @return Boolean
* @param string $path
* @param string $attr
* @param int $i
* @return bool
* @access private
*/
function _setstat_recursive($path, $attr, &$i)
@ -1517,7 +1538,7 @@ class Net_SFTP extends Net_SSH2
}
unset($entries['.'], $entries['..']);
foreach ($entries as $filename=>$props) {
foreach ($entries as $filename => $props) {
if (!isset($props['type'])) {
return false;
}
@ -1562,13 +1583,13 @@ class Net_SFTP extends Net_SSH2
/**
* Return the target of a symbolic link
*
* @param String $link
* @return Mixed
* @param string $link
* @return mixed
* @access public
*/
function readlink($link)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
return false;
}
@ -1605,18 +1626,18 @@ class Net_SFTP extends Net_SSH2
*
* symlink() creates a symbolic link to the existing target with the specified name link.
*
* @param String $target
* @param String $link
* @return Boolean
* @param string $target
* @param string $link
* @return bool
* @access public
*/
function symlink($target, $link)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
return false;
}
$target = $this->_realpath($target);
//$target = $this->_realpath($target);
$link = $this->_realpath($link);
$packet = pack('Na*Na*', strlen($target), $target, strlen($link), $link);
@ -1642,13 +1663,13 @@ class Net_SFTP extends Net_SSH2
/**
* Creates a directory.
*
* @param String $dir
* @return Boolean
* @param string $dir
* @return bool
* @access public
*/
function mkdir($dir, $mode = -1, $recursive = false)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
return false;
}
@ -1677,8 +1698,8 @@ class Net_SFTP extends Net_SSH2
/**
* Helper function for directory creation
*
* @param String $dir
* @return Boolean
* @param string $dir
* @return bool
* @access private
*/
function _mkdir_helper($dir, $attr)
@ -1705,13 +1726,13 @@ class Net_SFTP extends Net_SSH2
/**
* Removes a directory.
*
* @param String $dir
* @return Boolean
* @param string $dir
* @return bool
* @access public
*/
function rmdir($dir)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
return false;
}
@ -1749,48 +1770,51 @@ class Net_SFTP extends Net_SSH2
/**
* Uploads a file to the SFTP server.
*
* By default, Net_SFTP::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
* So, for example, if you set $data to 'filename.ext' and then do Net_SFTP::get(), you will get a file, twelve bytes
* By default, \phpseclib\Net\SFTP::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
* So, for example, if you set $data to 'filename.ext' and then do \phpseclib\Net\SFTP::get(), you will get a file, twelve bytes
* long, containing 'filename.ext' as its contents.
*
* Setting $mode to NET_SFTP_LOCAL_FILE will change the above behavior. With NET_SFTP_LOCAL_FILE, $remote_file will
* Setting $mode to self::SOURCE_LOCAL_FILE will change the above behavior. With self::SOURCE_LOCAL_FILE, $remote_file will
* contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
* large $remote_file will be, as well.
*
* Setting $mode to self::SOURCE_CALLBACK will use $data as callback function, which gets only one parameter -- number of bytes to return, and returns a string if there is some data or null if there is no more data
*
* If $data is a resource then it'll be used as a resource instead.
*
* Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
* care of that, yourself.
*
* $mode can take an additional two parameters - NET_SFTP_RESUME and NET_SFTP_RESUME_START. These are bitwise AND'd with
* $mode can take an additional two parameters - self::RESUME and self::RESUME_START. These are bitwise AND'd with
* $mode. So if you want to resume upload of a 300mb file on the local file system you'd set $mode to the following:
*
* NET_SFTP_LOCAL_FILE | NET_SFTP_RESUME
* self::SOURCE_LOCAL_FILE | self::RESUME
*
* If you wanted to simply append the full contents of a local file to the full contents of a remote file you'd replace
* NET_SFTP_RESUME with NET_SFTP_RESUME_START.
* self::RESUME with self::RESUME_START.
*
* If $mode & (NET_SFTP_RESUME | NET_SFTP_RESUME_START) then NET_SFTP_RESUME_START will be assumed.
* If $mode & (self::RESUME | self::RESUME_START) then self::RESUME_START will be assumed.
*
* $start and $local_start give you more fine grained control over this process and take precident over NET_SFTP_RESUME
* when they're non-negative. ie. $start could let you write at the end of a file (like NET_SFTP_RESUME) or in the middle
* of one. $local_start could let you start your reading from the end of a file (like NET_SFTP_RESUME_START) or in the
* $start and $local_start give you more fine grained control over this process and take precident over self::RESUME
* when they're non-negative. ie. $start could let you write at the end of a file (like self::RESUME) or in the middle
* of one. $local_start could let you start your reading from the end of a file (like self::RESUME_START) or in the
* middle of one.
*
* Setting $local_start to > 0 or $mode | NET_SFTP_RESUME_START doesn't do anything unless $mode | NET_SFTP_LOCAL_FILE.
* Setting $local_start to > 0 or $mode | self::RESUME_START doesn't do anything unless $mode | self::SOURCE_LOCAL_FILE.
*
* @param String $remote_file
* @param String|resource $data
* @param optional Integer $mode
* @param optional Integer $start
* @param optional Integer $local_start
* @return Boolean
* @param string $remote_file
* @param string|resource $data
* @param int $mode
* @param int $start
* @param int $local_start
* @param callable|null $progressCallback
* @return bool
* @access public
* @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - Net_SFTP::setMode().
* @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - \phpseclib\Net\SFTP::setMode().
*/
function put($remote_file, $data, $mode = NET_SFTP_STRING, $start = -1, $local_start = -1)
function put($remote_file, $data, $mode = self::SOURCE_STRING, $start = -1, $local_start = -1, $progressCallback = null)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
return false;
}
@ -1804,11 +1828,11 @@ class Net_SFTP extends Net_SSH2
$flags = NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE;
// according to the SFTP specs, NET_SFTP_OPEN_APPEND should "force all writes to append data at the end of the file."
// in practice, it doesn't seem to do that.
//$flags|= ($mode & NET_SFTP_RESUME) ? NET_SFTP_OPEN_APPEND : NET_SFTP_OPEN_TRUNCATE;
//$flags|= ($mode & self::RESUME) ? NET_SFTP_OPEN_APPEND : NET_SFTP_OPEN_TRUNCATE;
if ($start >= 0) {
$offset = $start;
} elseif ($mode & NET_SFTP_RESUME) {
} elseif ($mode & self::RESUME) {
// if NET_SFTP_OPEN_APPEND worked as it should _size() wouldn't need to be called
$size = $this->size($remote_file);
$offset = $size !== false ? $size : 0;
@ -1836,12 +1860,20 @@ class Net_SFTP extends Net_SSH2
}
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3
$dataCallback = false;
switch (true) {
case $mode & self::SOURCE_CALLBACK:
if (!is_callable($data)) {
user_error("\$data should be is_callable() if you specify SOURCE_CALLBACK flag");
}
$dataCallback = $data;
// do nothing
break;
case is_resource($data):
$mode = $mode & ~NET_SFTP_LOCAL_FILE;
$mode = $mode & ~self::SOURCE_LOCAL_FILE;
$fp = $data;
break;
case $mode & NET_SFTP_LOCAL_FILE:
case $mode & self::SOURCE_LOCAL_FILE:
if (!is_file($data)) {
user_error("$data is not a valid file");
return false;
@ -1858,11 +1890,10 @@ class Net_SFTP extends Net_SSH2
if ($local_start >= 0) {
fseek($fp, $local_start);
} elseif ($mode & NET_SFTP_RESUME_START) {
// do nothing
} else {
fseek($fp, $offset);
$size-= $local_start;
}
} elseif ($dataCallback) {
$size = 0;
} else {
$size = strlen($data);
}
@ -1874,17 +1905,31 @@ class Net_SFTP extends Net_SSH2
// make the SFTP packet be exactly 4096 bytes by including the bytes in the NET_SFTP_WRITE packets "header"
$sftp_packet_size-= strlen($handle) + 25;
$i = 0;
while ($sent < $size) {
$temp = isset($fp) ? fread($fp, $sftp_packet_size) : substr($data, $sent, $sftp_packet_size);
while ($dataCallback || ($size === 0 || $sent < $size)) {
if ($dataCallback) {
$temp = call_user_func($dataCallback, $sftp_packet_size);
if (is_null($temp)) {
break;
}
} else {
$temp = isset($fp) ? fread($fp, $sftp_packet_size) : substr($data, $sent, $sftp_packet_size);
if ($temp === false || $temp === '') {
break;
}
}
$subtemp = $offset + $sent;
$packet = pack('Na*N3a*', strlen($handle), $handle, $subtemp / 4294967296, $subtemp, strlen($temp), $temp);
if (!$this->_send_sftp_packet(NET_SFTP_WRITE, $packet)) {
if ($mode & NET_SFTP_LOCAL_FILE) {
if ($mode & self::SOURCE_LOCAL_FILE) {
fclose($fp);
}
return false;
}
$sent+= strlen($temp);
if (is_callable($progressCallback)) {
call_user_func($progressCallback, $sent);
}
$i++;
@ -1898,14 +1943,14 @@ class Net_SFTP extends Net_SSH2
}
if (!$this->_read_put_responses($i)) {
if ($mode & NET_SFTP_LOCAL_FILE) {
if ($mode & self::SOURCE_LOCAL_FILE) {
fclose($fp);
}
$this->_close_handle($handle);
return false;
}
if ($mode & NET_SFTP_LOCAL_FILE) {
if ($mode & self::SOURCE_LOCAL_FILE) {
fclose($fp);
}
@ -1918,8 +1963,8 @@ class Net_SFTP extends Net_SSH2
* Sending an SSH_FXP_WRITE packet and immediately reading its response isn't as efficient as blindly sending out $i
* SSH_FXP_WRITEs, in succession, and then reading $i responses.
*
* @param Integer $i
* @return Boolean
* @param int $i
* @return bool
* @access private
*/
function _read_put_responses($i)
@ -1944,8 +1989,8 @@ class Net_SFTP extends Net_SSH2
/**
* Close handle
*
* @param String $handle
* @return Boolean
* @param string $handle
* @return bool
* @access private
*/
function _close_handle($handle)
@ -1980,16 +2025,16 @@ class Net_SFTP extends Net_SSH2
*
* $offset and $length can be used to download files in chunks.
*
* @param String $remote_file
* @param optional String $local_file
* @param optional Integer $offset
* @param optional Integer $length
* @return Mixed
* @param string $remote_file
* @param string $local_file
* @param int $offset
* @param int $length
* @return mixed
* @access public
*/
function get($remote_file, $local_file = false, $offset = 0, $length = -1)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
return false;
}
@ -2035,40 +2080,68 @@ class Net_SFTP extends Net_SSH2
$fclose_check = $local_file !== false && !is_resource($local_file);
$start = $offset;
$size = $this->max_sftp_packet < $length || $length < 0 ? $this->max_sftp_packet : $length;
$read = 0;
while (true) {
$packet = pack('Na*N3', strlen($handle), $handle, $offset / 4294967296, $offset, $size);
if (!$this->_send_sftp_packet(NET_SFTP_READ, $packet)) {
if ($fclose_check) {
fclose($fp);
}
return false;
}
$i = 0;
$response = $this->_get_sftp_packet();
switch ($this->packet_type) {
case NET_SFTP_DATA:
$temp = substr($response, 4);
$offset+= strlen($temp);
if ($local_file === false) {
$content.= $temp;
} else {
fputs($fp, $temp);
}
break;
case NET_SFTP_STATUS:
// could, in theory, return false if !strlen($content) but we'll hold off for the time being
$this->_logError($response);
break 2;
default:
user_error('Expected SSH_FXP_DATA or SSH_FXP_STATUS');
while ($i < NET_SFTP_QUEUE_SIZE && ($length < 0 || $read < $length)) {
$tempoffset = $start + $read;
$packet_size = $length > 0 ? min($this->max_sftp_packet, $length - $read) : $this->max_sftp_packet;
$packet = pack('Na*N3', strlen($handle), $handle, $tempoffset / 4294967296, $tempoffset, $packet_size);
if (!$this->_send_sftp_packet(NET_SFTP_READ, $packet)) {
if ($fclose_check) {
fclose($fp);
}
return false;
}
$packet = null;
$read+= $packet_size;
$i++;
}
if ($length > 0 && $length <= $offset - $start) {
if (!$i) {
break;
}
$clear_responses = false;
while ($i > 0) {
$i--;
if ($clear_responses) {
$this->_get_sftp_packet();
continue;
} else {
$response = $this->_get_sftp_packet();
}
switch ($this->packet_type) {
case NET_SFTP_DATA:
$temp = substr($response, 4);
$offset+= strlen($temp);
if ($local_file === false) {
$content.= $temp;
} else {
fputs($fp, $temp);
}
$temp = null;
break;
case NET_SFTP_STATUS:
// could, in theory, return false if !strlen($content) but we'll hold off for the time being
$this->_logError($response);
$clear_responses = true; // don't break out of the loop yet, so we can read the remaining responses
break;
default:
if ($fclose_check) {
fclose($fp);
}
user_error('Expected SSH_FX_DATA or SSH_FXP_STATUS');
}
$response = null;
}
if ($clear_responses) {
break;
}
}
@ -2096,14 +2169,14 @@ class Net_SFTP extends Net_SSH2
/**
* Deletes a file on the SFTP server.
*
* @param String $path
* @param Boolean $recursive
* @return Boolean
* @param string $path
* @param bool $recursive
* @return bool
* @access public
*/
function delete($path, $recursive = true)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
return false;
}
@ -2146,9 +2219,9 @@ class Net_SFTP extends Net_SSH2
*
* Minimizes directory lookups and SSH_FXP_STATUS requests for speed.
*
* @param String $path
* @param Integer $i
* @return Boolean
* @param string $path
* @param int $i
* @return bool
* @access private
*/
function _delete_recursive($path, &$i)
@ -2166,7 +2239,7 @@ class Net_SFTP extends Net_SSH2
}
unset($entries['.'], $entries['..']);
foreach ($entries as $filename=>$props) {
foreach ($entries as $filename => $props) {
if (!isset($props['type'])) {
return false;
}
@ -2180,6 +2253,7 @@ class Net_SFTP extends Net_SSH2
if (!$this->_send_sftp_packet(NET_SFTP_REMOVE, pack('Na*', strlen($temp), $temp))) {
return false;
}
$this->_remove_from_stat_cache($temp);
$i++;
@ -2190,12 +2264,12 @@ class Net_SFTP extends Net_SSH2
$i = 0;
}
}
$this->_remove_from_stat_cache($path);
}
if (!$this->_send_sftp_packet(NET_SFTP_RMDIR, pack('Na*', strlen($path), $path))) {
return false;
}
$this->_remove_from_stat_cache($path);
$i++;
@ -2212,8 +2286,8 @@ class Net_SFTP extends Net_SSH2
/**
* Checks whether a file or directory exists
*
* @param String $path
* @return Boolean
* @param string $path
* @return bool
* @access public
*/
function file_exists($path)
@ -2235,8 +2309,8 @@ class Net_SFTP extends Net_SSH2
/**
* Tells whether the filename is a directory
*
* @param String $path
* @return Boolean
* @param string $path
* @return bool
* @access public
*/
function is_dir($path)
@ -2251,8 +2325,8 @@ class Net_SFTP extends Net_SSH2
/**
* Tells whether the filename is a regular file
*
* @param String $path
* @return Boolean
* @param string $path
* @return bool
* @access public
*/
function is_file($path)
@ -2267,24 +2341,94 @@ class Net_SFTP extends Net_SSH2
/**
* Tells whether the filename is a symbolic link
*
* @param String $path
* @return Boolean
* @param string $path
* @return bool
* @access public
*/
function is_link($path)
{
$result = $this->_get_stat_cache_prop($path, 'type');
$result = $this->_get_lstat_cache_prop($path, 'type');
if ($result === false) {
return false;
}
return $result === NET_SFTP_TYPE_SYMLINK;
}
/**
* Tells whether a file exists and is readable
*
* @param string $path
* @return bool
* @access public
*/
function is_readable($path)
{
$path = $this->_realpath($path);
$packet = pack('Na*N2', strlen($path), $path, NET_SFTP_OPEN_READ, 0);
if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {
return false;
}
$response = $this->_get_sftp_packet();
switch ($this->packet_type) {
case NET_SFTP_HANDLE:
return true;
case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
return false;
default:
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
return false;
}
}
/**
* Tells whether the filename is writable
*
* @param string $path
* @return bool
* @access public
*/
function is_writable($path)
{
$path = $this->_realpath($path);
$packet = pack('Na*N2', strlen($path), $path, NET_SFTP_OPEN_WRITE, 0);
if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {
return false;
}
$response = $this->_get_sftp_packet();
switch ($this->packet_type) {
case NET_SFTP_HANDLE:
return true;
case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
return false;
default:
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
return false;
}
}
/**
* Tells whether the filename is writeable
*
* Alias of is_writable
*
* @param string $path
* @return bool
* @access public
*/
function is_writeable($path)
{
return $this->is_writable($path);
}
/**
* Gets last access time of file
*
* @param String $path
* @return Mixed
* @param string $path
* @return mixed
* @access public
*/
function fileatime($path)
@ -2295,8 +2439,8 @@ class Net_SFTP extends Net_SSH2
/**
* Gets file modification time
*
* @param String $path
* @return Mixed
* @param string $path
* @return mixed
* @access public
*/
function filemtime($path)
@ -2307,8 +2451,8 @@ class Net_SFTP extends Net_SSH2
/**
* Gets file permissions
*
* @param String $path
* @return Mixed
* @param string $path
* @return mixed
* @access public
*/
function fileperms($path)
@ -2319,8 +2463,8 @@ class Net_SFTP extends Net_SSH2
/**
* Gets file owner
*
* @param String $path
* @return Mixed
* @param string $path
* @return mixed
* @access public
*/
function fileowner($path)
@ -2331,8 +2475,8 @@ class Net_SFTP extends Net_SSH2
/**
* Gets file group
*
* @param String $path
* @return Mixed
* @param string $path
* @return mixed
* @access public
*/
function filegroup($path)
@ -2343,8 +2487,8 @@ class Net_SFTP extends Net_SSH2
/**
* Gets file size
*
* @param String $path
* @return Mixed
* @param string $path
* @return mixed
* @access public
*/
function filesize($path)
@ -2355,8 +2499,8 @@ class Net_SFTP extends Net_SSH2
/**
* Gets file type
*
* @param String $path
* @return Mixed
* @param string $path
* @return mixed
* @access public
*/
function filetype($path)
@ -2367,13 +2511,20 @@ class Net_SFTP extends Net_SSH2
}
switch ($type) {
case NET_SFTP_TYPE_BLOCK_DEVICE: return 'block';
case NET_SFTP_TYPE_CHAR_DEVICE: return 'char';
case NET_SFTP_TYPE_DIRECTORY: return 'dir';
case NET_SFTP_TYPE_FIFO: return 'fifo';
case NET_SFTP_TYPE_REGULAR: return 'file';
case NET_SFTP_TYPE_SYMLINK: return 'link';
default: return false;
case NET_SFTP_TYPE_BLOCK_DEVICE:
return 'block';
case NET_SFTP_TYPE_CHAR_DEVICE:
return 'char';
case NET_SFTP_TYPE_DIRECTORY:
return 'dir';
case NET_SFTP_TYPE_FIFO:
return 'fifo';
case NET_SFTP_TYPE_REGULAR:
return 'file';
case NET_SFTP_TYPE_SYMLINK:
return 'link';
default:
return false;
}
}
@ -2382,24 +2533,54 @@ class Net_SFTP extends Net_SSH2
*
* Uses cache if appropriate.
*
* @param String $path
* @param String $prop
* @return Mixed
* @param string $path
* @param string $prop
* @return mixed
* @access private
*/
function _get_stat_cache_prop($path, $prop)
{
return $this->_get_xstat_cache_prop($path, $prop, 'stat');
}
/**
* Return an lstat properity
*
* Uses cache if appropriate.
*
* @param string $path
* @param string $prop
* @return mixed
* @access private
*/
function _get_lstat_cache_prop($path, $prop)
{
return $this->_get_xstat_cache_prop($path, $prop, 'lstat');
}
/**
* Return a stat or lstat properity
*
* Uses cache if appropriate.
*
* @param string $path
* @param string $prop
* @return mixed
* @access private
*/
function _get_xstat_cache_prop($path, $prop, $type)
{
if ($this->use_stat_cache) {
$path = $this->_realpath($path);
$result = $this->_query_stat_cache($path);
if (is_object($result) && isset($result->$prop)) {
return $result->$prop;
if (is_object($result) && isset($result->$type)) {
return $result->{$type}[$prop];
}
}
$result = $this->stat($path);
$result = $this->$type($path);
if ($result === false || !isset($result[$prop])) {
return false;
@ -2411,14 +2592,14 @@ class Net_SFTP extends Net_SSH2
/**
* Renames a file or a directory on the SFTP server
*
* @param String $oldname
* @param String $newname
* @return Boolean
* @param string $oldname
* @param string $newname
* @return bool
* @access public
*/
function rename($oldname, $newname)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
return false;
}
@ -2461,8 +2642,8 @@ class Net_SFTP extends Net_SSH2
*
* See '7. File Attributes' of draft-ietf-secsh-filexfer-13 for more info.
*
* @param String $response
* @return Array
* @param string $response
* @return array
* @access private
*/
function _parseAttributes(&$response)
@ -2515,8 +2696,8 @@ class Net_SFTP extends Net_SSH2
*
* Quoting the SFTP RFC, "Implementations MUST NOT send bits that are not defined" but they seem to anyway
*
* @param Integer $mode
* @return Integer
* @param int $mode
* @return int
* @access private
*/
function _parseMode($mode)
@ -2562,8 +2743,8 @@ class Net_SFTP extends Net_SSH2
*
* If the longname is in an unrecognized format bool(false) is returned.
*
* @param String $longname
* @return Mixed
* @param string $longname
* @return mixed
* @access private
*/
function _parseLongname($longname)
@ -2591,11 +2772,11 @@ class Net_SFTP extends Net_SSH2
*
* See '6. General Packet Format' of draft-ietf-secsh-filexfer-13 for more info.
*
* @param Integer $type
* @param String $data
* @see Net_SFTP::_get_sftp_packet()
* @see Net_SSH2::_send_channel_packet()
* @return Boolean
* @param int $type
* @param string $data
* @see self::_get_sftp_packet()
* @see self::_send_channel_packet()
* @return bool
* @access private
*/
function _send_sftp_packet($type, $data)
@ -2605,7 +2786,7 @@ class Net_SFTP extends Net_SSH2
pack('NCa*', strlen($data) + 1, $type, $data);
$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
$result = $this->_send_channel_packet(NET_SFTP_CHANNEL, $packet);
$result = $this->_send_channel_packet(self::CHANNEL, $packet);
$stop = strtok(microtime(), ' ') + strtok('');
if (defined('NET_SFTP_LOGGING')) {
@ -2635,8 +2816,8 @@ class Net_SFTP extends Net_SSH2
* There can be one SSH_MSG_CHANNEL_DATA messages containing two SFTP packets or there can be two SSH_MSG_CHANNEL_DATA
* messages containing one SFTP packet.
*
* @see Net_SFTP::_send_sftp_packet()
* @return String
* @see self::_send_sftp_packet()
* @return string
* @access private
*/
function _get_sftp_packet()
@ -2647,7 +2828,7 @@ class Net_SFTP extends Net_SSH2
// SFTP packet length
while (strlen($this->packet_buffer) < 4) {
$temp = $this->_get_channel_packet(NET_SFTP_CHANNEL);
$temp = $this->_get_channel_packet(self::CHANNEL);
if (is_bool($temp)) {
$this->packet_type = false;
$this->packet_buffer = '';
@ -2661,7 +2842,7 @@ class Net_SFTP extends Net_SSH2
// SFTP packet type and data payload
while ($tempLength > 0) {
$temp = $this->_get_channel_packet(NET_SFTP_CHANNEL);
$temp = $this->_get_channel_packet(self::CHANNEL);
if (is_bool($temp)) {
$this->packet_type = false;
$this->packet_buffer = '';
@ -2708,7 +2889,7 @@ class Net_SFTP extends Net_SSH2
* Returns a string if NET_SFTP_LOGGING == NET_SFTP_LOG_COMPLEX, an array if NET_SFTP_LOGGING == NET_SFTP_LOG_SIMPLE and false if !defined('NET_SFTP_LOGGING')
*
* @access public
* @return String or Array
* @return string or Array
*/
function getSFTPLog()
{
@ -2729,7 +2910,7 @@ class Net_SFTP extends Net_SSH2
/**
* Returns all errors
*
* @return String
* @return string
* @access public
*/
function getSFTPErrors()
@ -2740,7 +2921,7 @@ class Net_SFTP extends Net_SSH2
/**
* Returns the last error
*
* @return String
* @return string
* @access public
*/
function getLastSFTPError()
@ -2751,7 +2932,7 @@ class Net_SFTP extends Net_SSH2
/**
* Get supported SFTP versions
*
* @return Array
* @return array
* @access public
*/
function getSupportedVersions()
@ -2766,8 +2947,8 @@ class Net_SFTP extends Net_SSH2
/**
* Disconnect
*
* @param Integer $reason
* @return Boolean
* @param int $reason
* @return bool
* @access private
*/
function _disconnect($reason)

View file

@ -7,54 +7,41 @@
*
* PHP version 5
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Net
* @package Net_SFTP_Stream
* @package SFTP
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2013 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\Net\SFTP;
use phpseclib\Crypt\RSA;
use phpseclib\Net\SFTP;
/**
* SFTP Stream Wrapper
*
* @package Net_SFTP_Stream
* @package SFTP
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Net_SFTP_Stream
class Stream
{
/**
* SFTP instances
*
* Rather than re-create the connection we re-use instances if possible
*
* @var Array
* @var array
*/
static $instances;
/**
* SFTP instance
*
* @var Object
* @var object
* @access private
*/
var $sftp;
@ -62,7 +49,7 @@ class Net_SFTP_Stream
/**
* Path
*
* @var String
* @var string
* @access private
*/
var $path;
@ -70,7 +57,7 @@ class Net_SFTP_Stream
/**
* Mode
*
* @var String
* @var string
* @access private
*/
var $mode;
@ -78,7 +65,7 @@ class Net_SFTP_Stream
/**
* Position
*
* @var Integer
* @var int
* @access private
*/
var $pos;
@ -86,7 +73,7 @@ class Net_SFTP_Stream
/**
* Size
*
* @var Integer
* @var int
* @access private
*/
var $size;
@ -94,7 +81,7 @@ class Net_SFTP_Stream
/**
* Directory entries
*
* @var Array
* @var array
* @access private
*/
var $entries;
@ -102,7 +89,7 @@ class Net_SFTP_Stream
/**
* EOF flag
*
* @var Boolean
* @var bool
* @access private
*/
var $eof;
@ -112,7 +99,7 @@ class Net_SFTP_Stream
*
* Technically this needs to be publically accessible so PHP can set it directly
*
* @var Resource
* @var resource
* @access public
*/
var $context;
@ -120,7 +107,7 @@ class Net_SFTP_Stream
/**
* Notification callback function
*
* @var Callable
* @var callable
* @access public
*/
var $notification;
@ -128,8 +115,8 @@ class Net_SFTP_Stream
/**
* Registers this class as a URL wrapper.
*
* @param optional String $protocol The wrapper name to be registered.
* @return Boolean True on success, false otherwise.
* @param string $protocol The wrapper name to be registered.
* @return bool True on success, false otherwise.
* @access public
*/
static function register($protocol = 'sftp')
@ -137,8 +124,7 @@ class Net_SFTP_Stream
if (in_array($protocol, stream_get_wrappers(), true)) {
return false;
}
$class = function_exists('get_called_class') ? get_called_class() : __CLASS__;
return stream_wrapper_register($protocol, $class);
return stream_wrapper_register($protocol, get_called_class());
}
/**
@ -146,15 +132,11 @@ class Net_SFTP_Stream
*
* @access public
*/
function Net_SFTP_Stream()
function __construct()
{
if (defined('NET_SFTP_STREAM_LOGGING')) {
echo "__construct()\r\n";
}
if (!class_exists('Net_SFTP')) {
include_once 'Net/SFTP.php';
}
}
/**
@ -165,13 +147,24 @@ class Net_SFTP_Stream
* If "notification" is set as a context parameter the message code for successful login is
* NET_SSH2_MSG_USERAUTH_SUCCESS. For a failed login it's NET_SSH2_MSG_USERAUTH_FAILURE.
*
* @param String $path
* @return String
* @param string $path
* @return string
* @access private
*/
function _parse_path($path)
{
$orig = $path;
extract(parse_url($path) + array('port' => 22));
if (isset($query)) {
$path.= '?' . $query;
} elseif (preg_match('/(\?|\?#)$/', $orig)) {
$path.= '?';
}
if (isset($fragment)) {
$path.= '#' . $fragment;
} elseif ($orig[strlen($orig) - 1] == '#') {
$path.= '#';
}
if (!isset($host)) {
return false;
@ -187,7 +180,7 @@ class Net_SFTP_Stream
if ($host[0] == '$') {
$host = substr($host, 1);
global $$host;
if (!is_object($$host) || get_class($$host) != 'Net_SFTP') {
if (($$host instanceof SFTP) === false) {
return false;
}
$this->sftp = $$host;
@ -201,7 +194,7 @@ class Net_SFTP_Stream
if (isset($context[$scheme]['sftp'])) {
$sftp = $context[$scheme]['sftp'];
}
if (isset($sftp) && is_object($sftp) && get_class($sftp) == 'Net_SFTP') {
if (isset($sftp) && $sftp instanceof SFTP) {
$this->sftp = $sftp;
return $path;
}
@ -211,7 +204,7 @@ class Net_SFTP_Stream
if (isset($context[$scheme]['password'])) {
$pass = $context[$scheme]['password'];
}
if (isset($context[$scheme]['privkey']) && is_object($context[$scheme]['privkey']) && get_Class($context[$scheme]['privkey']) == 'Crypt_RSA') {
if (isset($context[$scheme]['privkey']) && $context[$scheme]['privkey'] instanceof RSA) {
$pass = $context[$scheme]['privkey'];
}
@ -219,11 +212,11 @@ class Net_SFTP_Stream
return false;
}
// casting $pass to a string is necessary in the event that it's a Crypt_RSA object
// casting $pass to a string is necessary in the event that it's a \phpseclib\Crypt\RSA object
if (isset(self::$instances[$host][$port][$user][(string) $pass])) {
$this->sftp = self::$instances[$host][$port][$user][(string) $pass];
} else {
$this->sftp = new Net_SFTP($host, $port);
$this->sftp = new SFTP($host, $port);
$this->sftp->disableStatCache();
if (isset($this->notification) && is_callable($this->notification)) {
/* if !is_callable($this->notification) we could do this:
@ -257,11 +250,11 @@ class Net_SFTP_Stream
/**
* Opens file or URL
*
* @param String $path
* @param String $mode
* @param Integer $options
* @param String $opened_path
* @return Boolean
* @param string $path
* @param string $mode
* @param int $options
* @param string $opened_path
* @return bool
* @access public
*/
function _stream_open($path, $mode, $options, &$opened_path)
@ -280,14 +273,17 @@ class Net_SFTP_Stream
if ($this->size === false) {
if ($this->mode[0] == 'r') {
return false;
} else {
$this->sftp->touch($path);
$this->size = 0;
}
} else {
switch ($this->mode[0]) {
case 'x':
return false;
case 'w':
case 'c':
$this->sftp->truncate($path, 0);
$this->size = 0;
}
}
@ -299,8 +295,8 @@ class Net_SFTP_Stream
/**
* Read from stream
*
* @param Integer $count
* @return Mixed
* @param int $count
* @return mixed
* @access public
*/
function _stream_read($count)
@ -341,8 +337,8 @@ class Net_SFTP_Stream
/**
* Write to stream
*
* @param String $data
* @return Mixed
* @param string $data
* @return mixed
* @access public
*/
function _stream_write($data)
@ -352,7 +348,7 @@ class Net_SFTP_Stream
return false;
}
$result = $this->sftp->put($this->path, $data, NET_SFTP_STRING, $this->pos);
$result = $this->sftp->put($this->path, $data, SFTP::SOURCE_STRING, $this->pos);
if (isset($this->notification) && is_callable($this->notification)) {
if (!$result) {
call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0);
@ -376,7 +372,7 @@ class Net_SFTP_Stream
/**
* Retrieve the current position of a stream
*
* @return Integer
* @return int
* @access public
*/
function _stream_tell()
@ -394,7 +390,7 @@ class Net_SFTP_Stream
* will return false. do fread($fp, 1) and feof() will then return true. do fseek($fp, 10) on ablank file and feof()
* will return false. do fread($fp, 1) and feof() will then return true.
*
* @return Boolean
* @return bool
* @access public
*/
function _stream_eof()
@ -405,9 +401,9 @@ class Net_SFTP_Stream
/**
* Seeks to specific location in a stream
*
* @param Integer $offset
* @param Integer $whence
* @return Boolean
* @param int $offset
* @param int $whence
* @return bool
* @access public
*/
function _stream_seek($offset, $whence)
@ -433,10 +429,10 @@ class Net_SFTP_Stream
/**
* Change stream options
*
* @param String $path
* @param Integer $option
* @param Mixed $var
* @return Boolean
* @param string $path
* @param int $option
* @param mixed $var
* @return bool
* @access public
*/
function _stream_metadata($path, $option, $var)
@ -467,8 +463,8 @@ class Net_SFTP_Stream
/**
* Retrieve the underlaying resource
*
* @param Integer $cast_as
* @return Resource
* @param int $cast_as
* @return resource
* @access public
*/
function _stream_cast($cast_as)
@ -479,8 +475,8 @@ class Net_SFTP_Stream
/**
* Advisory file locking
*
* @param Integer $operation
* @return Boolean
* @param int $operation
* @return bool
* @access public
*/
function _stream_lock($operation)
@ -492,12 +488,12 @@ class Net_SFTP_Stream
* Renames a file or directory
*
* Attempts to rename oldname to newname, moving it between directories if necessary.
* If newname exists, it will be overwritten. This is a departure from what Net_SFTP
* If newname exists, it will be overwritten. This is a departure from what \phpseclib\Net\SFTP
* does.
*
* @param String $path_from
* @param String $path_to
* @return Boolean
* @param string $path_from
* @param string $path_to
* @return bool
* @access public
*/
function _rename($path_from, $path_to)
@ -511,7 +507,7 @@ class Net_SFTP_Stream
$path_from = $this->_parse_path($path_from);
$path_to = parse_url($path_to);
if ($path_from == false) {
if ($path_from === false) {
return false;
}
@ -547,9 +543,9 @@ class Net_SFTP_Stream
* string longname
* ATTRS attrs
*
* @param String $path
* @param Integer $options
* @return Boolean
* @param string $path
* @param int $options
* @return bool
* @access public
*/
function _dir_opendir($path, $options)
@ -566,7 +562,7 @@ class Net_SFTP_Stream
/**
* Read entry from directory handle
*
* @return Mixed
* @return mixed
* @access public
*/
function _dir_readdir()
@ -580,7 +576,7 @@ class Net_SFTP_Stream
/**
* Rewind directory handle
*
* @return Boolean
* @return bool
* @access public
*/
function _dir_rewinddir()
@ -592,7 +588,7 @@ class Net_SFTP_Stream
/**
* Close directory handle
*
* @return Boolean
* @return bool
* @access public
*/
function _dir_closedir()
@ -605,10 +601,10 @@ class Net_SFTP_Stream
*
* Only valid $options is STREAM_MKDIR_RECURSIVE
*
* @param String $path
* @param Integer $mode
* @param Integer $options
* @return Boolean
* @param string $path
* @param int $mode
* @param int $options
* @return bool
* @access public
*/
function _mkdir($path, $mode, $options)
@ -629,10 +625,10 @@ class Net_SFTP_Stream
* STREAM_MKDIR_RECURSIVE is supposed to be set. Also, when I try it out with rmdir() I get 8 as
* $options. What does 8 correspond to?
*
* @param String $path
* @param Integer $mode
* @param Integer $options
* @return Boolean
* @param string $path
* @param int $mode
* @param int $options
* @return bool
* @access public
*/
function _rmdir($path, $options)
@ -648,9 +644,9 @@ class Net_SFTP_Stream
/**
* Flushes the output
*
* See <http://php.net/fflush>. Always returns true because Net_SFTP doesn't cache stuff before writing
* See <http://php.net/fflush>. Always returns true because \phpseclib\Net\SFTP doesn't cache stuff before writing
*
* @return Boolean
* @return bool
* @access public
*/
function _stream_flush()
@ -661,7 +657,7 @@ class Net_SFTP_Stream
/**
* Retrieve information about a file resource
*
* @return Mixed
* @return mixed
* @access public
*/
function _stream_stat()
@ -676,8 +672,8 @@ class Net_SFTP_Stream
/**
* Delete a file
*
* @param String $path
* @return Boolean
* @param string $path
* @return bool
* @access public
*/
function _unlink($path)
@ -693,13 +689,13 @@ class Net_SFTP_Stream
/**
* Retrieve information about a file
*
* Ignores the STREAM_URL_STAT_QUIET flag because the entirety of Net_SFTP_Stream is quiet by default
* Ignores the STREAM_URL_STAT_QUIET flag because the entirety of \phpseclib\Net\SFTP\Stream is quiet by default
* might be worthwhile to reconstruct bits 12-16 (ie. the file type) if mode doesn't have them but we'll
* cross that bridge when and if it's reached
*
* @param String $path
* @param Integer $flags
* @return Mixed
* @param string $path
* @param int $flags
* @return mixed
* @access public
*/
function _url_stat($path, $flags)
@ -720,8 +716,8 @@ class Net_SFTP_Stream
/**
* Truncate stream
*
* @param Integer $new_size
* @return Boolean
* @param int $new_size
* @return bool
* @access public
*/
function _stream_truncate($new_size)
@ -740,12 +736,12 @@ class Net_SFTP_Stream
* Change stream options
*
* STREAM_OPTION_WRITE_BUFFER isn't supported for the same reason stream_flush isn't.
* The other two aren't supported because of limitations in Net_SFTP.
* The other two aren't supported because of limitations in \phpseclib\Net\SFTP.
*
* @param Integer $option
* @param Integer $arg1
* @param Integer $arg2
* @return Boolean
* @param int $option
* @param int $arg1
* @param int $arg2
* @return bool
* @access public
*/
function _stream_set_option($option, $arg1, $arg2)
@ -772,9 +768,9 @@ class Net_SFTP_Stream
* If NET_SFTP_STREAM_LOGGING is defined all calls will be output on the screen and then (regardless of whether or not
* NET_SFTP_STREAM_LOGGING is enabled) the parameters will be passed through to the appropriate method.
*
* @param String
* @param Array
* @return Mixed
* @param string
* @param array
* @return mixed
* @access public
*/
function __call($name, $arguments)
@ -797,5 +793,3 @@ class Net_SFTP_Stream
return call_user_func_array(array($this, $name), $arguments);
}
}
Net_SFTP_Stream::register();

View file

@ -3,14 +3,14 @@
/**
* Pure-PHP implementation of SSHv1.
*
* PHP versions 4 and 5
* PHP version 5
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Net/SSH1.php';
* include 'vendor/autoload.php';
*
* $ssh = new Net_SSH1('www.domain.tld');
* $ssh = new \phpseclib\Net\SSH1('www.domain.tld');
* if (!$ssh->login('username', 'password')) {
* exit('Login Failed');
* }
@ -22,9 +22,9 @@
* Here's another short example:
* <code>
* <?php
* include 'Net/SSH1.php';
* include 'vendor/autoload.php';
*
* $ssh = new Net_SSH1('www.domain.tld');
* $ssh = new \phpseclib\Net\SSH1('www.domain.tld');
* if (!$ssh->login('username', 'password')) {
* exit('Login Failed');
* }
@ -38,204 +38,193 @@
* More information on the SSHv1 specification can be found by reading
* {@link http://www.snailbook.com/docs/protocol-1.5.txt protocol-1.5.txt}.
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Net
* @package Net_SSH1
* @package SSH1
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**#@+
* Encryption Methods
*
* @see Net_SSH1::getSupportedCiphers()
* @access public
*/
/**
* No encryption
*
* Not supported.
*/
define('NET_SSH1_CIPHER_NONE', 0);
/**
* IDEA in CFB mode
*
* Not supported.
*/
define('NET_SSH1_CIPHER_IDEA', 1);
/**
* DES in CBC mode
*/
define('NET_SSH1_CIPHER_DES', 2);
/**
* Triple-DES in CBC mode
*
* All implementations are required to support this
*/
define('NET_SSH1_CIPHER_3DES', 3);
/**
* TRI's Simple Stream encryption CBC
*
* Not supported nor is it defined in the official SSH1 specs. OpenSSH, however, does define it (see cipher.h),
* although it doesn't use it (see cipher.c)
*/
define('NET_SSH1_CIPHER_BROKEN_TSS', 4);
/**
* RC4
*
* Not supported.
*
* @internal According to the SSH1 specs:
*
* "The first 16 bytes of the session key are used as the key for
* the server to client direction. The remaining 16 bytes are used
* as the key for the client to server direction. This gives
* independent 128-bit keys for each direction."
*
* This library currently only supports encryption when the same key is being used for both directions. This is
* because there's only one $crypto object. Two could be added ($encrypt and $decrypt, perhaps).
*/
define('NET_SSH1_CIPHER_RC4', 5);
/**
* Blowfish
*
* Not supported nor is it defined in the official SSH1 specs. OpenSSH, however, defines it (see cipher.h) and
* uses it (see cipher.c)
*/
define('NET_SSH1_CIPHER_BLOWFISH', 6);
/**#@-*/
namespace phpseclib\Net;
/**#@+
* Authentication Methods
*
* @see Net_SSH1::getSupportedAuthentications()
* @access public
*/
/**
* .rhosts or /etc/hosts.equiv
*/
define('NET_SSH1_AUTH_RHOSTS', 1);
/**
* pure RSA authentication
*/
define('NET_SSH1_AUTH_RSA', 2);
/**
* password authentication
*
* This is the only method that is supported by this library.
*/
define('NET_SSH1_AUTH_PASSWORD', 3);
/**
* .rhosts with RSA host authentication
*/
define('NET_SSH1_AUTH_RHOSTS_RSA', 4);
/**#@-*/
/**#@+
* Terminal Modes
*
* @link http://3sp.com/content/developer/maverick-net/docs/Maverick.SSH.PseudoTerminalModesMembers.html
* @access private
*/
define('NET_SSH1_TTY_OP_END', 0);
/**#@-*/
/**
* The Response Type
*
* @see Net_SSH1::_get_binary_packet()
* @access private
*/
define('NET_SSH1_RESPONSE_TYPE', 1);
/**
* The Response Data
*
* @see Net_SSH1::_get_binary_packet()
* @access private
*/
define('NET_SSH1_RESPONSE_DATA', 2);
/**#@+
* Execution Bitmap Masks
*
* @see Net_SSH1::bitmap
* @access private
*/
define('NET_SSH1_MASK_CONSTRUCTOR', 0x00000001);
define('NET_SSH1_MASK_CONNECTED', 0x00000002);
define('NET_SSH1_MASK_LOGIN', 0x00000004);
define('NET_SSH1_MASK_SHELL', 0x00000008);
/**#@-*/
/**#@+
* @access public
* @see Net_SSH1::getLog()
*/
/**
* Returns the message numbers
*/
define('NET_SSH1_LOG_SIMPLE', 1);
/**
* Returns the message content
*/
define('NET_SSH1_LOG_COMPLEX', 2);
/**
* Outputs the content real-time
*/
define('NET_SSH1_LOG_REALTIME', 3);
/**
* Dumps the content real-time to a file
*/
define('NET_SSH1_LOG_REALTIME_FILE', 4);
/**#@-*/
/**#@+
* @access public
* @see Net_SSH1::read()
*/
/**
* Returns when a string matching $expect exactly is found
*/
define('NET_SSH1_READ_SIMPLE', 1);
/**
* Returns when a string matching the regular expression $expect is found
*/
define('NET_SSH1_READ_REGEX', 2);
/**#@-*/
use phpseclib\Crypt\DES;
use phpseclib\Crypt\Random;
use phpseclib\Crypt\TripleDES;
use phpseclib\Math\BigInteger;
/**
* Pure-PHP implementation of SSHv1.
*
* @package Net_SSH1
* @package SSH1
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Net_SSH1
class SSH1
{
/**#@+
* Encryption Methods
*
* @see \phpseclib\Net\SSH1::getSupportedCiphers()
* @access public
*/
/**
* No encryption
*
* Not supported.
*/
const CIPHER_NONE = 0;
/**
* IDEA in CFB mode
*
* Not supported.
*/
const CIPHER_IDEA = 1;
/**
* DES in CBC mode
*/
const CIPHER_DES = 2;
/**
* Triple-DES in CBC mode
*
* All implementations are required to support this
*/
const CIPHER_3DES = 3;
/**
* TRI's Simple Stream encryption CBC
*
* Not supported nor is it defined in the official SSH1 specs. OpenSSH, however, does define it (see cipher.h),
* although it doesn't use it (see cipher.c)
*/
const CIPHER_BROKEN_TSS = 4;
/**
* RC4
*
* Not supported.
*
* @internal According to the SSH1 specs:
*
* "The first 16 bytes of the session key are used as the key for
* the server to client direction. The remaining 16 bytes are used
* as the key for the client to server direction. This gives
* independent 128-bit keys for each direction."
*
* This library currently only supports encryption when the same key is being used for both directions. This is
* because there's only one $crypto object. Two could be added ($encrypt and $decrypt, perhaps).
*/
const CIPHER_RC4 = 5;
/**
* Blowfish
*
* Not supported nor is it defined in the official SSH1 specs. OpenSSH, however, defines it (see cipher.h) and
* uses it (see cipher.c)
*/
const CIPHER_BLOWFISH = 6;
/**#@-*/
/**#@+
* Authentication Methods
*
* @see \phpseclib\Net\SSH1::getSupportedAuthentications()
* @access public
*/
/**
* .rhosts or /etc/hosts.equiv
*/
const AUTH_RHOSTS = 1;
/**
* pure RSA authentication
*/
const AUTH_RSA = 2;
/**
* password authentication
*
* This is the only method that is supported by this library.
*/
const AUTH_PASSWORD = 3;
/**
* .rhosts with RSA host authentication
*/
const AUTH_RHOSTS_RSA = 4;
/**#@-*/
/**#@+
* Terminal Modes
*
* @link http://3sp.com/content/developer/maverick-net/docs/Maverick.SSH.PseudoTerminalModesMembers.html
* @access private
*/
const TTY_OP_END = 0;
/**#@-*/
/**
* The Response Type
*
* @see \phpseclib\Net\SSH1::_get_binary_packet()
* @access private
*/
const RESPONSE_TYPE = 1;
/**
* The Response Data
*
* @see \phpseclib\Net\SSH1::_get_binary_packet()
* @access private
*/
const RESPONSE_DATA = 2;
/**#@+
* Execution Bitmap Masks
*
* @see \phpseclib\Net\SSH1::bitmap
* @access private
*/
const MASK_CONSTRUCTOR = 0x00000001;
const MASK_CONNECTED = 0x00000002;
const MASK_LOGIN = 0x00000004;
const MASK_SHELL = 0x00000008;
/**#@-*/
/**#@+
* @access public
* @see \phpseclib\Net\SSH1::getLog()
*/
/**
* Returns the message numbers
*/
const LOG_SIMPLE = 1;
/**
* Returns the message content
*/
const LOG_COMPLEX = 2;
/**
* Outputs the content real-time
*/
const LOG_REALTIME = 3;
/**
* Dumps the content real-time to a file
*/
const LOG_REALTIME_FILE = 4;
/**#@-*/
/**#@+
* @access public
* @see \phpseclib\Net\SSH1::read()
*/
/**
* Returns when a string matching $expect exactly is found
*/
const READ_SIMPLE = 1;
/**
* Returns when a string matching the regular expression $expect is found
*/
const READ_REGEX = 2;
/**#@-*/
/**
* The SSH identifier
*
* @var String
* @var string
* @access private
*/
var $identifier = 'SSH-1.5-phpseclib';
@ -243,7 +232,7 @@ class Net_SSH1
/**
* The Socket Object
*
* @var Object
* @var object
* @access private
*/
var $fsock;
@ -251,7 +240,7 @@ class Net_SSH1
/**
* The cryptography object
*
* @var Object
* @var object
* @access private
*/
var $crypto = false;
@ -262,7 +251,7 @@ class Net_SSH1
* The bits that are set represent functions that have been called already. This is used to determine
* if a requisite function has been successfully executed. If not, an error should be thrown.
*
* @var Integer
* @var int
* @access private
*/
var $bitmap = 0;
@ -272,8 +261,8 @@ class Net_SSH1
*
* Logged for debug purposes
*
* @see Net_SSH1::getServerKeyPublicExponent()
* @var String
* @see self::getServerKeyPublicExponent()
* @var string
* @access private
*/
var $server_key_public_exponent;
@ -283,8 +272,8 @@ class Net_SSH1
*
* Logged for debug purposes
*
* @see Net_SSH1::getServerKeyPublicModulus()
* @var String
* @see self::getServerKeyPublicModulus()
* @var string
* @access private
*/
var $server_key_public_modulus;
@ -294,8 +283,8 @@ class Net_SSH1
*
* Logged for debug purposes
*
* @see Net_SSH1::getHostKeyPublicExponent()
* @var String
* @see self::getHostKeyPublicExponent()
* @var string
* @access private
*/
var $host_key_public_exponent;
@ -305,8 +294,8 @@ class Net_SSH1
*
* Logged for debug purposes
*
* @see Net_SSH1::getHostKeyPublicModulus()
* @var String
* @see self::getHostKeyPublicModulus()
* @var string
* @access private
*/
var $host_key_public_modulus;
@ -316,18 +305,18 @@ class Net_SSH1
*
* Logged for debug purposes
*
* @see Net_SSH1::getSupportedCiphers()
* @var Array
* @see self::getSupportedCiphers()
* @var array
* @access private
*/
var $supported_ciphers = array(
NET_SSH1_CIPHER_NONE => 'No encryption',
NET_SSH1_CIPHER_IDEA => 'IDEA in CFB mode',
NET_SSH1_CIPHER_DES => 'DES in CBC mode',
NET_SSH1_CIPHER_3DES => 'Triple-DES in CBC mode',
NET_SSH1_CIPHER_BROKEN_TSS => 'TRI\'s Simple Stream encryption CBC',
NET_SSH1_CIPHER_RC4 => 'RC4',
NET_SSH1_CIPHER_BLOWFISH => 'Blowfish'
self::CIPHER_NONE => 'No encryption',
self::CIPHER_IDEA => 'IDEA in CFB mode',
self::CIPHER_DES => 'DES in CBC mode',
self::CIPHER_3DES => 'Triple-DES in CBC mode',
self::CIPHER_BROKEN_TSS => 'TRI\'s Simple Stream encryption CBC',
self::CIPHER_RC4 => 'RC4',
self::CIPHER_BLOWFISH => 'Blowfish'
);
/**
@ -335,22 +324,22 @@ class Net_SSH1
*
* Logged for debug purposes
*
* @see Net_SSH1::getSupportedAuthentications()
* @var Array
* @see self::getSupportedAuthentications()
* @var array
* @access private
*/
var $supported_authentications = array(
NET_SSH1_AUTH_RHOSTS => '.rhosts or /etc/hosts.equiv',
NET_SSH1_AUTH_RSA => 'pure RSA authentication',
NET_SSH1_AUTH_PASSWORD => 'password authentication',
NET_SSH1_AUTH_RHOSTS_RSA => '.rhosts with RSA host authentication'
self::AUTH_RHOSTS => '.rhosts or /etc/hosts.equiv',
self::AUTH_RSA => 'pure RSA authentication',
self::AUTH_PASSWORD => 'password authentication',
self::AUTH_RHOSTS_RSA => '.rhosts with RSA host authentication'
);
/**
* Server Identification
*
* @see Net_SSH1::getServerIdentification()
* @var String
* @see self::getServerIdentification()
* @var string
* @access private
*/
var $server_identification = '';
@ -358,8 +347,8 @@ class Net_SSH1
/**
* Protocol Flags
*
* @see Net_SSH1::Net_SSH1()
* @var Array
* @see self::__construct()
* @var array
* @access private
*/
var $protocol_flags = array();
@ -367,8 +356,8 @@ class Net_SSH1
/**
* Protocol Flag Log
*
* @see Net_SSH1::getLog()
* @var Array
* @see self::getLog()
* @var array
* @access private
*/
var $protocol_flag_log = array();
@ -376,8 +365,8 @@ class Net_SSH1
/**
* Message Log
*
* @see Net_SSH1::getLog()
* @var Array
* @see self::getLog()
* @var array
* @access private
*/
var $message_log = array();
@ -385,8 +374,8 @@ class Net_SSH1
/**
* Real-time log file pointer
*
* @see Net_SSH1::_append_log()
* @var Resource
* @see self::_append_log()
* @var resource
* @access private
*/
var $realtime_log_file;
@ -394,8 +383,8 @@ class Net_SSH1
/**
* Real-time log file size
*
* @see Net_SSH1::_append_log()
* @var Integer
* @see self::_append_log()
* @var int
* @access private
*/
var $realtime_log_size;
@ -403,8 +392,8 @@ class Net_SSH1
/**
* Real-time log file wrap boolean
*
* @see Net_SSH1::_append_log()
* @var Boolean
* @see self::_append_log()
* @var bool
* @access private
*/
var $realtime_log_wrap;
@ -412,8 +401,8 @@ class Net_SSH1
/**
* Interactive Buffer
*
* @see Net_SSH1::read()
* @var Array
* @see self::read()
* @var array
* @access private
*/
var $interactiveBuffer = '';
@ -421,7 +410,7 @@ class Net_SSH1
/**
* Timeout
*
* @see Net_SSH1::setTimeout()
* @see self::setTimeout()
* @access private
*/
var $timeout;
@ -429,7 +418,7 @@ class Net_SSH1
/**
* Current Timeout
*
* @see Net_SSH1::_get_channel_packet()
* @see self::_get_channel_packet()
* @access private
*/
var $curTimeout;
@ -437,7 +426,7 @@ class Net_SSH1
/**
* Log Boundary
*
* @see Net_SSH1::_format_log
* @see self::_format_log()
* @access private
*/
var $log_boundary = ':';
@ -445,7 +434,7 @@ class Net_SSH1
/**
* Log Long Width
*
* @see Net_SSH1::_format_log
* @see self::_format_log()
* @access private
*/
var $log_long_width = 65;
@ -453,7 +442,7 @@ class Net_SSH1
/**
* Log Short Width
*
* @see Net_SSH1::_format_log
* @see self::_format_log()
* @access private
*/
var $log_short_width = 16;
@ -461,9 +450,9 @@ class Net_SSH1
/**
* Hostname
*
* @see Net_SSH1::Net_SSH1()
* @see Net_SSH1::_connect()
* @var String
* @see self::__construct()
* @see self::_connect()
* @var string
* @access private
*/
var $host;
@ -471,9 +460,9 @@ class Net_SSH1
/**
* Port Number
*
* @see Net_SSH1::Net_SSH1()
* @see Net_SSH1::_connect()
* @var Integer
* @see self::__construct()
* @see self::_connect()
* @var int
* @access private
*/
var $port;
@ -486,9 +475,9 @@ class Net_SSH1
* however, is non-optional. There will be a timeout, whether or not you set it. If you don't it'll be
* 10 seconds. It is used by fsockopen() in that function.
*
* @see Net_SSH1::Net_SSH1()
* @see Net_SSH1::_connect()
* @var Integer
* @see self::__construct()
* @see self::_connect()
* @var int
* @access private
*/
var $connectionTimeout;
@ -496,9 +485,9 @@ class Net_SSH1
/**
* Default cipher
*
* @see Net_SSH1::Net_SSH1()
* @see Net_SSH1::_connect()
* @var Integer
* @see self::__construct()
* @see self::_connect()
* @var int
* @access private
*/
var $cipher;
@ -508,28 +497,15 @@ class Net_SSH1
*
* Connects to an SSHv1 server
*
* @param String $host
* @param optional Integer $port
* @param optional Integer $timeout
* @param optional Integer $cipher
* @return Net_SSH1
* @param string $host
* @param int $port
* @param int $timeout
* @param int $cipher
* @return \phpseclib\Net\SSH1
* @access public
*/
function Net_SSH1($host, $port = 22, $timeout = 10, $cipher = NET_SSH1_CIPHER_3DES)
function __construct($host, $port = 22, $timeout = 10, $cipher = self::CIPHER_3DES)
{
if (!class_exists('Math_BigInteger')) {
include_once 'Math/BigInteger.php';
}
// Include Crypt_Random
// the class_exists() will only be called if the crypt_random_string function hasn't been defined and
// will trigger a call to __autoload() if you're wanting to auto-load classes
// call function_exists() a second time to stop the include_once from being called outside
// of the auto loader
if (!function_exists('crypt_random_string') && !class_exists('Crypt_Random') && !function_exists('crypt_random_string')) {
include_once 'Crypt/Random.php';
}
$this->protocol_flags = array(
1 => 'NET_SSH1_MSG_DISCONNECT',
2 => 'NET_SSH1_SMSG_PUBLIC_KEY',
@ -560,7 +536,7 @@ class Net_SSH1
/**
* Connect to an SSHv1 server
*
* @return Boolean
* @return bool
* @access private
*/
function _connect()
@ -590,46 +566,46 @@ class Net_SSH1
fputs($this->fsock, $this->identifier."\r\n");
$response = $this->_get_binary_packet();
if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
user_error('Expected SSH_SMSG_PUBLIC_KEY');
return false;
}
$anti_spoofing_cookie = $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 8);
$anti_spoofing_cookie = $this->_string_shift($response[self::RESPONSE_DATA], 8);
$this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
$this->_string_shift($response[self::RESPONSE_DATA], 4);
$temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
$server_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
$temp = unpack('nlen', $this->_string_shift($response[self::RESPONSE_DATA], 2));
$server_key_public_exponent = new BigInteger($this->_string_shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
$this->server_key_public_exponent = $server_key_public_exponent;
$temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
$server_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
$temp = unpack('nlen', $this->_string_shift($response[self::RESPONSE_DATA], 2));
$server_key_public_modulus = new BigInteger($this->_string_shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
$this->server_key_public_modulus = $server_key_public_modulus;
$this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
$this->_string_shift($response[self::RESPONSE_DATA], 4);
$temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
$host_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
$temp = unpack('nlen', $this->_string_shift($response[self::RESPONSE_DATA], 2));
$host_key_public_exponent = new BigInteger($this->_string_shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
$this->host_key_public_exponent = $host_key_public_exponent;
$temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
$host_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
$temp = unpack('nlen', $this->_string_shift($response[self::RESPONSE_DATA], 2));
$host_key_public_modulus = new BigInteger($this->_string_shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
$this->host_key_public_modulus = $host_key_public_modulus;
$this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
$this->_string_shift($response[self::RESPONSE_DATA], 4);
// get a list of the supported ciphers
extract(unpack('Nsupported_ciphers_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));
foreach ($this->supported_ciphers as $mask=>$name) {
extract(unpack('Nsupported_ciphers_mask', $this->_string_shift($response[self::RESPONSE_DATA], 4)));
foreach ($this->supported_ciphers as $mask => $name) {
if (($supported_ciphers_mask & (1 << $mask)) == 0) {
unset($this->supported_ciphers[$mask]);
}
}
// get a list of the supported authentications
extract(unpack('Nsupported_authentications_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));
foreach ($this->supported_authentications as $mask=>$name) {
extract(unpack('Nsupported_authentications_mask', $this->_string_shift($response[self::RESPONSE_DATA], 4)));
foreach ($this->supported_authentications as $mask => $name) {
if (($supported_authentications_mask & (1 << $mask)) == 0) {
unset($this->supported_authentications[$mask]);
}
@ -637,7 +613,7 @@ class Net_SSH1
$session_id = pack('H*', md5($host_key_public_modulus->toBytes() . $server_key_public_modulus->toBytes() . $anti_spoofing_cookie));
$session_key = crypt_random_string(32);
$session_key = Random::string(32);
$double_encrypted_session_key = $session_key ^ str_pad($session_id, 32, chr(0));
if ($server_key_public_modulus->compare($host_key_public_modulus) < 0) {
@ -672,7 +648,7 @@ class Net_SSH1
);
}
$cipher = isset($this->supported_ciphers[$this->cipher]) ? $this->cipher : NET_SSH1_CIPHER_3DES;
$cipher = isset($this->supported_ciphers[$this->cipher]) ? $this->cipher : self::CIPHER_3DES;
$data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0);
if (!$this->_send_binary_packet($data)) {
@ -681,32 +657,23 @@ class Net_SSH1
}
switch ($cipher) {
//case NET_SSH1_CIPHER_NONE:
// $this->crypto = new Crypt_Null();
//case self::CIPHER_NONE:
// $this->crypto = new \phpseclib\Crypt\Null();
// break;
case NET_SSH1_CIPHER_DES:
if (!class_exists('Crypt_DES')) {
include_once 'Crypt/DES.php';
}
$this->crypto = new Crypt_DES();
case self::CIPHER_DES:
$this->crypto = new DES();
$this->crypto->disablePadding();
$this->crypto->enableContinuousBuffer();
$this->crypto->setKey(substr($session_key, 0, 8));
break;
case NET_SSH1_CIPHER_3DES:
if (!class_exists('Crypt_TripleDES')) {
include_once 'Crypt/TripleDES.php';
}
$this->crypto = new Crypt_TripleDES(CRYPT_DES_MODE_3CBC);
case self::CIPHER_3DES:
$this->crypto = new TripleDES(TripleDES::MODE_3CBC);
$this->crypto->disablePadding();
$this->crypto->enableContinuousBuffer();
$this->crypto->setKey(substr($session_key, 0, 24));
break;
//case NET_SSH1_CIPHER_RC4:
// if (!class_exists('Crypt_RC4')) {
// include_once 'Crypt/RC4.php';
// }
// $this->crypto = new Crypt_RC4();
//case self::CIPHER_RC4:
// $this->crypto = new RC4();
// $this->crypto->enableContinuousBuffer();
// $this->crypto->setKey(substr($session_key, 0, 16));
// break;
@ -714,12 +681,12 @@ class Net_SSH1
$response = $this->_get_binary_packet();
if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
user_error('Expected SSH_SMSG_SUCCESS');
return false;
}
$this->bitmap = NET_SSH1_MASK_CONNECTED;
$this->bitmap = self::MASK_CONNECTED;
return true;
}
@ -727,21 +694,21 @@ class Net_SSH1
/**
* Login
*
* @param String $username
* @param optional String $password
* @return Boolean
* @param string $username
* @param string $password
* @return bool
* @access public
*/
function login($username, $password = '')
{
if (!($this->bitmap & NET_SSH1_MASK_CONSTRUCTOR)) {
$this->bitmap |= NET_SSH1_MASK_CONSTRUCTOR;
if (!($this->bitmap & self::MASK_CONSTRUCTOR)) {
$this->bitmap |= self::MASK_CONSTRUCTOR;
if (!$this->_connect()) {
return false;
}
}
if (!($this->bitmap & NET_SSH1_MASK_CONNECTED)) {
if (!($this->bitmap & self::MASK_CONNECTED)) {
return false;
}
@ -757,10 +724,10 @@ class Net_SSH1
if ($response === true) {
return false;
}
if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) {
$this->bitmap |= NET_SSH1_MASK_LOGIN;
if ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) {
$this->bitmap |= self::MASK_LOGIN;
return true;
} else if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) {
} elseif ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) {
user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
return false;
}
@ -773,7 +740,7 @@ class Net_SSH1
}
// remove the username and password from the last logged packet
if (defined('NET_SSH1_LOGGING') && NET_SSH1_LOGGING == NET_SSH1_LOG_COMPLEX) {
if (defined('NET_SSH1_LOGGING') && NET_SSH1_LOGGING == self::LOG_COMPLEX) {
$data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen('password'), 'password');
$this->message_log[count($this->message_log) - 1] = $data;
}
@ -783,10 +750,10 @@ class Net_SSH1
if ($response === true) {
return false;
}
if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) {
$this->bitmap |= NET_SSH1_MASK_LOGIN;
if ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) {
$this->bitmap |= self::MASK_LOGIN;
return true;
} else if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) {
} elseif ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) {
return false;
} else {
user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
@ -800,7 +767,7 @@ class Net_SSH1
* $ssh->exec('ping 127.0.0.1'); on a Linux host will never return and will run indefinitely. setTimeout() makes it so it'll timeout.
* Setting $timeout to false or 0 will mean there is no timeout.
*
* @param Mixed $timeout
* @param mixed $timeout
*/
function setTimeout($timeout)
{
@ -817,19 +784,19 @@ class Net_SSH1
* {@link http://www.faqs.org/docs/bashman/bashref_65.html http://www.faqs.org/docs/bashman/bashref_65.html}
* {@link http://www.faqs.org/docs/bashman/bashref_62.html http://www.faqs.org/docs/bashman/bashref_62.html}
*
* To execute further commands, a new Net_SSH1 object will need to be created.
* To execute further commands, a new \phpseclib\Net\SSH1 object will need to be created.
*
* Returns false on failure and the output, otherwise.
*
* @see Net_SSH1::interactiveRead()
* @see Net_SSH1::interactiveWrite()
* @param String $cmd
* @see self::interactiveRead()
* @see self::interactiveWrite()
* @param string $cmd
* @return mixed
* @access public
*/
function exec($cmd, $block = true)
{
if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) {
if (!($this->bitmap & self::MASK_LOGIN)) {
user_error('Operation disallowed prior to login()');
return false;
}
@ -850,9 +817,9 @@ class Net_SSH1
if ($response !== false) {
do {
$output.= substr($response[NET_SSH1_RESPONSE_DATA], 4);
$output.= substr($response[self::RESPONSE_DATA], 4);
$response = $this->_get_binary_packet();
} while (is_array($response) && $response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_EXITSTATUS);
} while (is_array($response) && $response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_EXITSTATUS);
}
$data = pack('C', NET_SSH1_CMSG_EXIT_CONFIRMATION);
@ -862,7 +829,7 @@ class Net_SSH1
fclose($this->fsock);
// reset the execution bitmap - a new Net_SSH1 object needs to be created.
// reset the execution bitmap - a new \phpseclib\Net\SSH1 object needs to be created.
$this->bitmap = 0;
return $output;
@ -871,9 +838,9 @@ class Net_SSH1
/**
* Creates an interactive shell
*
* @see Net_SSH1::interactiveRead()
* @see Net_SSH1::interactiveWrite()
* @return Boolean
* @see self::interactiveRead()
* @see self::interactiveWrite()
* @return bool
* @access private
*/
function _initShell()
@ -881,7 +848,7 @@ class Net_SSH1
// connect using the sample parameters in protocol-1.5.txt.
// according to wikipedia.org's entry on text terminals, "the fundamental type of application running on a text
// terminal is a command line interpreter or shell". thus, opening a terminal session to run the shell.
$data = pack('CNa*N4C', NET_SSH1_CMSG_REQUEST_PTY, strlen('vt100'), 'vt100', 24, 80, 0, 0, NET_SSH1_TTY_OP_END);
$data = pack('CNa*N4C', NET_SSH1_CMSG_REQUEST_PTY, strlen('vt100'), 'vt100', 24, 80, 0, 0, self::TTY_OP_END);
if (!$this->_send_binary_packet($data)) {
user_error('Error sending SSH_CMSG_REQUEST_PTY');
@ -893,7 +860,7 @@ class Net_SSH1
if ($response === true) {
return false;
}
if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
user_error('Expected SSH_SMSG_SUCCESS');
return false;
}
@ -905,7 +872,7 @@ class Net_SSH1
return false;
}
$this->bitmap |= NET_SSH1_MASK_SHELL;
$this->bitmap |= self::MASK_SHELL;
//stream_set_blocking($this->fsock, 0);
@ -915,9 +882,9 @@ class Net_SSH1
/**
* Inputs a command into an interactive shell.
*
* @see Net_SSH1::interactiveWrite()
* @param String $cmd
* @return Boolean
* @see self::interactiveWrite()
* @param string $cmd
* @return bool
* @access public
*/
function write($cmd)
@ -928,30 +895,30 @@ class Net_SSH1
/**
* Returns the output of an interactive shell when there's a match for $expect
*
* $expect can take the form of a string literal or, if $mode == NET_SSH1_READ_REGEX,
* $expect can take the form of a string literal or, if $mode == self::READ__REGEX,
* a regular expression.
*
* @see Net_SSH1::write()
* @param String $expect
* @param Integer $mode
* @return Boolean
* @see self::write()
* @param string $expect
* @param int $mode
* @return bool
* @access public
*/
function read($expect, $mode = NET_SSH1_READ_SIMPLE)
function read($expect, $mode = self::READ__SIMPLE)
{
if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) {
if (!($this->bitmap & self::MASK_LOGIN)) {
user_error('Operation disallowed prior to login()');
return false;
}
if (!($this->bitmap & NET_SSH1_MASK_SHELL) && !$this->_initShell()) {
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
user_error('Unable to initiate an interactive shell session');
return false;
}
$match = $expect;
while (true) {
if ($mode == NET_SSH1_READ_REGEX) {
if ($mode == self::READ__REGEX) {
preg_match($expect, $this->interactiveBuffer, $matches);
$match = isset($matches[0]) ? $matches[0] : '';
}
@ -964,26 +931,26 @@ class Net_SSH1
if ($response === true) {
return $this->_string_shift($this->interactiveBuffer, strlen($this->interactiveBuffer));
}
$this->interactiveBuffer.= substr($response[NET_SSH1_RESPONSE_DATA], 4);
$this->interactiveBuffer.= substr($response[self::RESPONSE_DATA], 4);
}
}
/**
* Inputs a command into an interactive shell.
*
* @see Net_SSH1::interactiveRead()
* @param String $cmd
* @return Boolean
* @see self::interactiveRead()
* @param string $cmd
* @return bool
* @access public
*/
function interactiveWrite($cmd)
{
if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) {
if (!($this->bitmap & self::MASK_LOGIN)) {
user_error('Operation disallowed prior to login()');
return false;
}
if (!($this->bitmap & NET_SSH1_MASK_SHELL) && !$this->_initShell()) {
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
user_error('Unable to initiate an interactive shell session');
return false;
}
@ -1007,18 +974,18 @@ class Net_SSH1
* does not support ANSI escape sequences in Win32 Console applications", so if you're a Windows user,
* there's not going to be much recourse.
*
* @see Net_SSH1::interactiveRead()
* @return String
* @see self::interactiveRead()
* @return string
* @access public
*/
function interactiveRead()
{
if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) {
if (!($this->bitmap & self::MASK_LOGIN)) {
user_error('Operation disallowed prior to login()');
return false;
}
if (!($this->bitmap & NET_SSH1_MASK_SHELL) && !$this->_initShell()) {
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
user_error('Unable to initiate an interactive shell session');
return false;
}
@ -1027,7 +994,7 @@ class Net_SSH1
$write = $except = null;
if (stream_select($read, $write, $except, 0)) {
$response = $this->_get_binary_packet();
return substr($response[NET_SSH1_RESPONSE_DATA], 4);
return substr($response[self::RESPONSE_DATA], 4);
} else {
return '';
}
@ -1059,7 +1026,7 @@ class Net_SSH1
/**
* Disconnect
*
* @param String $msg
* @param string $msg
* @access private
*/
function _disconnect($msg = 'Client Quit')
@ -1070,9 +1037,9 @@ class Net_SSH1
/*
$response = $this->_get_binary_packet();
if ($response === true) {
$response = array(NET_SSH1_RESPONSE_TYPE => -1);
$response = array(self::RESPONSE_TYPE => -1);
}
switch ($response[NET_SSH1_RESPONSE_TYPE]) {
switch ($response[self::RESPONSE_TYPE]) {
case NET_SSH1_SMSG_EXITSTATUS:
$data = pack('C', NET_SSH1_CMSG_EXIT_CONFIRMATION);
break;
@ -1096,8 +1063,8 @@ class Net_SSH1
* Also, this function could be improved upon by adding detection for the following exploit:
* http://www.securiteam.com/securitynews/5LP042K3FY.html
*
* @see Net_SSH1::_send_binary_packet()
* @return Array
* @see self::_send_binary_packet()
* @return array
* @access private
*/
function _get_binary_packet()
@ -1162,8 +1129,8 @@ class Net_SSH1
}
return array(
NET_SSH1_RESPONSE_TYPE => $type,
NET_SSH1_RESPONSE_DATA => $data
self::RESPONSE_TYPE => $type,
self::RESPONSE_DATA => $data
);
}
@ -1172,9 +1139,9 @@ class Net_SSH1
*
* Returns true on success, false on failure.
*
* @see Net_SSH1::_get_binary_packet()
* @param String $data
* @return Boolean
* @see self::_get_binary_packet()
* @param string $data
* @return bool
* @access private
*/
function _send_binary_packet($data)
@ -1186,7 +1153,7 @@ class Net_SSH1
$length = strlen($data) + 4;
$padding = crypt_random_string(8 - ($length & 7));
$padding = Random::string(8 - ($length & 7));
$orig = $data;
$data = $padding . $data;
@ -1219,10 +1186,10 @@ class Net_SSH1
* we've reimplemented it. A more detailed discussion of the differences can be found after
* $crc_lookup_table's initialization.
*
* @see Net_SSH1::_get_binary_packet()
* @see Net_SSH1::_send_binary_packet()
* @param String $data
* @return Integer
* @see self::_get_binary_packet()
* @see self::_send_binary_packet()
* @param string $data
* @return int
* @access private
*/
function _crc($data)
@ -1299,7 +1266,7 @@ class Net_SSH1
$crc = 0x00000000;
$length = strlen($data);
for ($i=0;$i<$length;$i++) {
for ($i=0; $i<$length; $i++) {
// We AND $crc >> 8 with 0x00FFFFFF because we want the eight newly added bits to all
// be zero. PHP, unfortunately, doesn't always do this. 0x80000000 >> 8, as an example,
// yields 0xFF800000 - not 0x00800000. The following link elaborates:
@ -1317,9 +1284,9 @@ class Net_SSH1
*
* Inspired by array_shift
*
* @param String $string
* @param optional Integer $index
* @return String
* @param string $string
* @param int $index
* @return string
* @access private
*/
function _string_shift(&$string, $index = 1)
@ -1336,22 +1303,18 @@ class Net_SSH1
* should be a number with the property that gcd($e, ($p - 1) * ($q - 1)) == 1. Could just make anything that
* calls this call modexp, instead, but I think this makes things clearer, maybe...
*
* @see Net_SSH1::Net_SSH1()
* @param Math_BigInteger $m
* @param Array $key
* @return Math_BigInteger
* @see self::__construct()
* @param BigInteger $m
* @param array $key
* @return BigInteger
* @access private
*/
function _rsa_crypt($m, $key)
{
/*
if (!class_exists('Crypt_RSA')) {
include_once 'Crypt/RSA.php';
}
$rsa = new Crypt_RSA();
$rsa->loadKey($key, CRYPT_RSA_PUBLIC_FORMAT_RAW);
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$rsa = new RSA();
$rsa->loadKey($key, RSA::PUBLIC_FORMAT_RAW);
$rsa->setEncryptionMode(RSA::ENCRYPTION_PKCS1);
return $rsa->encrypt($m);
*/
@ -1372,13 +1335,13 @@ class Net_SSH1
$length = strlen($modulus) - strlen($m) - 3;
$random = '';
while (strlen($random) != $length) {
$block = crypt_random_string($length - strlen($random));
$block = Random::string($length - strlen($random));
$block = str_replace("\x00", '', $block);
$random.= $block;
}
$temp = chr(0) . chr(2) . $random . chr(0) . $m;
$m = new Math_BigInteger($temp, 256);
$m = new BigInteger($temp, 256);
$m = $m->modPow($key[0], $key[1]);
return $m->toBytes();
@ -1391,14 +1354,14 @@ class Net_SSH1
* named constants from it, using the value as the name of the constant and the index as the value of the constant.
* If any of the constants that would be defined already exists, none of the constants will be defined.
*
* @param Array $array
* @param array $array
* @access private
*/
function _define_array()
{
$args = func_get_args();
foreach ($args as $arg) {
foreach ($arg as $key=>$value) {
foreach ($arg as $key => $value) {
if (!defined($value)) {
define($value, $key);
} else {
@ -1411,10 +1374,10 @@ class Net_SSH1
/**
* Returns a log of the packets that have been sent and received.
*
* Returns a string if NET_SSH1_LOGGING == NET_SSH1_LOG_COMPLEX, an array if NET_SSH1_LOGGING == NET_SSH1_LOG_SIMPLE and false if !defined('NET_SSH1_LOGGING')
* Returns a string if NET_SSH1_LOGGING == self::LOG_COMPLEX, an array if NET_SSH1_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SSH1_LOGGING')
*
* @access public
* @return String or Array
* @return array|false|string
*/
function getLog()
{
@ -1423,10 +1386,10 @@ class Net_SSH1
}
switch (NET_SSH1_LOGGING) {
case NET_SSH1_LOG_SIMPLE:
case self::LOG_SIMPLE:
return $this->message_number_log;
break;
case NET_SSH1_LOG_COMPLEX:
case self::LOG_COMPLEX:
return $this->_format_log($this->message_log, $this->protocol_flags_log);
break;
default:
@ -1437,10 +1400,10 @@ class Net_SSH1
/**
* Formats a log for printing
*
* @param Array $message_log
* @param Array $message_number_log
* @param array $message_log
* @param array $message_number_log
* @access private
* @return String
* @return string
*/
function _format_log($message_log, $message_number_log)
{
@ -1473,9 +1436,9 @@ class Net_SSH1
*
* For use with preg_replace_callback()
*
* @param Array $matches
* @param array $matches
* @access private
* @return String
* @return string
*/
function _format_log_helper($matches)
{
@ -1488,8 +1451,8 @@ class Net_SSH1
* Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead,
* the raw bytes. This behavior is similar to PHP's md5() function.
*
* @param optional Boolean $raw_output
* @return String
* @param bool $raw_output
* @return string
* @access public
*/
function getServerKeyPublicExponent($raw_output = false)
@ -1503,8 +1466,8 @@ class Net_SSH1
* Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead,
* the raw bytes. This behavior is similar to PHP's md5() function.
*
* @param optional Boolean $raw_output
* @return String
* @param bool $raw_output
* @return string
* @access public
*/
function getServerKeyPublicModulus($raw_output = false)
@ -1518,8 +1481,8 @@ class Net_SSH1
* Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead,
* the raw bytes. This behavior is similar to PHP's md5() function.
*
* @param optional Boolean $raw_output
* @return String
* @param bool $raw_output
* @return string
* @access public
*/
function getHostKeyPublicExponent($raw_output = false)
@ -1533,8 +1496,8 @@ class Net_SSH1
* Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead,
* the raw bytes. This behavior is similar to PHP's md5() function.
*
* @param optional Boolean $raw_output
* @return String
* @param bool $raw_output
* @return string
* @access public
*/
function getHostKeyPublicModulus($raw_output = false)
@ -1547,10 +1510,10 @@ class Net_SSH1
*
* Just because a cipher is supported by an SSH1 server doesn't mean it's supported by this library. If $raw_output
* is set to true, returns, instead, an array of constants. ie. instead of array('Triple-DES in CBC mode'), you'll
* get array(NET_SSH1_CIPHER_3DES).
* get array(self::CIPHER_3DES).
*
* @param optional Boolean $raw_output
* @return Array
* @param bool $raw_output
* @return array
* @access public
*/
function getSupportedCiphers($raw_output = false)
@ -1563,10 +1526,10 @@ class Net_SSH1
*
* Just because a cipher is supported by an SSH1 server doesn't mean it's supported by this library. If $raw_output
* is set to true, returns, instead, an array of constants. ie. instead of array('password authentication'), you'll
* get array(NET_SSH1_AUTH_PASSWORD).
* get array(self::AUTH_PASSWORD).
*
* @param optional Boolean $raw_output
* @return Array
* @param bool $raw_output
* @return array
* @access public
*/
function getSupportedAuthentications($raw_output = false)
@ -1577,7 +1540,7 @@ class Net_SSH1
/**
* Return the server identification.
*
* @return String
* @return string
* @access public
*/
function getServerIdentification()
@ -1590,23 +1553,23 @@ class Net_SSH1
*
* Makes sure that only the last 1MB worth of packets will be logged
*
* @param String $data
* @param string $data
* @access private
*/
function _append_log($protocol_flags, $message)
{
switch (NET_SSH1_LOGGING) {
// useful for benchmarks
case NET_SSH1_LOG_SIMPLE:
case self::LOG_SIMPLE:
$this->protocol_flags_log[] = $protocol_flags;
break;
// the most useful log for SSH1
case NET_SSH1_LOG_COMPLEX:
case self::LOG_COMPLEX:
$this->protocol_flags_log[] = $protocol_flags;
$this->_string_shift($message);
$this->log_size+= strlen($message);
$this->message_log[] = $message;
while ($this->log_size > NET_SSH1_LOG_MAX_SIZE) {
while ($this->log_size > self::LOG_MAX_SIZE) {
$this->log_size-= strlen(array_shift($this->message_log));
array_shift($this->protocol_flags_log);
}
@ -1614,19 +1577,19 @@ class Net_SSH1
// dump the output out realtime; packets may be interspersed with non packets,
// passwords won't be filtered out and select other packets may not be correctly
// identified
case NET_SSH1_LOG_REALTIME:
case self::LOG_REALTIME:
echo "<pre>\r\n" . $this->_format_log(array($message), array($protocol_flags)) . "\r\n</pre>\r\n";
@flush();
@ob_flush();
break;
// basically the same thing as NET_SSH1_LOG_REALTIME with the caveat that NET_SSH1_LOG_REALTIME_FILE
// needs to be defined and that the resultant log file will be capped out at NET_SSH1_LOG_MAX_SIZE.
// basically the same thing as self::LOG_REALTIME with the caveat that self::LOG_REALTIME_FILE
// needs to be defined and that the resultant log file will be capped out at self::LOG_MAX_SIZE.
// the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily
// at the beginning of the file
case NET_SSH1_LOG_REALTIME_FILE:
case self::LOG_REALTIME_FILE:
if (!isset($this->realtime_log_file)) {
// PHP doesn't seem to like using constants in fopen()
$filename = NET_SSH1_LOG_REALTIME_FILE;
$filename = self::LOG_REALTIME_FILE;
$fp = fopen($filename, 'w');
$this->realtime_log_file = $fp;
}
@ -1640,7 +1603,7 @@ class Net_SSH1
fseek($this->realtime_log_file, ftell($this->realtime_log_file) - strlen($temp));
}
$this->realtime_log_size+= strlen($entry);
if ($this->realtime_log_size > NET_SSH1_LOG_MAX_SIZE) {
if ($this->realtime_log_size > self::LOG_MAX_SIZE) {
fseek($this->realtime_log_file, 0);
$this->realtime_log_size = strlen($entry);
$this->realtime_log_wrap = true;

View file

@ -3,14 +3,14 @@
/**
* Pure-PHP implementation of SSHv2.
*
* PHP versions 4 and 5
* PHP version 5
*
* Here are some examples of how to use this library:
* <code>
* <?php
* include 'Net/SSH2.php';
* include 'vendor/autoload.php';
*
* $ssh = new Net_SSH2('www.domain.tld');
* $ssh = new \phpseclib\Net\SSH2('www.domain.tld');
* if (!$ssh->login('username', 'password')) {
* exit('Login Failed');
* }
@ -22,14 +22,13 @@
*
* <code>
* <?php
* include 'Crypt/RSA.php';
* include 'Net/SSH2.php';
* include 'vendor/autoload.php';
*
* $key = new Crypt_RSA();
* $key = new \phpseclib\Crypt\RSA();
* //$key->setPassword('whatever');
* $key->loadKey(file_get_contents('privatekey'));
*
* $ssh = new Net_SSH2('www.domain.tld');
* $ssh = new \phpseclib\Net\SSH2('www.domain.tld');
* if (!$ssh->login('username', $key)) {
* exit('Login Failed');
* }
@ -40,120 +39,117 @@
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Net
* @package Net_SSH2
* @package SSH2
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**#@+
* Execution Bitmap Masks
*
* @see Net_SSH2::bitmap
* @access private
*/
define('NET_SSH2_MASK_CONSTRUCTOR', 0x00000001);
define('NET_SSH2_MASK_CONNECTED', 0x00000002);
define('NET_SSH2_MASK_LOGIN_REQ', 0x00000004);
define('NET_SSH2_MASK_LOGIN', 0x00000008);
define('NET_SSH2_MASK_SHELL', 0x00000010);
define('NET_SSH2_MASK_WINDOW_ADJUST', 0x00000020);
/**#@-*/
namespace phpseclib\Net;
/**#@+
* Channel constants
*
* RFC4254 refers not to client and server channels but rather to sender and recipient channels. we don't refer
* to them in that way because RFC4254 toggles the meaning. the client sends a SSH_MSG_CHANNEL_OPEN message with
* a sender channel and the server sends a SSH_MSG_CHANNEL_OPEN_CONFIRMATION in response, with a sender and a
* recepient channel. at first glance, you might conclude that SSH_MSG_CHANNEL_OPEN_CONFIRMATION's sender channel
* would be the same thing as SSH_MSG_CHANNEL_OPEN's sender channel, but it's not, per this snipet:
* The 'recipient channel' is the channel number given in the original
* open request, and 'sender channel' is the channel number allocated by
* the other side.
*
* @see Net_SSH2::_send_channel_packet()
* @see Net_SSH2::_get_channel_packet()
* @access private
*/
define('NET_SSH2_CHANNEL_EXEC', 0); // PuTTy uses 0x100
define('NET_SSH2_CHANNEL_SHELL', 1);
define('NET_SSH2_CHANNEL_SUBSYSTEM', 2);
/**#@-*/
/**#@+
* @access public
* @see Net_SSH2::getLog()
*/
/**
* Returns the message numbers
*/
define('NET_SSH2_LOG_SIMPLE', 1);
/**
* Returns the message content
*/
define('NET_SSH2_LOG_COMPLEX', 2);
/**
* Outputs the content real-time
*/
define('NET_SSH2_LOG_REALTIME', 3);
/**
* Dumps the content real-time to a file
*/
define('NET_SSH2_LOG_REALTIME_FILE', 4);
/**#@-*/
/**#@+
* @access public
* @see Net_SSH2::read()
*/
/**
* Returns when a string matching $expect exactly is found
*/
define('NET_SSH2_READ_SIMPLE', 1);
/**
* Returns when a string matching the regular expression $expect is found
*/
define('NET_SSH2_READ_REGEX', 2);
/**
* Make sure that the log never gets larger than this
*/
define('NET_SSH2_LOG_MAX_SIZE', 1024 * 1024);
/**#@-*/
use phpseclib\Crypt\Base;
use phpseclib\Crypt\Blowfish;
use phpseclib\Crypt\Hash;
use phpseclib\Crypt\Random;
use phpseclib\Crypt\RC4;
use phpseclib\Crypt\Rijndael;
use phpseclib\Crypt\RSA;
use phpseclib\Crypt\TripleDES;
use phpseclib\Crypt\Twofish;
use phpseclib\Math\BigInteger; // Used to do Diffie-Hellman key exchange and DSA/RSA signature verification.
use phpseclib\System\SSH\Agent;
/**
* Pure-PHP implementation of SSHv2.
*
* @package Net_SSH2
* @package SSH2
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Net_SSH2
class SSH2
{
/**#@+
* Execution Bitmap Masks
*
* @see \phpseclib\Net\SSH2::bitmap
* @access private
*/
const MASK_CONSTRUCTOR = 0x00000001;
const MASK_CONNECTED = 0x00000002;
const MASK_LOGIN_REQ = 0x00000004;
const MASK_LOGIN = 0x00000008;
const MASK_SHELL = 0x00000010;
const MASK_WINDOW_ADJUST = 0x00000020;
/**#@-*/
/**#@+
* Channel constants
*
* RFC4254 refers not to client and server channels but rather to sender and recipient channels. we don't refer
* to them in that way because RFC4254 toggles the meaning. the client sends a SSH_MSG_CHANNEL_OPEN message with
* a sender channel and the server sends a SSH_MSG_CHANNEL_OPEN_CONFIRMATION in response, with a sender and a
* recepient channel. at first glance, you might conclude that SSH_MSG_CHANNEL_OPEN_CONFIRMATION's sender channel
* would be the same thing as SSH_MSG_CHANNEL_OPEN's sender channel, but it's not, per this snipet:
* The 'recipient channel' is the channel number given in the original
* open request, and 'sender channel' is the channel number allocated by
* the other side.
*
* @see \phpseclib\Net\SSH2::_send_channel_packet()
* @see \phpseclib\Net\SSH2::_get_channel_packet()
* @access private
*/
const CHANNEL_EXEC = 0; // PuTTy uses 0x100
const CHANNEL_SHELL = 1;
const CHANNEL_SUBSYSTEM = 2;
const CHANNEL_AGENT_FORWARD = 3;
/**#@-*/
/**#@+
* @access public
* @see \phpseclib\Net\SSH2::getLog()
*/
/**
* Returns the message numbers
*/
const LOG_SIMPLE = 1;
/**
* Returns the message content
*/
const LOG_COMPLEX = 2;
/**
* Outputs the content real-time
*/
const LOG_REALTIME = 3;
/**
* Dumps the content real-time to a file
*/
const LOG_REALTIME_FILE = 4;
/**#@-*/
/**#@+
* @access public
* @see \phpseclib\Net\SSH2::read()
*/
/**
* Returns when a string matching $expect exactly is found
*/
const READ_SIMPLE = 1;
/**
* Returns when a string matching the regular expression $expect is found
*/
const READ_REGEX = 2;
/**
* Make sure that the log never gets larger than this
*/
const LOG_MAX_SIZE = 1048576; // 1024 * 1024
/**#@-*/
/**
* The SSH identifier
*
* @var String
* @var string
* @access private
*/
var $identifier;
@ -161,7 +157,7 @@ class Net_SSH2
/**
* The Socket Object
*
* @var Object
* @var object
* @access private
*/
var $fsock;
@ -172,7 +168,7 @@ class Net_SSH2
* The bits that are set represent functions that have been called already. This is used to determine
* if a requisite function has been successfully executed. If not, an error should be thrown.
*
* @var Integer
* @var int
* @access private
*/
var $bitmap = 0;
@ -180,9 +176,9 @@ class Net_SSH2
/**
* Error information
*
* @see Net_SSH2::getErrors()
* @see Net_SSH2::getLastError()
* @var String
* @see self::getErrors()
* @see self::getLastError()
* @var string
* @access private
*/
var $errors = array();
@ -190,8 +186,8 @@ class Net_SSH2
/**
* Server Identifier
*
* @see Net_SSH2::getServerIdentification()
* @var mixed false or Array
* @see self::getServerIdentification()
* @var array|false
* @access private
*/
var $server_identifier = false;
@ -199,17 +195,44 @@ class Net_SSH2
/**
* Key Exchange Algorithms
*
* @see Net_SSH2::getKexAlgorithims()
* @var mixed false or Array
* @see self::getKexAlgorithims()
* @var array|false
* @access private
*/
var $kex_algorithms = false;
/**
* Minimum Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods
*
* @see self::_key_exchange()
* @var int
* @access private
*/
var $kex_dh_group_size_min = 1536;
/**
* Preferred Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods
*
* @see self::_key_exchange()
* @var int
* @access private
*/
var $kex_dh_group_size_preferred = 2048;
/**
* Maximum Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods
*
* @see self::_key_exchange()
* @var int
* @access private
*/
var $kex_dh_group_size_max = 4096;
/**
* Server Host Key Algorithms
*
* @see Net_SSH2::getServerHostKeyAlgorithms()
* @var mixed false or Array
* @see self::getServerHostKeyAlgorithms()
* @var array|false
* @access private
*/
var $server_host_key_algorithms = false;
@ -217,8 +240,8 @@ class Net_SSH2
/**
* Encryption Algorithms: Client to Server
*
* @see Net_SSH2::getEncryptionAlgorithmsClient2Server()
* @var mixed false or Array
* @see self::getEncryptionAlgorithmsClient2Server()
* @var array|false
* @access private
*/
var $encryption_algorithms_client_to_server = false;
@ -226,8 +249,8 @@ class Net_SSH2
/**
* Encryption Algorithms: Server to Client
*
* @see Net_SSH2::getEncryptionAlgorithmsServer2Client()
* @var mixed false or Array
* @see self::getEncryptionAlgorithmsServer2Client()
* @var array|false
* @access private
*/
var $encryption_algorithms_server_to_client = false;
@ -235,8 +258,8 @@ class Net_SSH2
/**
* MAC Algorithms: Client to Server
*
* @see Net_SSH2::getMACAlgorithmsClient2Server()
* @var mixed false or Array
* @see self::getMACAlgorithmsClient2Server()
* @var array|false
* @access private
*/
var $mac_algorithms_client_to_server = false;
@ -244,8 +267,8 @@ class Net_SSH2
/**
* MAC Algorithms: Server to Client
*
* @see Net_SSH2::getMACAlgorithmsServer2Client()
* @var mixed false or Array
* @see self::getMACAlgorithmsServer2Client()
* @var array|false
* @access private
*/
var $mac_algorithms_server_to_client = false;
@ -253,8 +276,8 @@ class Net_SSH2
/**
* Compression Algorithms: Client to Server
*
* @see Net_SSH2::getCompressionAlgorithmsClient2Server()
* @var mixed false or Array
* @see self::getCompressionAlgorithmsClient2Server()
* @var array|false
* @access private
*/
var $compression_algorithms_client_to_server = false;
@ -262,8 +285,8 @@ class Net_SSH2
/**
* Compression Algorithms: Server to Client
*
* @see Net_SSH2::getCompressionAlgorithmsServer2Client()
* @var mixed false or Array
* @see self::getCompressionAlgorithmsServer2Client()
* @var array|false
* @access private
*/
var $compression_algorithms_server_to_client = false;
@ -271,8 +294,8 @@ class Net_SSH2
/**
* Languages: Server to Client
*
* @see Net_SSH2::getLanguagesServer2Client()
* @var mixed false or Array
* @see self::getLanguagesServer2Client()
* @var array|false
* @access private
*/
var $languages_server_to_client = false;
@ -280,8 +303,8 @@ class Net_SSH2
/**
* Languages: Client to Server
*
* @see Net_SSH2::getLanguagesClient2Server()
* @var mixed false or Array
* @see self::getLanguagesClient2Server()
* @var array|false
* @access private
*/
var $languages_client_to_server = false;
@ -296,9 +319,9 @@ class Net_SSH2
*
* -- http://tools.ietf.org/html/rfc4253#section-6
*
* @see Net_SSH2::Net_SSH2()
* @see Net_SSH2::_send_binary_packet()
* @var Integer
* @see self::__construct()
* @see self::_send_binary_packet()
* @var int
* @access private
*/
var $encrypt_block_size = 8;
@ -306,9 +329,9 @@ class Net_SSH2
/**
* Block Size for Client to Server Encryption
*
* @see Net_SSH2::Net_SSH2()
* @see Net_SSH2::_get_binary_packet()
* @var Integer
* @see self::__construct()
* @see self::_get_binary_packet()
* @var int
* @access private
*/
var $decrypt_block_size = 8;
@ -316,8 +339,8 @@ class Net_SSH2
/**
* Server to Client Encryption Object
*
* @see Net_SSH2::_get_binary_packet()
* @var Object
* @see self::_get_binary_packet()
* @var object
* @access private
*/
var $decrypt = false;
@ -325,8 +348,8 @@ class Net_SSH2
/**
* Client to Server Encryption Object
*
* @see Net_SSH2::_send_binary_packet()
* @var Object
* @see self::_send_binary_packet()
* @var object
* @access private
*/
var $encrypt = false;
@ -334,8 +357,8 @@ class Net_SSH2
/**
* Client to Server HMAC Object
*
* @see Net_SSH2::_send_binary_packet()
* @var Object
* @see self::_send_binary_packet()
* @var object
* @access private
*/
var $hmac_create = false;
@ -343,8 +366,8 @@ class Net_SSH2
/**
* Server to Client HMAC Object
*
* @see Net_SSH2::_get_binary_packet()
* @var Object
* @see self::_get_binary_packet()
* @var object
* @access private
*/
var $hmac_check = false;
@ -356,8 +379,8 @@ class Net_SSH2
* For the client to server side, the HMAC object will make the HMAC as long as it needs to be. All we need to do is
* append it.
*
* @see Net_SSH2::_get_binary_packet()
* @var Integer
* @see self::_get_binary_packet()
* @var int
* @access private
*/
var $hmac_size = false;
@ -365,14 +388,14 @@ class Net_SSH2
/**
* Server Public Host Key
*
* @see Net_SSH2::getServerPublicHostKey()
* @var String
* @see self::getServerPublicHostKey()
* @var string
* @access private
*/
var $server_public_host_key;
/**
* Session identifer
* Session identifier
*
* "The exchange hash H from the first key exchange is additionally
* used as the session identifier, which is a unique identifier for
@ -380,8 +403,8 @@ class Net_SSH2
*
* -- http://tools.ietf.org/html/rfc4253#section-7.2
*
* @see Net_SSH2::_key_exchange()
* @var String
* @see self::_key_exchange()
* @var string
* @access private
*/
var $session_id = false;
@ -391,8 +414,8 @@ class Net_SSH2
*
* The current exchange hash
*
* @see Net_SSH2::_key_exchange()
* @var String
* @see self::_key_exchange()
* @var string
* @access private
*/
var $exchange_hash = false;
@ -400,8 +423,8 @@ class Net_SSH2
/**
* Message Numbers
*
* @see Net_SSH2::Net_SSH2()
* @var Array
* @see self::__construct()
* @var array
* @access private
*/
var $message_numbers = array();
@ -409,8 +432,8 @@ class Net_SSH2
/**
* Disconnection Message 'reason codes' defined in RFC4253
*
* @see Net_SSH2::Net_SSH2()
* @var Array
* @see self::__construct()
* @var array
* @access private
*/
var $disconnect_reasons = array();
@ -418,8 +441,8 @@ class Net_SSH2
/**
* SSH_MSG_CHANNEL_OPEN_FAILURE 'reason codes', defined in RFC4254
*
* @see Net_SSH2::Net_SSH2()
* @var Array
* @see self::__construct()
* @var array
* @access private
*/
var $channel_open_failure_reasons = array();
@ -428,8 +451,8 @@ class Net_SSH2
* Terminal Modes
*
* @link http://tools.ietf.org/html/rfc4254#section-8
* @see Net_SSH2::Net_SSH2()
* @var Array
* @see self::__construct()
* @var array
* @access private
*/
var $terminal_modes = array();
@ -438,8 +461,8 @@ class Net_SSH2
* SSH_MSG_CHANNEL_EXTENDED_DATA's data_type_codes
*
* @link http://tools.ietf.org/html/rfc4254#section-5.2
* @see Net_SSH2::Net_SSH2()
* @var Array
* @see self::__construct()
* @var array
* @access private
*/
var $channel_extended_data_type_codes = array();
@ -449,8 +472,8 @@ class Net_SSH2
*
* See 'Section 6.4. Data Integrity' of rfc4253 for more info.
*
* @see Net_SSH2::_send_binary_packet()
* @var Integer
* @see self::_send_binary_packet()
* @var int
* @access private
*/
var $send_seq_no = 0;
@ -460,8 +483,8 @@ class Net_SSH2
*
* See 'Section 6.4. Data Integrity' of rfc4253 for more info.
*
* @see Net_SSH2::_get_binary_packet()
* @var Integer
* @see self::_get_binary_packet()
* @var int
* @access private
*/
var $get_seq_no = 0;
@ -471,9 +494,9 @@ class Net_SSH2
*
* Maps client channels to server channels
*
* @see Net_SSH2::_get_channel_packet()
* @see Net_SSH2::exec()
* @var Array
* @see self::_get_channel_packet()
* @see self::exec()
* @var array
* @access private
*/
var $server_channels = array();
@ -484,9 +507,9 @@ class Net_SSH2
* If a client requests a packet from one channel but receives two packets from another those packets should
* be placed in a buffer
*
* @see Net_SSH2::_get_channel_packet()
* @see Net_SSH2::exec()
* @var Array
* @see self::_get_channel_packet()
* @see self::exec()
* @var array
* @access private
*/
var $channel_buffers = array();
@ -496,8 +519,8 @@ class Net_SSH2
*
* Contains the type of the last sent message
*
* @see Net_SSH2::_get_channel_packet()
* @var Array
* @see self::_get_channel_packet()
* @var array
* @access private
*/
var $channel_status = array();
@ -507,8 +530,8 @@ class Net_SSH2
*
* Maximum packet size indexed by channel
*
* @see Net_SSH2::_send_channel_packet()
* @var Array
* @see self::_send_channel_packet()
* @var array
* @access private
*/
var $packet_size_client_to_server = array();
@ -516,8 +539,8 @@ class Net_SSH2
/**
* Message Number Log
*
* @see Net_SSH2::getLog()
* @var Array
* @see self::getLog()
* @var array
* @access private
*/
var $message_number_log = array();
@ -525,8 +548,8 @@ class Net_SSH2
/**
* Message Log
*
* @see Net_SSH2::getLog()
* @var Array
* @see self::getLog()
* @var array
* @access private
*/
var $message_log = array();
@ -536,9 +559,9 @@ class Net_SSH2
*
* Bytes the other party can send before it must wait for the window to be adjusted (0x7FFFFFFF = 2GB)
*
* @var Integer
* @see Net_SSH2::_send_channel_packet()
* @see Net_SSH2::exec()
* @var int
* @see self::_send_channel_packet()
* @see self::exec()
* @access private
*/
var $window_size = 0x7FFFFFFF;
@ -548,8 +571,8 @@ class Net_SSH2
*
* Window size indexed by channel
*
* @see Net_SSH2::_send_channel_packet()
* @var Array
* @see self::_send_channel_packet()
* @var array
* @access private
*/
var $window_size_server_to_client = array();
@ -559,8 +582,8 @@ class Net_SSH2
*
* Window size indexed by channel
*
* @see Net_SSH2::_get_channel_packet()
* @var Array
* @see self::_get_channel_packet()
* @var array
* @access private
*/
var $window_size_client_to_server = array();
@ -570,8 +593,8 @@ class Net_SSH2
*
* Verified against $this->session_id
*
* @see Net_SSH2::getServerPublicHostKey()
* @var String
* @see self::getServerPublicHostKey()
* @var string
* @access private
*/
var $signature = '';
@ -581,8 +604,8 @@ class Net_SSH2
*
* ssh-rsa or ssh-dss.
*
* @see Net_SSH2::getServerPublicHostKey()
* @var String
* @see self::getServerPublicHostKey()
* @var string
* @access private
*/
var $signature_format = '';
@ -590,8 +613,8 @@ class Net_SSH2
/**
* Interactive Buffer
*
* @see Net_SSH2::read()
* @var Array
* @see self::read()
* @var array
* @access private
*/
var $interactiveBuffer = '';
@ -599,11 +622,11 @@ class Net_SSH2
/**
* Current log size
*
* Should never exceed NET_SSH2_LOG_MAX_SIZE
* Should never exceed self::LOG_MAX_SIZE
*
* @see Net_SSH2::_send_binary_packet()
* @see Net_SSH2::_get_binary_packet()
* @var Integer
* @see self::_send_binary_packet()
* @see self::_get_binary_packet()
* @var int
* @access private
*/
var $log_size;
@ -611,7 +634,7 @@ class Net_SSH2
/**
* Timeout
*
* @see Net_SSH2::setTimeout()
* @see self::setTimeout()
* @access private
*/
var $timeout;
@ -619,7 +642,7 @@ class Net_SSH2
/**
* Current Timeout
*
* @see Net_SSH2::_get_channel_packet()
* @see self::_get_channel_packet()
* @access private
*/
var $curTimeout;
@ -627,8 +650,8 @@ class Net_SSH2
/**
* Real-time log file pointer
*
* @see Net_SSH2::_append_log()
* @var Resource
* @see self::_append_log()
* @var resource
* @access private
*/
var $realtime_log_file;
@ -636,8 +659,8 @@ class Net_SSH2
/**
* Real-time log file size
*
* @see Net_SSH2::_append_log()
* @var Integer
* @see self::_append_log()
* @var int
* @access private
*/
var $realtime_log_size;
@ -645,8 +668,8 @@ class Net_SSH2
/**
* Has the signature been validated?
*
* @see Net_SSH2::getServerPublicHostKey()
* @var Boolean
* @see self::getServerPublicHostKey()
* @var bool
* @access private
*/
var $signature_validated = false;
@ -654,7 +677,7 @@ class Net_SSH2
/**
* Real-time log file wrap boolean
*
* @see Net_SSH2::_append_log()
* @see self::_append_log()
* @access private
*/
var $realtime_log_wrap;
@ -662,7 +685,7 @@ class Net_SSH2
/**
* Flag to suppress stderr from output
*
* @see Net_SSH2::enableQuietMode()
* @see self::enableQuietMode()
* @access private
*/
var $quiet_mode = false;
@ -670,7 +693,7 @@ class Net_SSH2
/**
* Time of first network activity
*
* @var Integer
* @var int
* @access private
*/
var $last_packet;
@ -678,7 +701,7 @@ class Net_SSH2
/**
* Exit status returned from ssh if any
*
* @var Integer
* @var int
* @access private
*/
var $exit_status;
@ -686,8 +709,8 @@ class Net_SSH2
/**
* Flag to request a PTY when using exec()
*
* @var Boolean
* @see Net_SSH2::enablePTY()
* @var bool
* @see self::enablePTY()
* @access private
*/
var $request_pty = false;
@ -695,7 +718,7 @@ class Net_SSH2
/**
* Flag set while exec() is running when using enablePTY()
*
* @var Boolean
* @var bool
* @access private
*/
var $in_request_pty_exec = false;
@ -703,7 +726,7 @@ class Net_SSH2
/**
* Flag set after startSubsystem() is called
*
* @var Boolean
* @var bool
* @access private
*/
var $in_subsystem;
@ -711,7 +734,7 @@ class Net_SSH2
/**
* Contents of stdError
*
* @var String
* @var string
* @access private
*/
var $stdErrorLog;
@ -719,8 +742,8 @@ class Net_SSH2
/**
* The Last Interactive Response
*
* @see Net_SSH2::_keyboard_interactive_process()
* @var String
* @see self::_keyboard_interactive_process()
* @var string
* @access private
*/
var $last_interactive_response = '';
@ -728,8 +751,8 @@ class Net_SSH2
/**
* Keyboard Interactive Request / Responses
*
* @see Net_SSH2::_keyboard_interactive_process()
* @var Array
* @see self::_keyboard_interactive_process()
* @var array
* @access private
*/
var $keyboard_requests_responses = array();
@ -740,9 +763,9 @@ class Net_SSH2
* Quoting from the RFC, "in some jurisdictions, sending a warning message before
* authentication may be relevant for getting legal protection."
*
* @see Net_SSH2::_filter()
* @see Net_SSH2::getBannerMessage()
* @var String
* @see self::_filter()
* @see self::getBannerMessage()
* @var string
* @access private
*/
var $banner_message = '';
@ -750,8 +773,8 @@ class Net_SSH2
/**
* Did read() timeout or return normally?
*
* @see Net_SSH2::isTimeout()
* @var Boolean
* @see self::isTimeout()
* @var bool
* @access private
*/
var $is_timeout = false;
@ -759,8 +782,8 @@ class Net_SSH2
/**
* Log Boundary
*
* @see Net_SSH2::_format_log()
* @var String
* @see self::_format_log()
* @var string
* @access private
*/
var $log_boundary = ':';
@ -768,8 +791,8 @@ class Net_SSH2
/**
* Log Long Width
*
* @see Net_SSH2::_format_log()
* @var Integer
* @see self::_format_log()
* @var int
* @access private
*/
var $log_long_width = 65;
@ -777,8 +800,8 @@ class Net_SSH2
/**
* Log Short Width
*
* @see Net_SSH2::_format_log()
* @var Integer
* @see self::_format_log()
* @var int
* @access private
*/
var $log_short_width = 16;
@ -786,9 +809,9 @@ class Net_SSH2
/**
* Hostname
*
* @see Net_SSH2::Net_SSH2()
* @see Net_SSH2::_connect()
* @var String
* @see self::__construct()
* @see self::_connect()
* @var string
* @access private
*/
var $host;
@ -796,35 +819,20 @@ class Net_SSH2
/**
* Port Number
*
* @see Net_SSH2::Net_SSH2()
* @see Net_SSH2::_connect()
* @var Integer
* @see self::__construct()
* @see self::_connect()
* @var int
* @access private
*/
var $port;
/**
* Timeout for initial connection
*
* Set by the constructor call. Calling setTimeout() is optional. If it's not called functions like
* exec() won't timeout unless some PHP setting forces it too. The timeout specified in the constructor,
* however, is non-optional. There will be a timeout, whether or not you set it. If you don't it'll be
* 10 seconds. It is used by fsockopen() and the initial stream_select in that function.
*
* @see Net_SSH2::Net_SSH2()
* @see Net_SSH2::_connect()
* @var Integer
* @access private
*/
var $connectionTimeout;
/**
* Number of columns for terminal window size
*
* @see Net_SSH2::getWindowColumns()
* @see Net_SSH2::setWindowColumns()
* @see Net_SSH2::setWindowSize()
* @var Integer
* @see self::getWindowColumns()
* @see self::setWindowColumns()
* @see self::setWindowSize()
* @var int
* @access private
*/
var $windowColumns = 80;
@ -832,40 +840,46 @@ class Net_SSH2
/**
* Number of columns for terminal window size
*
* @see Net_SSH2::getWindowRows()
* @see Net_SSH2::setWindowRows()
* @see Net_SSH2::setWindowSize()
* @var Integer
* @see self::getWindowRows()
* @see self::setWindowRows()
* @see self::setWindowSize()
* @var int
* @access private
*/
var $windowRows = 24;
/**
* Crypto Engine
*
* @see self::setCryptoEngine()
* @see self::_key_exchange()
* @var int
* @access private
*/
var $crypto_engine = false;
/**
* A System_SSH_Agent for use in the SSH2 Agent Forwarding scenario
*
* @var System_SSH_Agent
* @access private
*/
var $agent;
/**
* Default Constructor.
*
* @param String $host
* @param optional Integer $port
* @param optional Integer $timeout
* @see Net_SSH2::login()
* @return Net_SSH2
* $host can either be a string, representing the host, or a stream resource.
*
* @param mixed $host
* @param int $port
* @param int $timeout
* @see self::login()
* @return \phpseclib\Net\SSH2
* @access public
*/
function Net_SSH2($host, $port = 22, $timeout = 10)
function __construct($host, $port = 22, $timeout = 10)
{
// Include Math_BigInteger
// Used to do Diffie-Hellman key exchange and DSA/RSA signature verification.
if (!class_exists('Math_BigInteger')) {
include_once 'Math/BigInteger.php';
}
if (!function_exists('crypt_random_string')) {
include_once 'Crypt/Random.php';
}
if (!class_exists('Crypt_Hash')) {
include_once 'Crypt/Hash.php';
}
$this->message_numbers = array(
1 => 'NET_SSH2_MSG_DISCONNECT',
2 => 'NET_SSH2_MSG_IGNORE',
@ -933,59 +947,78 @@ class Net_SSH2
array(60 => 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ'),
array(60 => 'NET_SSH2_MSG_USERAUTH_PK_OK'),
array(60 => 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST',
61 => 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE')
61 => 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE'),
// RFC 4419 - diffie-hellman-group-exchange-sha{1,256}
array(30 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST_OLD',
31 => 'NET_SSH2_MSG_KEXDH_GEX_GROUP',
32 => 'NET_SSH2_MSG_KEXDH_GEX_INIT',
33 => 'NET_SSH2_MSG_KEXDH_GEX_REPLY',
34 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST'),
// RFC 5656 - Elliptic Curves (for curve25519-sha256@libssh.org)
array(30 => 'NET_SSH2_MSG_KEX_ECDH_INIT',
31 => 'NET_SSH2_MSG_KEX_ECDH_REPLY')
);
$this->host = $host;
$this->port = $port;
$this->connectionTimeout = $timeout;
if (is_resource($host)) {
$this->fsock = $host;
return;
}
if (is_string($host)) {
$this->host = $host;
$this->port = $port;
$this->timeout = $timeout;
}
}
/**
* Set Crypto Engine Mode
*
* Possible $engine values:
* CRYPT_MODE_INTERNAL, CRYPT_MODE_MCRYPT
*
* @param int $engine
* @access private
*/
function setCryptoEngine($engine)
{
$this->crypto_engine = $engine;
}
/**
* Connect to an SSHv2 server
*
* @return Boolean
* @return bool
* @access private
*/
function _connect()
{
if ($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR) {
if ($this->bitmap & self::MASK_CONSTRUCTOR) {
return false;
}
$this->bitmap |= NET_SSH2_MASK_CONSTRUCTOR;
$this->bitmap |= self::MASK_CONSTRUCTOR;
$timeout = $this->connectionTimeout;
$host = $this->host . ':' . $this->port;
$this->curTimeout = $this->timeout;
$this->last_packet = strtok(microtime(), ' ') + strtok(''); // == microtime(true) in PHP5
$this->last_packet = microtime(true);
$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
$this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $timeout);
if (!$this->fsock) {
user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"));
return false;
}
$elapsed = strtok(microtime(), ' ') + strtok('') - $start;
if (!is_resource($this->fsock)) {
$start = microtime(true);
$this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout);
if (!$this->fsock) {
$host = $this->host . ':' . $this->port;
user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"));
return false;
}
$elapsed = microtime(true) - $start;
$timeout-= $elapsed;
$this->curTimeout-= $elapsed;
if ($timeout <= 0) {
user_error("Cannot connect to $host. Timeout error");
return false;
}
$read = array($this->fsock);
$write = $except = null;
$sec = floor($timeout);
$usec = 1000000 * ($timeout - $sec);
// on windows this returns a "Warning: Invalid CRT parameters detected" error
// the !count() is done as a workaround for <https://bugs.php.net/42682>
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
user_error("Cannot connect to $host. Banner timeout");
return false;
if ($this->curTimeout <= 0) {
$this->is_timeout = true;
return false;
}
}
/* According to the SSH2 specs,
@ -995,14 +1028,51 @@ class Net_SSH2
Feed. Such lines MUST NOT begin with "SSH-", and SHOULD be encoded
in ISO-10646 UTF-8 [RFC3629] (language is not specified). Clients
MUST be able to process such lines." */
$temp = '';
$extra = '';
while (!feof($this->fsock) && !preg_match('#^SSH-(\d\.\d+)#', $temp, $matches)) {
if (substr($temp, -2) == "\r\n") {
$extra.= $temp;
$temp = '';
$data = '';
while (!feof($this->fsock) && !preg_match('#(.*)^(SSH-(\d\.\d+).*)#ms', $data, $matches)) {
$line = '';
while (true) {
if ($this->curTimeout) {
if ($this->curTimeout < 0) {
$this->is_timeout = true;
return false;
}
$read = array($this->fsock);
$write = $except = null;
$start = microtime(true);
$sec = floor($this->curTimeout);
$usec = 1000000 * ($this->curTimeout - $sec);
// on windows this returns a "Warning: Invalid CRT parameters detected" error
// the !count() is done as a workaround for <https://bugs.php.net/42682>
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
$this->is_timeout = true;
return false;
}
$elapsed = microtime(true) - $start;
$this->curTimeout-= $elapsed;
}
$temp = stream_get_line($this->fsock, 255, "\n");
if (strlen($temp) == 255) {
continue;
}
$line.= "$temp\n";
// quoting RFC4253, "Implementers who wish to maintain
// compatibility with older, undocumented versions of this protocol may
// want to process the identification string without expecting the
// presence of the carriage return character for reasons described in
// Section 5 of this document."
//if (substr($line, -2) == "\r\n") {
// break;
//}
break;
}
$temp.= fgets($this->fsock, 255);
$data.= $line;
}
if (feof($this->fsock)) {
@ -1010,20 +1080,22 @@ class Net_SSH2
return false;
}
$extra = $matches[1];
$this->identifier = $this->_generate_identifier();
if (defined('NET_SSH2_LOGGING')) {
$this->_append_log('<-', $extra . $temp);
$this->_append_log('<-', $matches[0]);
$this->_append_log('->', $this->identifier . "\r\n");
}
$this->server_identifier = trim($temp, "\r\n");
if (strlen($extra)) {
$this->errors[] = utf8_decode($extra);
$this->errors[] = utf8_decode($data);
}
if ($matches[1] != '1.99' && $matches[1] != '2.0') {
user_error("Cannot connect to SSH $matches[1] servers");
if ($matches[3] != '1.99' && $matches[3] != '2.0') {
user_error("Cannot connect to SSH $matches[3] servers");
return false;
}
@ -1044,7 +1116,7 @@ class Net_SSH2
return false;
}
$this->bitmap|= NET_SSH2_MASK_CONNECTED;
$this->bitmap|= self::MASK_CONNECTED;
return true;
}
@ -1055,14 +1127,20 @@ class Net_SSH2
* You should overwrite this method in your own class if you want to use another identifier
*
* @access protected
* @return String
* @return string
*/
function _generate_identifier()
{
$identifier = 'SSH-2.0-phpseclib_0.3';
$identifier = 'SSH-2.0-phpseclib_2.0';
$ext = array();
if (extension_loaded('mcrypt')) {
if (extension_loaded('libsodium')) {
$ext[] = 'libsodium';
}
if (extension_loaded('openssl')) {
$ext[] = 'openssl';
} elseif (extension_loaded('mcrypt')) {
$ext[] = 'mcrypt';
}
@ -1082,92 +1160,113 @@ class Net_SSH2
/**
* Key Exchange
*
* @param String $kexinit_payload_server
* @param string $kexinit_payload_server
* @access private
*/
function _key_exchange($kexinit_payload_server)
{
static $kex_algorithms = array(
'diffie-hellman-group1-sha1', // REQUIRED
'diffie-hellman-group14-sha1' // REQUIRED
);
$kex_algorithms = array(
// Elliptic Curve Diffie-Hellman Key Agreement (ECDH) using
// Curve25519. See doc/curve25519-sha256@libssh.org.txt in the
// libssh repository for more information.
'curve25519-sha256@libssh.org',
static $server_host_key_algorithms = array(
// Diffie-Hellman Key Agreement (DH) using integer modulo prime
// groups.
'diffie-hellman-group1-sha1', // REQUIRED
'diffie-hellman-group14-sha1', // REQUIRED
'diffie-hellman-group-exchange-sha1', // RFC 4419
'diffie-hellman-group-exchange-sha256', // RFC 4419
);
if (!function_exists('\\Sodium\\library_version_major')) {
$kex_algorithms = array_diff(
$kex_algorithms,
array('curve25519-sha256@libssh.org')
);
}
$server_host_key_algorithms = array(
'ssh-rsa', // RECOMMENDED sign Raw RSA Key
'ssh-dss' // REQUIRED sign Raw DSS Key
);
static $encryption_algorithms = false;
if ($encryption_algorithms === false) {
$encryption_algorithms = array(
// from <http://tools.ietf.org/html/rfc4345#section-4>:
'arcfour256',
'arcfour128',
$encryption_algorithms = array(
// from <http://tools.ietf.org/html/rfc4345#section-4>:
'arcfour256',
'arcfour128',
//'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key
//'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key
// CTR modes from <http://tools.ietf.org/html/rfc4344#section-4>:
'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key
'aes192-ctr', // RECOMMENDED AES with 192-bit key
'aes256-ctr', // RECOMMENDED AES with 256-bit key
// CTR modes from <http://tools.ietf.org/html/rfc4344#section-4>:
'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key
'aes192-ctr', // RECOMMENDED AES with 192-bit key
'aes256-ctr', // RECOMMENDED AES with 256-bit key
'twofish128-ctr', // OPTIONAL Twofish in SDCTR mode, with 128-bit key
'twofish192-ctr', // OPTIONAL Twofish with 192-bit key
'twofish256-ctr', // OPTIONAL Twofish with 256-bit key
'twofish128-ctr', // OPTIONAL Twofish in SDCTR mode, with 128-bit key
'twofish192-ctr', // OPTIONAL Twofish with 192-bit key
'twofish256-ctr', // OPTIONAL Twofish with 256-bit key
'aes128-cbc', // RECOMMENDED AES with a 128-bit key
'aes192-cbc', // OPTIONAL AES with a 192-bit key
'aes256-cbc', // OPTIONAL AES in CBC mode, with a 256-bit key
'aes128-cbc', // RECOMMENDED AES with a 128-bit key
'aes192-cbc', // OPTIONAL AES with a 192-bit key
'aes256-cbc', // OPTIONAL AES in CBC mode, with a 256-bit key
'twofish128-cbc', // OPTIONAL Twofish with a 128-bit key
'twofish192-cbc', // OPTIONAL Twofish with a 192-bit key
'twofish256-cbc',
'twofish-cbc', // OPTIONAL alias for "twofish256-cbc"
// (this is being retained for historical reasons)
'twofish128-cbc', // OPTIONAL Twofish with a 128-bit key
'twofish192-cbc', // OPTIONAL Twofish with a 192-bit key
'twofish256-cbc',
'twofish-cbc', // OPTIONAL alias for "twofish256-cbc"
// (this is being retained for historical reasons)
'blowfish-ctr', // OPTIONAL Blowfish in SDCTR mode
'blowfish-ctr', // OPTIONAL Blowfish in SDCTR mode
'blowfish-cbc', // OPTIONAL Blowfish in CBC mode
'blowfish-cbc', // OPTIONAL Blowfish in CBC mode
'3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode
'3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode
'3des-cbc', // REQUIRED three-key 3DES in CBC mode
//'none' // OPTIONAL no encryption; NOT RECOMMENDED
'3des-cbc', // REQUIRED three-key 3DES in CBC mode
//'none' // OPTIONAL no encryption; NOT RECOMMENDED
);
if (extension_loaded('openssl') && !extension_loaded('mcrypt')) {
// OpenSSL does not support arcfour256 in any capacity and arcfour128 / arcfour support is limited to
// instances that do not use continuous buffers
$encryption_algorithms = array_diff(
$encryption_algorithms,
array('arcfour256', 'arcfour128', 'arcfour')
);
if (phpseclib_resolve_include_path('Crypt/RC4.php') === false) {
$encryption_algorithms = array_diff(
$encryption_algorithms,
array('arcfour256', 'arcfour128', 'arcfour')
);
}
if (phpseclib_resolve_include_path('Crypt/Rijndael.php') === false) {
$encryption_algorithms = array_diff(
$encryption_algorithms,
array('aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc')
);
}
if (phpseclib_resolve_include_path('Crypt/Twofish.php') === false) {
$encryption_algorithms = array_diff(
$encryption_algorithms,
array('twofish128-ctr', 'twofish192-ctr', 'twofish256-ctr', 'twofish128-cbc', 'twofish192-cbc', 'twofish256-cbc', 'twofish-cbc')
);
}
if (phpseclib_resolve_include_path('Crypt/Blowfish.php') === false) {
$encryption_algorithms = array_diff(
$encryption_algorithms,
array('blowfish-ctr', 'blowfish-cbc')
);
}
if (phpseclib_resolve_include_path('Crypt/TripleDES.php') === false) {
$encryption_algorithms = array_diff(
$encryption_algorithms,
array('3des-ctr', '3des-cbc')
);
}
$encryption_algorithms = array_values($encryption_algorithms);
}
if (class_exists('\phpseclib\Crypt\RC4') === false) {
$encryption_algorithms = array_diff(
$encryption_algorithms,
array('arcfour256', 'arcfour128', 'arcfour')
);
}
if (class_exists('\phpseclib\Crypt\Rijndael') === false) {
$encryption_algorithms = array_diff(
$encryption_algorithms,
array('aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc')
);
}
if (class_exists('\phpseclib\Crypt\Twofish') === false) {
$encryption_algorithms = array_diff(
$encryption_algorithms,
array('twofish128-ctr', 'twofish192-ctr', 'twofish256-ctr', 'twofish128-cbc', 'twofish192-cbc', 'twofish256-cbc', 'twofish-cbc')
);
}
if (class_exists('\phpseclib\Crypt\Blowfish') === false) {
$encryption_algorithms = array_diff(
$encryption_algorithms,
array('blowfish-ctr', 'blowfish-cbc')
);
}
if (class_exists('\phpseclib\Crypt\TripleDES') === false) {
$encryption_algorithms = array_diff(
$encryption_algorithms,
array('3des-ctr', '3des-cbc')
);
}
$encryption_algorithms = array_values($encryption_algorithms);
$mac_algorithms = array(
// from <http://www.ietf.org/rfc/rfc6668.txt>:
'hmac-sha2-256',// RECOMMENDED HMAC-SHA256 (digest length = key length = 32)
@ -1179,7 +1278,7 @@ class Net_SSH2
//'none' // OPTIONAL no MAC; NOT RECOMMENDED
);
static $compression_algorithms = array(
$compression_algorithms = array(
'none' // REQUIRED no compression
//'zlib' // OPTIONAL ZLIB (LZ77) compression
);
@ -1193,19 +1292,13 @@ class Net_SSH2
));
}
static $str_kex_algorithms, $str_server_host_key_algorithms,
$encryption_algorithms_server_to_client, $mac_algorithms_server_to_client, $compression_algorithms_server_to_client,
$encryption_algorithms_client_to_server, $mac_algorithms_client_to_server, $compression_algorithms_client_to_server;
$str_kex_algorithms = implode(',', $kex_algorithms);
$str_server_host_key_algorithms = implode(',', $server_host_key_algorithms);
$encryption_algorithms_server_to_client = $encryption_algorithms_client_to_server = implode(',', $encryption_algorithms);
$mac_algorithms_server_to_client = $mac_algorithms_client_to_server = implode(',', $mac_algorithms);
$compression_algorithms_server_to_client = $compression_algorithms_client_to_server = implode(',', $compression_algorithms);
if (empty($str_kex_algorithms)) {
$str_kex_algorithms = implode(',', $kex_algorithms);
$str_server_host_key_algorithms = implode(',', $server_host_key_algorithms);
$encryption_algorithms_server_to_client = $encryption_algorithms_client_to_server = implode(',', $encryption_algorithms);
$mac_algorithms_server_to_client = $mac_algorithms_client_to_server = implode(',', $mac_algorithms);
$compression_algorithms_server_to_client = $compression_algorithms_client_to_server = implode(',', $compression_algorithms);
}
$client_cookie = crypt_random_string(16);
$client_cookie = Random::string(16);
$response = $kexinit_payload_server;
$this->_string_shift($response, 1); // skip past the message number (it should be SSH_MSG_KEXINIT)
@ -1245,14 +1338,32 @@ class Net_SSH2
$first_kex_packet_follows = $first_kex_packet_follows != 0;
// the sending of SSH2_MSG_KEXINIT could go in one of two places. this is the second place.
$kexinit_payload_client = pack('Ca*Na*Na*Na*Na*Na*Na*Na*Na*Na*Na*CN',
NET_SSH2_MSG_KEXINIT, $client_cookie, strlen($str_kex_algorithms), $str_kex_algorithms,
strlen($str_server_host_key_algorithms), $str_server_host_key_algorithms, strlen($encryption_algorithms_client_to_server),
$encryption_algorithms_client_to_server, strlen($encryption_algorithms_server_to_client), $encryption_algorithms_server_to_client,
strlen($mac_algorithms_client_to_server), $mac_algorithms_client_to_server, strlen($mac_algorithms_server_to_client),
$mac_algorithms_server_to_client, strlen($compression_algorithms_client_to_server), $compression_algorithms_client_to_server,
strlen($compression_algorithms_server_to_client), $compression_algorithms_server_to_client, 0, '', 0, '',
0, 0
$kexinit_payload_client = pack(
'Ca*Na*Na*Na*Na*Na*Na*Na*Na*Na*Na*CN',
NET_SSH2_MSG_KEXINIT,
$client_cookie,
strlen($str_kex_algorithms),
$str_kex_algorithms,
strlen($str_server_host_key_algorithms),
$str_server_host_key_algorithms,
strlen($encryption_algorithms_client_to_server),
$encryption_algorithms_client_to_server,
strlen($encryption_algorithms_server_to_client),
$encryption_algorithms_server_to_client,
strlen($mac_algorithms_client_to_server),
$mac_algorithms_client_to_server,
strlen($mac_algorithms_server_to_client),
$mac_algorithms_server_to_client,
strlen($compression_algorithms_client_to_server),
$compression_algorithms_client_to_server,
strlen($compression_algorithms_server_to_client),
$compression_algorithms_server_to_client,
0,
'',
0,
'',
0,
0
);
if (!$this->_send_binary_packet($kexinit_payload_client)) {
@ -1261,151 +1372,141 @@ class Net_SSH2
// here ends the second place.
// we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange
for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_server_to_client); $i++);
if ($i == count($encryption_algorithms)) {
// we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the
// diffie-hellman key exchange as fast as possible
$decrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_server_to_client);
$decryptKeyLength = $this->_encryption_algorithm_to_key_size($decrypt);
if ($decryptKeyLength === null) {
user_error('No compatible server to client encryption algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
// we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the
// diffie-hellman key exchange as fast as possible
$decrypt = $encryption_algorithms[$i];
switch ($decrypt) {
case '3des-cbc':
case '3des-ctr':
$decryptKeyLength = 24; // eg. 192 / 8
break;
case 'aes256-cbc':
case 'aes256-ctr':
case 'twofish-cbc':
case 'twofish256-cbc':
case 'twofish256-ctr':
$decryptKeyLength = 32; // eg. 256 / 8
break;
case 'aes192-cbc':
case 'aes192-ctr':
case 'twofish192-cbc':
case 'twofish192-ctr':
$decryptKeyLength = 24; // eg. 192 / 8
break;
case 'aes128-cbc':
case 'aes128-ctr':
case 'twofish128-cbc':
case 'twofish128-ctr':
case 'blowfish-cbc':
case 'blowfish-ctr':
$decryptKeyLength = 16; // eg. 128 / 8
break;
case 'arcfour':
case 'arcfour128':
$decryptKeyLength = 16; // eg. 128 / 8
break;
case 'arcfour256':
$decryptKeyLength = 32; // eg. 128 / 8
break;
case 'none';
$decryptKeyLength = 0;
}
for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_client_to_server); $i++);
if ($i == count($encryption_algorithms)) {
$encrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_client_to_server);
$encryptKeyLength = $this->_encryption_algorithm_to_key_size($encrypt);
if ($encryptKeyLength === null) {
user_error('No compatible client to server encryption algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
$encrypt = $encryption_algorithms[$i];
switch ($encrypt) {
case '3des-cbc':
case '3des-ctr':
$encryptKeyLength = 24;
break;
case 'aes256-cbc':
case 'aes256-ctr':
case 'twofish-cbc':
case 'twofish256-cbc':
case 'twofish256-ctr':
$encryptKeyLength = 32;
break;
case 'aes192-cbc':
case 'aes192-ctr':
case 'twofish192-cbc':
case 'twofish192-ctr':
$encryptKeyLength = 24;
break;
case 'aes128-cbc':
case 'aes128-ctr':
case 'twofish128-cbc':
case 'twofish128-ctr':
case 'blowfish-cbc':
case 'blowfish-ctr':
$encryptKeyLength = 16;
break;
case 'arcfour':
case 'arcfour128':
$encryptKeyLength = 16;
break;
case 'arcfour256':
$encryptKeyLength = 32;
break;
case 'none';
$encryptKeyLength = 0;
}
$keyLength = $decryptKeyLength > $encryptKeyLength ? $decryptKeyLength : $encryptKeyLength;
// through diffie-hellman key exchange a symmetric key is obtained
for ($i = 0; $i < count($kex_algorithms) && !in_array($kex_algorithms[$i], $this->kex_algorithms); $i++);
if ($i == count($kex_algorithms)) {
$kex_algorithm = $this->_array_intersect_first($kex_algorithms, $this->kex_algorithms);
if ($kex_algorithm === false) {
user_error('No compatible key exchange algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
switch ($kex_algorithms[$i]) {
// see http://tools.ietf.org/html/rfc2409#section-6.2 and
// http://tools.ietf.org/html/rfc2412, appendex E
case 'diffie-hellman-group1-sha1':
$prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
'020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
'4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF';
break;
// see http://tools.ietf.org/html/rfc3526#section-3
case 'diffie-hellman-group14-sha1':
$prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
'020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
'4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
'98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
'9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
'3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF';
break;
// Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty.
$exchange_hash_rfc4419 = '';
if ($kex_algorithm === 'curve25519-sha256@libssh.org') {
$x = Random::string(32);
$eBytes = \Sodium\crypto_box_publickey_from_secretkey($x);
$clientKexInitMessage = NET_SSH2_MSG_KEX_ECDH_INIT;
$serverKexReplyMessage = NET_SSH2_MSG_KEX_ECDH_REPLY;
$kexHash = new Hash('sha256');
} else {
if (strpos($kex_algorithm, 'diffie-hellman-group-exchange') === 0) {
$dh_group_sizes_packed = pack(
'NNN',
$this->kex_dh_group_size_min,
$this->kex_dh_group_size_preferred,
$this->kex_dh_group_size_max
);
$packet = pack(
'Ca*',
NET_SSH2_MSG_KEXDH_GEX_REQUEST,
$dh_group_sizes_packed
);
if (!$this->_send_binary_packet($packet)) {
return false;
}
$response = $this->_get_binary_packet();
if ($response === false) {
user_error('Connection closed by server');
return false;
}
extract(unpack('Ctype', $this->_string_shift($response, 1)));
if ($type != NET_SSH2_MSG_KEXDH_GEX_GROUP) {
user_error('Expected SSH_MSG_KEX_DH_GEX_GROUP');
return false;
}
extract(unpack('NprimeLength', $this->_string_shift($response, 4)));
$primeBytes = $this->_string_shift($response, $primeLength);
$prime = new BigInteger($primeBytes, -256);
extract(unpack('NgLength', $this->_string_shift($response, 4)));
$gBytes = $this->_string_shift($response, $gLength);
$g = new BigInteger($gBytes, -256);
$exchange_hash_rfc4419 = pack(
'a*Na*Na*',
$dh_group_sizes_packed,
$primeLength,
$primeBytes,
$gLength,
$gBytes
);
$clientKexInitMessage = NET_SSH2_MSG_KEXDH_GEX_INIT;
$serverKexReplyMessage = NET_SSH2_MSG_KEXDH_GEX_REPLY;
} else {
switch ($kex_algorithm) {
// see http://tools.ietf.org/html/rfc2409#section-6.2 and
// http://tools.ietf.org/html/rfc2412, appendex E
case 'diffie-hellman-group1-sha1':
$prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
'020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
'4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF';
break;
// see http://tools.ietf.org/html/rfc3526#section-3
case 'diffie-hellman-group14-sha1':
$prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
'020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
'4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
'98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
'9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
'3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF';
break;
}
// For both diffie-hellman-group1-sha1 and diffie-hellman-group14-sha1
// the generator field element is 2 (decimal) and the hash function is sha1.
$g = new BigInteger(2);
$prime = new BigInteger($prime, 16);
$clientKexInitMessage = NET_SSH2_MSG_KEXDH_INIT;
$serverKexReplyMessage = NET_SSH2_MSG_KEXDH_REPLY;
}
switch ($kex_algorithm) {
case 'diffie-hellman-group-exchange-sha256':
$kexHash = new Hash('sha256');
break;
default:
$kexHash = new Hash('sha1');
}
/* To increase the speed of the key exchange, both client and server may
reduce the size of their private exponents. It should be at least
twice as long as the key material that is generated from the shared
secret. For more details, see the paper by van Oorschot and Wiener
[VAN-OORSCHOT].
-- http://tools.ietf.org/html/rfc4419#section-6.2 */
$one = new BigInteger(1);
$keyLength = min($kexHash->getLength(), max($encryptKeyLength, $decryptKeyLength));
$max = $one->bitwise_leftShift(16 * $keyLength); // 2 * 8 * $keyLength
$max = $max->subtract($one);
$x = $one->random($one, $max);
$e = $g->modPow($x, $prime);
$eBytes = $e->toBytes(true);
}
// For both diffie-hellman-group1-sha1 and diffie-hellman-group14-sha1
// the generator field element is 2 (decimal) and the hash function is sha1.
$g = new Math_BigInteger(2);
$prime = new Math_BigInteger($prime, 16);
$kexHash = new Crypt_Hash('sha1');
//$q = $p->bitwise_rightShift(1);
/* To increase the speed of the key exchange, both client and server may
reduce the size of their private exponents. It should be at least
twice as long as the key material that is generated from the shared
secret. For more details, see the paper by van Oorschot and Wiener
[VAN-OORSCHOT].
-- http://tools.ietf.org/html/rfc4419#section-6.2 */
$one = new Math_BigInteger(1);
$keyLength = min($keyLength, $kexHash->getLength());
$max = $one->bitwise_leftShift(16 * $keyLength); // 2 * 8 * $keyLength
$max = $max->subtract($one);
$x = $one->random($one, $max);
$e = $g->modPow($x, $prime);
$eBytes = $e->toBytes(true);
$data = pack('CNa*', NET_SSH2_MSG_KEXDH_INIT, strlen($eBytes), $eBytes);
$data = pack('CNa*', $clientKexInitMessage, strlen($eBytes), $eBytes);
if (!$this->_send_binary_packet($data)) {
user_error('Connection closed by server');
@ -1419,7 +1520,7 @@ class Net_SSH2
}
extract(unpack('Ctype', $this->_string_shift($response, 1)));
if ($type != NET_SSH2_MSG_KEXDH_REPLY) {
if ($type != $serverKexReplyMessage) {
user_error('Expected SSH_MSG_KEXDH_REPLY');
return false;
}
@ -1432,7 +1533,6 @@ class Net_SSH2
$temp = unpack('Nlength', $this->_string_shift($response, 4));
$fBytes = $this->_string_shift($response, $temp['length']);
$f = new Math_BigInteger($fBytes, -256);
$temp = unpack('Nlength', $this->_string_shift($response, 4));
$this->signature = $this->_string_shift($response, $temp['length']);
@ -1440,14 +1540,38 @@ class Net_SSH2
$temp = unpack('Nlength', $this->_string_shift($this->signature, 4));
$this->signature_format = $this->_string_shift($this->signature, $temp['length']);
$key = $f->modPow($x, $prime);
if ($kex_algorithm === 'curve25519-sha256@libssh.org') {
if (strlen($fBytes) !== 32) {
user_error('Received curve25519 public key of invalid length.');
return false;
}
$key = new BigInteger(\Sodium\crypto_scalarmult($x, $fBytes), 256);
\Sodium\memzero($x);
} else {
$f = new BigInteger($fBytes, -256);
$key = $f->modPow($x, $prime);
}
$keyBytes = $key->toBytes(true);
$this->exchange_hash = pack('Na*Na*Na*Na*Na*Na*Na*Na*',
strlen($this->identifier), $this->identifier, strlen($this->server_identifier), $this->server_identifier,
strlen($kexinit_payload_client), $kexinit_payload_client, strlen($kexinit_payload_server),
$kexinit_payload_server, strlen($this->server_public_host_key), $this->server_public_host_key, strlen($eBytes),
$eBytes, strlen($fBytes), $fBytes, strlen($keyBytes), $keyBytes
$this->exchange_hash = pack(
'Na*Na*Na*Na*Na*a*Na*Na*Na*',
strlen($this->identifier),
$this->identifier,
strlen($this->server_identifier),
$this->server_identifier,
strlen($kexinit_payload_client),
$kexinit_payload_client,
strlen($kexinit_payload_server),
$kexinit_payload_server,
strlen($this->server_public_host_key),
$this->server_public_host_key,
$exchange_hash_rfc4419,
strlen($eBytes),
$eBytes,
strlen($fBytes),
$fBytes,
strlen($keyBytes),
$keyBytes
);
$this->exchange_hash = $kexHash->hash($this->exchange_hash);
@ -1456,18 +1580,19 @@ class Net_SSH2
$this->session_id = $this->exchange_hash;
}
for ($i = 0; $i < count($server_host_key_algorithms) && !in_array($server_host_key_algorithms[$i], $this->server_host_key_algorithms); $i++);
if ($i == count($server_host_key_algorithms)) {
$server_host_key_algorithm = $this->_array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms);
if ($server_host_key_algorithm === false) {
user_error('No compatible server host key algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
if ($public_key_format != $server_host_key_algorithms[$i] || $this->signature_format != $server_host_key_algorithms[$i]) {
if ($public_key_format != $server_host_key_algorithm || $this->signature_format != $server_host_key_algorithm) {
user_error('Server Host Key Algorithm Mismatch');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
$packet = pack('C',
$packet = pack(
'C',
NET_SSH2_MSG_NEWKEYS
);
@ -1489,163 +1614,16 @@ class Net_SSH2
return false;
}
switch ($encrypt) {
case '3des-cbc':
if (!class_exists('Crypt_TripleDES')) {
include_once 'Crypt/TripleDES.php';
}
$this->encrypt = new Crypt_TripleDES();
// $this->encrypt_block_size = 64 / 8 == the default
break;
case '3des-ctr':
if (!class_exists('Crypt_TripleDES')) {
include_once 'Crypt/TripleDES.php';
}
$this->encrypt = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
// $this->encrypt_block_size = 64 / 8 == the default
break;
case 'aes256-cbc':
case 'aes192-cbc':
case 'aes128-cbc':
if (!class_exists('Crypt_Rijndael')) {
include_once 'Crypt/Rijndael.php';
}
$this->encrypt = new Crypt_Rijndael();
$this->encrypt_block_size = 16; // eg. 128 / 8
break;
case 'aes256-ctr':
case 'aes192-ctr':
case 'aes128-ctr':
if (!class_exists('Crypt_Rijndael')) {
include_once 'Crypt/Rijndael.php';
}
$this->encrypt = new Crypt_Rijndael(CRYPT_RIJNDAEL_MODE_CTR);
$this->encrypt_block_size = 16; // eg. 128 / 8
break;
case 'blowfish-cbc':
if (!class_exists('Crypt_Blowfish')) {
include_once 'Crypt/Blowfish.php';
}
$this->encrypt = new Crypt_Blowfish();
$this->encrypt_block_size = 8;
break;
case 'blowfish-ctr':
if (!class_exists('Crypt_Blowfish')) {
include_once 'Crypt/Blowfish.php';
}
$this->encrypt = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR);
$this->encrypt_block_size = 8;
break;
case 'twofish128-cbc':
case 'twofish192-cbc':
case 'twofish256-cbc':
case 'twofish-cbc':
if (!class_exists('Crypt_Twofish')) {
include_once 'Crypt/Twofish.php';
}
$this->encrypt = new Crypt_Twofish();
$this->encrypt_block_size = 16;
break;
case 'twofish128-ctr':
case 'twofish192-ctr':
case 'twofish256-ctr':
if (!class_exists('Crypt_Twofish')) {
include_once 'Crypt/Twofish.php';
}
$this->encrypt = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR);
$this->encrypt_block_size = 16;
break;
case 'arcfour':
case 'arcfour128':
case 'arcfour256':
if (!class_exists('Crypt_RC4')) {
include_once 'Crypt/RC4.php';
}
$this->encrypt = new Crypt_RC4();
break;
case 'none';
//$this->encrypt = new Crypt_Null();
}
switch ($decrypt) {
case '3des-cbc':
if (!class_exists('Crypt_TripleDES')) {
include_once 'Crypt/TripleDES.php';
}
$this->decrypt = new Crypt_TripleDES();
break;
case '3des-ctr':
if (!class_exists('Crypt_TripleDES')) {
include_once 'Crypt/TripleDES.php';
}
$this->decrypt = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
break;
case 'aes256-cbc':
case 'aes192-cbc':
case 'aes128-cbc':
if (!class_exists('Crypt_Rijndael')) {
include_once 'Crypt/Rijndael.php';
}
$this->decrypt = new Crypt_Rijndael();
$this->decrypt_block_size = 16;
break;
case 'aes256-ctr':
case 'aes192-ctr':
case 'aes128-ctr':
if (!class_exists('Crypt_Rijndael')) {
include_once 'Crypt/Rijndael.php';
}
$this->decrypt = new Crypt_Rijndael(CRYPT_RIJNDAEL_MODE_CTR);
$this->decrypt_block_size = 16;
break;
case 'blowfish-cbc':
if (!class_exists('Crypt_Blowfish')) {
include_once 'Crypt/Blowfish.php';
}
$this->decrypt = new Crypt_Blowfish();
$this->decrypt_block_size = 8;
break;
case 'blowfish-ctr':
if (!class_exists('Crypt_Blowfish')) {
include_once 'Crypt/Blowfish.php';
}
$this->decrypt = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR);
$this->decrypt_block_size = 8;
break;
case 'twofish128-cbc':
case 'twofish192-cbc':
case 'twofish256-cbc':
case 'twofish-cbc':
if (!class_exists('Crypt_Twofish')) {
include_once 'Crypt/Twofish.php';
}
$this->decrypt = new Crypt_Twofish();
$this->decrypt_block_size = 16;
break;
case 'twofish128-ctr':
case 'twofish192-ctr':
case 'twofish256-ctr':
if (!class_exists('Crypt_Twofish')) {
include_once 'Crypt/Twofish.php';
}
$this->decrypt = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR);
$this->decrypt_block_size = 16;
break;
case 'arcfour':
case 'arcfour128':
case 'arcfour256':
if (!class_exists('Crypt_RC4')) {
include_once 'Crypt/RC4.php';
}
$this->decrypt = new Crypt_RC4();
break;
case 'none';
//$this->decrypt = new Crypt_Null();
}
$keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
$this->encrypt = $this->_encryption_algorithm_to_crypt_instance($encrypt);
if ($this->encrypt) {
if ($this->crypto_engine) {
$this->encrypt->setEngine($this->crypto_engine);
}
if ($this->encrypt->block_size) {
$this->encrypt_block_size = $this->encrypt->block_size;
}
$this->encrypt->enableContinuousBuffer();
$this->encrypt->disablePadding();
@ -1662,7 +1640,14 @@ class Net_SSH2
$this->encrypt->setKey(substr($key, 0, $encryptKeyLength));
}
$this->decrypt = $this->_encryption_algorithm_to_crypt_instance($decrypt);
if ($this->decrypt) {
if ($this->crypto_engine) {
$this->decrypt->setEngine($this->crypto_engine);
}
if ($this->decrypt->block_size) {
$this->decrypt_block_size = $this->decrypt->block_size;
}
$this->decrypt->enableContinuousBuffer();
$this->decrypt->disablePadding();
@ -1693,66 +1678,66 @@ class Net_SSH2
$this->decrypt->decrypt(str_repeat("\0", 1536));
}
for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_client_to_server); $i++);
if ($i == count($mac_algorithms)) {
$mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_client_to_server);
if ($mac_algorithm === false) {
user_error('No compatible client to server message authentication algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
$createKeyLength = 0; // ie. $mac_algorithms[$i] == 'none'
switch ($mac_algorithms[$i]) {
$createKeyLength = 0; // ie. $mac_algorithm == 'none'
switch ($mac_algorithm) {
case 'hmac-sha2-256':
$this->hmac_create = new Crypt_Hash('sha256');
$this->hmac_create = new Hash('sha256');
$createKeyLength = 32;
break;
case 'hmac-sha1':
$this->hmac_create = new Crypt_Hash('sha1');
$this->hmac_create = new Hash('sha1');
$createKeyLength = 20;
break;
case 'hmac-sha1-96':
$this->hmac_create = new Crypt_Hash('sha1-96');
$this->hmac_create = new Hash('sha1-96');
$createKeyLength = 20;
break;
case 'hmac-md5':
$this->hmac_create = new Crypt_Hash('md5');
$this->hmac_create = new Hash('md5');
$createKeyLength = 16;
break;
case 'hmac-md5-96':
$this->hmac_create = new Crypt_Hash('md5-96');
$this->hmac_create = new Hash('md5-96');
$createKeyLength = 16;
}
for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_server_to_client); $i++);
if ($i == count($mac_algorithms)) {
$mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_server_to_client);
if ($mac_algorithm === false) {
user_error('No compatible server to client message authentication algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
$checkKeyLength = 0;
$this->hmac_size = 0;
switch ($mac_algorithms[$i]) {
switch ($mac_algorithm) {
case 'hmac-sha2-256':
$this->hmac_check = new Crypt_Hash('sha256');
$this->hmac_check = new Hash('sha256');
$checkKeyLength = 32;
$this->hmac_size = 32;
break;
case 'hmac-sha1':
$this->hmac_check = new Crypt_Hash('sha1');
$this->hmac_check = new Hash('sha1');
$checkKeyLength = 20;
$this->hmac_size = 20;
break;
case 'hmac-sha1-96':
$this->hmac_check = new Crypt_Hash('sha1-96');
$this->hmac_check = new Hash('sha1-96');
$checkKeyLength = 20;
$this->hmac_size = 12;
break;
case 'hmac-md5':
$this->hmac_check = new Crypt_Hash('md5');
$this->hmac_check = new Hash('md5');
$checkKeyLength = 16;
$this->hmac_size = 16;
break;
case 'hmac-md5-96':
$this->hmac_check = new Crypt_Hash('md5-96');
$this->hmac_check = new Hash('md5-96');
$checkKeyLength = 16;
$this->hmac_size = 12;
}
@ -1769,33 +1754,116 @@ class Net_SSH2
}
$this->hmac_check->setKey(substr($key, 0, $checkKeyLength));
for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_server_to_client); $i++);
if ($i == count($compression_algorithms)) {
$compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_server_to_client);
if ($compression_algorithm === false) {
user_error('No compatible server to client compression algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
$this->decompress = $compression_algorithms[$i] == 'zlib';
$this->decompress = $compression_algorithm == 'zlib';
for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_client_to_server); $i++);
if ($i == count($compression_algorithms)) {
$compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_client_to_server);
if ($compression_algorithm === false) {
user_error('No compatible client to server compression algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
$this->compress = $compression_algorithms[$i] == 'zlib';
$this->compress = $compression_algorithm == 'zlib';
return true;
}
/**
* Maps an encryption algorithm name to the number of key bytes.
*
* @param string $algorithm Name of the encryption algorithm
* @return int|null Number of bytes as an integer or null for unknown
* @access private
*/
function _encryption_algorithm_to_key_size($algorithm)
{
switch ($algorithm) {
case 'none':
return 0;
case 'aes128-cbc':
case 'aes128-ctr':
case 'arcfour':
case 'arcfour128':
case 'blowfish-cbc':
case 'blowfish-ctr':
case 'twofish128-cbc':
case 'twofish128-ctr':
return 16;
case '3des-cbc':
case '3des-ctr':
case 'aes192-cbc':
case 'aes192-ctr':
case 'twofish192-cbc':
case 'twofish192-ctr':
return 24;
case 'aes256-cbc':
case 'aes256-ctr':
case 'arcfour256':
case 'twofish-cbc':
case 'twofish256-cbc':
case 'twofish256-ctr':
return 32;
}
return null;
}
/**
* Maps an encryption algorithm name to an instance of a subclass of
* \phpseclib\Crypt\Base.
*
* @param string $algorithm Name of the encryption algorithm
* @return mixed Instance of \phpseclib\Crypt\Base or null for unknown
* @access private
*/
function _encryption_algorithm_to_crypt_instance($algorithm)
{
switch ($algorithm) {
case '3des-cbc':
return new TripleDES();
case '3des-ctr':
return new TripleDES(Base::MODE_CTR);
case 'aes256-cbc':
case 'aes192-cbc':
case 'aes128-cbc':
return new Rijndael();
case 'aes256-ctr':
case 'aes192-ctr':
case 'aes128-ctr':
return new Rijndael(Base::MODE_CTR);
case 'blowfish-cbc':
return new Blowfish();
case 'blowfish-ctr':
return new Blowfish(Base::MODE_CTR);
case 'twofish128-cbc':
case 'twofish192-cbc':
case 'twofish256-cbc':
case 'twofish-cbc':
return new Twofish();
case 'twofish128-ctr':
case 'twofish192-ctr':
case 'twofish256-ctr':
return new Twofish(Base::MODE_CTR);
case 'arcfour':
case 'arcfour128':
case 'arcfour256':
return new RC4();
}
return null;
}
/**
* Login
*
* The $password parameter can be a plaintext password, a Crypt_RSA object or an array
* The $password parameter can be a plaintext password, a \phpseclib\Crypt\RSA object or an array
*
* @param String $username
* @param Mixed $password
* @param Mixed $...
* @return Boolean
* @see _login
* @param string $username
* @param mixed $password
* @param mixed $...
* @return bool
* @see self::_login()
* @access public
*/
function login($username)
@ -1807,16 +1875,16 @@ class Net_SSH2
/**
* Login Helper
*
* @param String $username
* @param Mixed $password
* @param Mixed $...
* @return Boolean
* @see _login_helper
* @param string $username
* @param mixed $password
* @param mixed $...
* @return bool
* @see self::_login_helper()
* @access private
*/
function _login($username)
{
if (!($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR)) {
if (!($this->bitmap & self::MASK_CONSTRUCTOR)) {
if (!$this->_connect()) {
return false;
}
@ -1838,22 +1906,25 @@ class Net_SSH2
/**
* Login Helper
*
* @param String $username
* @param optional String $password
* @return Boolean
* @param string $username
* @param string $password
* @return bool
* @access private
* @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
* by sending dummy SSH_MSG_IGNORE messages.
*/
function _login_helper($username, $password = null)
{
if (!($this->bitmap & NET_SSH2_MASK_CONNECTED)) {
if (!($this->bitmap & self::MASK_CONNECTED)) {
return false;
}
if (!($this->bitmap & NET_SSH2_MASK_LOGIN_REQ)) {
$packet = pack('CNa*',
NET_SSH2_MSG_SERVICE_REQUEST, strlen('ssh-userauth'), 'ssh-userauth'
if (!($this->bitmap & self::MASK_LOGIN_REQ)) {
$packet = pack(
'CNa*',
NET_SSH2_MSG_SERVICE_REQUEST,
strlen('ssh-userauth'),
'ssh-userauth'
);
if (!$this->_send_binary_packet($packet)) {
@ -1872,35 +1943,37 @@ class Net_SSH2
user_error('Expected SSH_MSG_SERVICE_ACCEPT');
return false;
}
$this->bitmap |= NET_SSH2_MASK_LOGIN_REQ;
$this->bitmap |= self::MASK_LOGIN_REQ;
}
if (strlen($this->last_interactive_response)) {
return !is_string($password) && !is_array($password) ? false : $this->_keyboard_interactive_process($password);
}
// although PHP5's get_class() preserves the case, PHP4's does not
if (is_object($password)) {
switch (strtolower(get_class($password))) {
case 'crypt_rsa':
return $this->_privatekey_login($username, $password);
case 'system_ssh_agent':
return $this->_ssh_agent_login($username, $password);
}
if ($password instanceof RSA) {
return $this->_privatekey_login($username, $password);
} elseif ($password instanceof Agent) {
return $this->_ssh_agent_login($username, $password);
}
if (is_array($password)) {
if ($this->_keyboard_interactive_login($username, $password)) {
$this->bitmap |= NET_SSH2_MASK_LOGIN;
$this->bitmap |= self::MASK_LOGIN;
return true;
}
return false;
}
if (!isset($password)) {
$packet = pack('CNa*Na*Na*',
NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection',
strlen('none'), 'none'
$packet = pack(
'CNa*Na*Na*',
NET_SSH2_MSG_USERAUTH_REQUEST,
strlen($username),
$username,
strlen('ssh-connection'),
'ssh-connection',
strlen('none'),
'none'
);
if (!$this->_send_binary_packet($packet)) {
@ -1917,7 +1990,7 @@ class Net_SSH2
switch ($type) {
case NET_SSH2_MSG_USERAUTH_SUCCESS:
$this->bitmap |= NET_SSH2_MASK_LOGIN;
$this->bitmap |= self::MASK_LOGIN;
return true;
//case NET_SSH2_MSG_USERAUTH_FAILURE:
default:
@ -1925,18 +1998,36 @@ class Net_SSH2
}
}
$packet = pack('CNa*Na*Na*CNa*',
NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection',
strlen('password'), 'password', 0, strlen($password), $password
$packet = pack(
'CNa*Na*Na*CNa*',
NET_SSH2_MSG_USERAUTH_REQUEST,
strlen($username),
$username,
strlen('ssh-connection'),
'ssh-connection',
strlen('password'),
'password',
0,
strlen($password),
$password
);
// remove the username and password from the logged packet
if (!defined('NET_SSH2_LOGGING')) {
$logged = null;
} else {
$logged = pack('CNa*Na*Na*CNa*',
NET_SSH2_MSG_USERAUTH_REQUEST, strlen('username'), 'username', strlen('ssh-connection'), 'ssh-connection',
strlen('password'), 'password', 0, strlen('password'), 'password'
$logged = pack(
'CNa*Na*Na*CNa*',
NET_SSH2_MSG_USERAUTH_REQUEST,
strlen('username'),
'username',
strlen('ssh-connection'),
'ssh-connection',
strlen('password'),
'password',
0,
strlen('password'),
'password'
);
}
@ -1970,14 +2061,14 @@ class Net_SSH2
if (!$partial_success && in_array('keyboard-interactive', $auth_methods)) {
if ($this->_keyboard_interactive_login($username, $password)) {
$this->bitmap |= NET_SSH2_MASK_LOGIN;
$this->bitmap |= self::MASK_LOGIN;
return true;
}
return false;
}
return false;
case NET_SSH2_MSG_USERAUTH_SUCCESS:
$this->bitmap |= NET_SSH2_MASK_LOGIN;
$this->bitmap |= self::MASK_LOGIN;
return true;
}
@ -1989,16 +2080,26 @@ class Net_SSH2
*
* See {@link http://tools.ietf.org/html/rfc4256 RFC4256} for details. This is not a full-featured keyboard-interactive authenticator.
*
* @param String $username
* @param String $password
* @return Boolean
* @param string $username
* @param string $password
* @return bool
* @access private
*/
function _keyboard_interactive_login($username, $password)
{
$packet = pack('CNa*Na*Na*Na*Na*',
NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection',
strlen('keyboard-interactive'), 'keyboard-interactive', 0, '', 0, ''
$packet = pack(
'CNa*Na*Na*Na*Na*',
NET_SSH2_MSG_USERAUTH_REQUEST,
strlen($username),
$username,
strlen('ssh-connection'),
'ssh-connection',
strlen('keyboard-interactive'),
'keyboard-interactive',
0,
'',
0,
''
);
if (!$this->_send_binary_packet($packet)) {
@ -2011,8 +2112,8 @@ class Net_SSH2
/**
* Handle the keyboard-interactive requests / responses.
*
* @param String $responses...
* @return Boolean
* @param string $responses...
* @return bool
* @access private
*/
function _keyboard_interactive_process()
@ -2069,7 +2170,7 @@ class Net_SSH2
// see http://tools.ietf.org/html/rfc4256#section-3.2
if (strlen($this->last_interactive_response)) {
$this->last_interactive_response = '';
} else if (defined('NET_SSH2_LOGGING')) {
} elseif (defined('NET_SSH2_LOGGING')) {
$this->message_number_log[count($this->message_number_log) - 1] = str_replace(
'UNKNOWN',
'NET_SSH2_MSG_USERAUTH_INFO_REQUEST',
@ -2097,7 +2198,7 @@ class Net_SSH2
return false;
}
if (defined('NET_SSH2_LOGGING') && NET_SSH2_LOGGING == NET_SSH2_LOG_COMPLEX) {
if (defined('NET_SSH2_LOGGING') && NET_SSH2_LOGGING == self::LOG_COMPLEX) {
$this->message_number_log[count($this->message_number_log) - 1] = str_replace(
'UNKNOWN',
'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE',
@ -2125,13 +2226,14 @@ class Net_SSH2
/**
* Login with an ssh-agent provided key
*
* @param String $username
* @param System_SSH_Agent $agent
* @return Boolean
* @param string $username
* @param \phpseclib\System\SSH\Agent $agent
* @return bool
* @access private
*/
function _ssh_agent_login($username, $agent)
{
$this->agent = $agent;
$keys = $agent->requestIdentities();
foreach ($keys as $key) {
if ($this->_privatekey_login($username, $key)) {
@ -2145,9 +2247,9 @@ class Net_SSH2
/**
* Login with an RSA private key
*
* @param String $username
* @param Crypt_RSA $password
* @return Boolean
* @param string $username
* @param \phpseclib\Crypt\RSA $password
* @return bool
* @access private
* @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
* by sending dummy SSH_MSG_IGNORE messages.
@ -2155,7 +2257,7 @@ class Net_SSH2
function _privatekey_login($username, $privatekey)
{
// see http://tools.ietf.org/html/rfc4253#page-15
$publickey = $privatekey->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_RAW);
$publickey = $privatekey->getPublicKey(RSA::PUBLIC_FORMAT_RAW);
if ($publickey === false) {
return false;
}
@ -2164,13 +2266,25 @@ class Net_SSH2
'e' => $publickey['e']->toBytes(true),
'n' => $publickey['n']->toBytes(true)
);
$publickey = pack('Na*Na*Na*',
strlen('ssh-rsa'), 'ssh-rsa', strlen($publickey['e']), $publickey['e'], strlen($publickey['n']), $publickey['n']
$publickey = pack(
'Na*Na*Na*',
strlen('ssh-rsa'),
'ssh-rsa',
strlen($publickey['e']),
$publickey['e'],
strlen($publickey['n']),
$publickey['n']
);
$part1 = pack('CNa*Na*Na*',
NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection',
strlen('publickey'), 'publickey'
$part1 = pack(
'CNa*Na*Na*',
NET_SSH2_MSG_USERAUTH_REQUEST,
strlen($username),
$username,
strlen('ssh-connection'),
'ssh-connection',
strlen('publickey'),
'publickey'
);
$part2 = pack('Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publickey), $publickey);
@ -2195,7 +2309,7 @@ class Net_SSH2
case NET_SSH2_MSG_USERAUTH_PK_OK:
// we'll just take it on faith that the public key blob and the public key algorithm name are as
// they should be
if (defined('NET_SSH2_LOGGING') && NET_SSH2_LOGGING == NET_SSH2_LOG_COMPLEX) {
if (defined('NET_SSH2_LOGGING') && NET_SSH2_LOGGING == self::LOG_COMPLEX) {
$this->message_number_log[count($this->message_number_log) - 1] = str_replace(
'UNKNOWN',
'NET_SSH2_MSG_USERAUTH_PK_OK',
@ -2205,7 +2319,7 @@ class Net_SSH2
}
$packet = $part1 . chr(1) . $part2;
$privatekey->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$privatekey->setSignatureMode(RSA::SIGNATURE_PKCS1);
$signature = $privatekey->sign(pack('Na*a*', strlen($this->session_id), $this->session_id, $packet));
$signature = pack('Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($signature), $signature);
$packet.= pack('Na*', strlen($signature), $signature);
@ -2227,7 +2341,7 @@ class Net_SSH2
// either the login is bad or the server employs multi-factor authentication
return false;
case NET_SSH2_MSG_USERAUTH_SUCCESS:
$this->bitmap |= NET_SSH2_MASK_LOGIN;
$this->bitmap |= self::MASK_LOGIN;
return true;
}
@ -2240,7 +2354,7 @@ class Net_SSH2
* $ssh->exec('ping 127.0.0.1'); on a Linux host will never return and will run indefinitely. setTimeout() makes it so it'll timeout.
* Setting $timeout to false or 0 will mean there is no timeout.
*
* @param Mixed $timeout
* @param mixed $timeout
* @access public
*/
function setTimeout($timeout)
@ -2261,12 +2375,12 @@ class Net_SSH2
/**
* Execute Command
*
* If $callback is set to false then Net_SSH2::_get_channel_packet(NET_SSH2_CHANNEL_EXEC) will need to be called manually.
* If $callback is set to false then \phpseclib\Net\SSH2::_get_channel_packet(self::CHANNEL_EXEC) will need to be called manually.
* In all likelihood, this is not a feature you want to be taking advantage of.
*
* @param String $command
* @param optional Callback $callback
* @return String
* @param string $command
* @param Callback $callback
* @return string
* @access public
*/
function exec($command, $callback = null)
@ -2275,42 +2389,63 @@ class Net_SSH2
$this->is_timeout = false;
$this->stdErrorLog = '';
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (!($this->bitmap & self::MASK_LOGIN)) {
return false;
}
// RFC4254 defines the (client) window size as "bytes the other party can send before it must wait for the window to
// be adjusted". 0x7FFFFFFF is, at 2GB, the max size. technically, it should probably be decremented, but,
// honestly, if you're transfering more than 2GB, you probably shouldn't be using phpseclib, anyway.
// honestly, if you're transferring more than 2GB, you probably shouldn't be using phpseclib, anyway.
// see http://tools.ietf.org/html/rfc4254#section-5.2 for more info
$this->window_size_server_to_client[NET_SSH2_CHANNEL_EXEC] = $this->window_size;
$this->window_size_server_to_client[self::CHANNEL_EXEC] = $this->window_size;
// 0x8000 is the maximum max packet size, per http://tools.ietf.org/html/rfc4253#section-6.1, although since PuTTy
// uses 0x4000, that's what will be used here, as well.
$packet_size = 0x4000;
$packet = pack('CNa*N3',
NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', NET_SSH2_CHANNEL_EXEC, $this->window_size_server_to_client[NET_SSH2_CHANNEL_EXEC], $packet_size);
$packet = pack(
'CNa*N3',
NET_SSH2_MSG_CHANNEL_OPEN,
strlen('session'),
'session',
self::CHANNEL_EXEC,
$this->window_size_server_to_client[self::CHANNEL_EXEC],
$packet_size
);
if (!$this->_send_binary_packet($packet)) {
return false;
}
$this->channel_status[NET_SSH2_CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_OPEN;
$this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_OPEN;
$response = $this->_get_channel_packet(NET_SSH2_CHANNEL_EXEC);
$response = $this->_get_channel_packet(self::CHANNEL_EXEC);
if ($response === false) {
return false;
}
if ($this->request_pty === true) {
$terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
$packet = pack('CNNa*CNa*N5a*',
NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_EXEC], strlen('pty-req'), 'pty-req', 1, strlen('vt100'), 'vt100',
$this->windowColumns, $this->windowRows, 0, 0, strlen($terminal_modes), $terminal_modes);
$packet = pack(
'CNNa*CNa*N5a*',
NET_SSH2_MSG_CHANNEL_REQUEST,
$this->server_channels[self::CHANNEL_EXEC],
strlen('pty-req'),
'pty-req',
1,
strlen('vt100'),
'vt100',
$this->windowColumns,
$this->windowRows,
0,
0,
strlen($terminal_modes),
$terminal_modes
);
if (!$this->_send_binary_packet($packet)) {
return false;
}
$response = $this->_get_binary_packet();
if ($response === false) {
user_error('Connection closed by server');
@ -2331,7 +2466,7 @@ class Net_SSH2
}
// sending a pty-req SSH_MSG_CHANNEL_REQUEST message is unnecessary and, in fact, in most cases, slows things
// down. the one place where it might be desirable is if you're doing something like Net_SSH2::exec('ping localhost &').
// down. the one place where it might be desirable is if you're doing something like \phpseclib\Net\SSH2::exec('ping localhost &').
// with a pty-req SSH_MSG_CHANNEL_REQUEST, exec() will return immediately and the ping process will then
// then immediately terminate. without such a request exec() will loop indefinitely. the ping process won't end but
// neither will your script.
@ -2339,20 +2474,28 @@ class Net_SSH2
// although, in theory, the size of SSH_MSG_CHANNEL_REQUEST could exceed the maximum packet size established by
// SSH_MSG_CHANNEL_OPEN_CONFIRMATION, RFC4254#section-5.1 states that the "maximum packet size" refers to the
// "maximum size of an individual data packet". ie. SSH_MSG_CHANNEL_DATA. RFC4254#section-5.2 corroborates.
$packet = pack('CNNa*CNa*',
NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_EXEC], strlen('exec'), 'exec', 1, strlen($command), $command);
$packet = pack(
'CNNa*CNa*',
NET_SSH2_MSG_CHANNEL_REQUEST,
$this->server_channels[self::CHANNEL_EXEC],
strlen('exec'),
'exec',
1,
strlen($command),
$command
);
if (!$this->_send_binary_packet($packet)) {
return false;
}
$this->channel_status[NET_SSH2_CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_REQUEST;
$this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_REQUEST;
$response = $this->_get_channel_packet(NET_SSH2_CHANNEL_EXEC);
$response = $this->_get_channel_packet(self::CHANNEL_EXEC);
if ($response === false) {
return false;
}
$this->channel_status[NET_SSH2_CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_DATA;
$this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_DATA;
if ($callback === false || $this->in_request_pty_exec) {
return true;
@ -2360,7 +2503,7 @@ class Net_SSH2
$output = '';
while (true) {
$temp = $this->_get_channel_packet(NET_SSH2_CHANNEL_EXEC);
$temp = $this->_get_channel_packet(self::CHANNEL_EXEC);
switch (true) {
case $temp === true:
return is_callable($callback) ? true : $output;
@ -2369,7 +2512,7 @@ class Net_SSH2
default:
if (is_callable($callback)) {
if (call_user_func($callback, $temp) === true) {
$this->_close_channel(NET_SSH2_CHANNEL_EXEC);
$this->_close_channel(self::CHANNEL_EXEC);
return true;
}
} else {
@ -2382,9 +2525,9 @@ class Net_SSH2
/**
* Creates an interactive shell
*
* @see Net_SSH2::read()
* @see Net_SSH2::write()
* @return Boolean
* @see self::read()
* @see self::write()
* @return bool
* @access private
*/
function _initShell()
@ -2393,27 +2536,47 @@ class Net_SSH2
return true;
}
$this->window_size_server_to_client[NET_SSH2_CHANNEL_SHELL] = $this->window_size;
$this->window_size_server_to_client[self::CHANNEL_SHELL] = $this->window_size;
$packet_size = 0x4000;
$packet = pack('CNa*N3',
NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', NET_SSH2_CHANNEL_SHELL, $this->window_size_server_to_client[NET_SSH2_CHANNEL_SHELL], $packet_size);
$packet = pack(
'CNa*N3',
NET_SSH2_MSG_CHANNEL_OPEN,
strlen('session'),
'session',
self::CHANNEL_SHELL,
$this->window_size_server_to_client[self::CHANNEL_SHELL],
$packet_size
);
if (!$this->_send_binary_packet($packet)) {
return false;
}
$this->channel_status[NET_SSH2_CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_OPEN;
$this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_OPEN;
$response = $this->_get_channel_packet(NET_SSH2_CHANNEL_SHELL);
$response = $this->_get_channel_packet(self::CHANNEL_SHELL);
if ($response === false) {
return false;
}
$terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
$packet = pack('CNNa*CNa*N5a*',
NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_SHELL], strlen('pty-req'), 'pty-req', 1, strlen('vt100'), 'vt100',
$this->windowColumns, $this->windowRows, 0, 0, strlen($terminal_modes), $terminal_modes);
$packet = pack(
'CNNa*CNa*N5a*',
NET_SSH2_MSG_CHANNEL_REQUEST,
$this->server_channels[self::CHANNEL_SHELL],
strlen('pty-req'),
'pty-req',
1,
strlen('vt100'),
'vt100',
$this->windowColumns,
$this->windowRows,
0,
0,
strlen($terminal_modes),
$terminal_modes
);
if (!$this->_send_binary_packet($packet)) {
return false;
@ -2437,22 +2600,28 @@ class Net_SSH2
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
}
$packet = pack('CNNa*C',
NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_SHELL], strlen('shell'), 'shell', 1);
$packet = pack(
'CNNa*C',
NET_SSH2_MSG_CHANNEL_REQUEST,
$this->server_channels[self::CHANNEL_SHELL],
strlen('shell'),
'shell',
1
);
if (!$this->_send_binary_packet($packet)) {
return false;
}
$this->channel_status[NET_SSH2_CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_REQUEST;
$this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_REQUEST;
$response = $this->_get_channel_packet(NET_SSH2_CHANNEL_SHELL);
$response = $this->_get_channel_packet(self::CHANNEL_SHELL);
if ($response === false) {
return false;
}
$this->channel_status[NET_SSH2_CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_DATA;
$this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_DATA;
$this->bitmap |= NET_SSH2_MASK_SHELL;
$this->bitmap |= self::MASK_SHELL;
return true;
}
@ -2460,46 +2629,64 @@ class Net_SSH2
/**
* Return the channel to be used with read() / write()
*
* @see Net_SSH2::read()
* @see Net_SSH2::write()
* @return Integer
* @see self::read()
* @see self::write()
* @return int
* @access public
*/
function _get_interactive_channel()
{
switch (true) {
case $this->in_subsystem:
return NET_SSH2_CHANNEL_SUBSYSTEM;
return self::CHANNEL_SUBSYSTEM;
case $this->in_request_pty_exec:
return NET_SSH2_CHANNEL_EXEC;
return self::CHANNEL_EXEC;
default:
return NET_SSH2_CHANNEL_SHELL;
return self::CHANNEL_SHELL;
}
}
/**
* Return an available open channel
*
* @return int
* @access public
*/
function _get_open_channel()
{
$channel = self::CHANNEL_EXEC;
do {
if (isset($this->channel_status[$channel]) && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_OPEN) {
return $channel;
}
} while ($channel++ < self::CHANNEL_SUBSYSTEM);
return false;
}
/**
* Returns the output of an interactive shell
*
* Returns when there's a match for $expect, which can take the form of a string literal or,
* if $mode == NET_SSH2_READ_REGEX, a regular expression.
* if $mode == self::READ_REGEX, a regular expression.
*
* @see Net_SSH2::write()
* @param String $expect
* @param Integer $mode
* @return String
* @see self::write()
* @param string $expect
* @param int $mode
* @return string
* @access public
*/
function read($expect = '', $mode = NET_SSH2_READ_SIMPLE)
function read($expect = '', $mode = self::READ_SIMPLE)
{
$this->curTimeout = $this->timeout;
$this->is_timeout = false;
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (!($this->bitmap & self::MASK_LOGIN)) {
user_error('Operation disallowed prior to login()');
return false;
}
if (!($this->bitmap & NET_SSH2_MASK_SHELL) && !$this->_initShell()) {
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
user_error('Unable to initiate an interactive shell session');
return false;
}
@ -2508,8 +2695,8 @@ class Net_SSH2
$match = $expect;
while (true) {
if ($mode == NET_SSH2_READ_REGEX) {
preg_match($expect, $this->interactiveBuffer, $matches);
if ($mode == self::READ_REGEX) {
preg_match($expect, substr($this->interactiveBuffer, -1024), $matches);
$match = isset($matches[0]) ? $matches[0] : '';
}
$pos = strlen($match) ? strpos($this->interactiveBuffer, $match) : false;
@ -2529,19 +2716,19 @@ class Net_SSH2
/**
* Inputs a command into an interactive shell.
*
* @see Net_SSH2::read()
* @param String $cmd
* @return Boolean
* @see self::read()
* @param string $cmd
* @return bool
* @access public
*/
function write($cmd)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (!($this->bitmap & self::MASK_LOGIN)) {
user_error('Operation disallowed prior to login()');
return false;
}
if (!($this->bitmap & NET_SSH2_MASK_SHELL) && !$this->_initShell()) {
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
user_error('Unable to initiate an interactive shell session');
return false;
}
@ -2558,46 +2745,61 @@ class Net_SSH2
* returns that and then that that was passed into stopSubsystem() but that'll be saved for a future date and implemented
* if there's sufficient demand for such a feature.
*
* @see Net_SSH2::stopSubsystem()
* @param String $subsystem
* @return Boolean
* @see self::stopSubsystem()
* @param string $subsystem
* @return bool
* @access public
*/
function startSubsystem($subsystem)
{
$this->window_size_server_to_client[NET_SSH2_CHANNEL_SUBSYSTEM] = $this->window_size;
$this->window_size_server_to_client[self::CHANNEL_SUBSYSTEM] = $this->window_size;
$packet = pack('CNa*N3',
NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', NET_SSH2_CHANNEL_SUBSYSTEM, $this->window_size, 0x4000);
$packet = pack(
'CNa*N3',
NET_SSH2_MSG_CHANNEL_OPEN,
strlen('session'),
'session',
self::CHANNEL_SUBSYSTEM,
$this->window_size,
0x4000
);
if (!$this->_send_binary_packet($packet)) {
return false;
}
$this->channel_status[NET_SSH2_CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_OPEN;
$this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_OPEN;
$response = $this->_get_channel_packet(NET_SSH2_CHANNEL_SUBSYSTEM);
$response = $this->_get_channel_packet(self::CHANNEL_SUBSYSTEM);
if ($response === false) {
return false;
}
$packet = pack('CNNa*CNa*',
NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_SUBSYSTEM], strlen('subsystem'), 'subsystem', 1, strlen($subsystem), $subsystem);
$packet = pack(
'CNNa*CNa*',
NET_SSH2_MSG_CHANNEL_REQUEST,
$this->server_channels[self::CHANNEL_SUBSYSTEM],
strlen('subsystem'),
'subsystem',
1,
strlen($subsystem),
$subsystem
);
if (!$this->_send_binary_packet($packet)) {
return false;
}
$this->channel_status[NET_SSH2_CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_REQUEST;
$this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_REQUEST;
$response = $this->_get_channel_packet(NET_SSH2_CHANNEL_SUBSYSTEM);
$response = $this->_get_channel_packet(self::CHANNEL_SUBSYSTEM);
if ($response === false) {
return false;
return false;
}
$this->channel_status[NET_SSH2_CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_DATA;
$this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_DATA;
$this->bitmap |= NET_SSH2_MASK_SHELL;
$this->bitmap |= self::MASK_SHELL;
$this->in_subsystem = true;
return true;
@ -2606,14 +2808,14 @@ class Net_SSH2
/**
* Stops a subsystem.
*
* @see Net_SSH2::startSubsystem()
* @return Boolean
* @see self::startSubsystem()
* @return bool
* @access public
*/
function stopSubsystem()
{
$this->in_subsystem = false;
$this->_close_channel(NET_SSH2_CHANNEL_SUBSYSTEM);
$this->_close_channel(self::CHANNEL_SUBSYSTEM);
return true;
}
@ -2670,12 +2872,23 @@ class Net_SSH2
/**
* Is the connection still active?
*
* @return boolean
* @return bool
* @access public
*/
function isConnected()
{
return (bool) ($this->bitmap & NET_SSH2_MASK_CONNECTED);
return (bool) ($this->bitmap & self::MASK_CONNECTED);
}
/**
* Have you successfully been logged in?
*
* @return bool
* @access public
*/
function isAuthenticated()
{
return (bool) ($this->bitmap & self::MASK_LOGIN);
}
/**
@ -2683,8 +2896,8 @@ class Net_SSH2
*
* See '6. Binary Packet Protocol' of rfc4253 for more info.
*
* @see Net_SSH2::_send_binary_packet()
* @return String
* @see self::_send_binary_packet()
* @return string
* @access private
*/
function _get_binary_packet()
@ -2695,8 +2908,8 @@ class Net_SSH2
return false;
}
$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
$raw = fread($this->fsock, $this->decrypt_block_size);
$start = microtime(true);
$raw = stream_get_contents($this->fsock, $this->decrypt_block_size);
if (!strlen($raw)) {
return '';
@ -2724,7 +2937,7 @@ class Net_SSH2
$buffer = '';
while ($remaining_length > 0) {
$temp = fread($this->fsock, $remaining_length);
$temp = stream_get_contents($this->fsock, $remaining_length);
if ($temp === false || feof($this->fsock)) {
user_error('Error reading from socket');
$this->bitmap = 0;
@ -2733,7 +2946,7 @@ class Net_SSH2
$buffer.= $temp;
$remaining_length-= strlen($temp);
}
$stop = strtok(microtime(), ' ') + strtok('');
$stop = microtime(true);
if (strlen($buffer)) {
$raw.= $this->decrypt !== false ? $this->decrypt->decrypt($buffer) : $buffer;
}
@ -2742,7 +2955,7 @@ class Net_SSH2
$padding = $this->_string_shift($raw, $padding_length); // should leave $raw empty
if ($this->hmac_check !== false) {
$hmac = fread($this->fsock, $this->hmac_size);
$hmac = stream_get_contents($this->fsock, $this->hmac_size);
if ($hmac === false || strlen($hmac) != $this->hmac_size) {
user_error('Error reading socket');
$this->bitmap = 0;
@ -2760,7 +2973,7 @@ class Net_SSH2
$this->get_seq_no++;
if (defined('NET_SSH2_LOGGING')) {
$current = strtok(microtime(), ' ') + strtok('');
$current = microtime(true);
$message_number = isset($this->message_numbers[ord($payload[0])]) ? $this->message_numbers[ord($payload[0])] : 'UNKNOWN (' . ord($payload[0]) . ')';
$message_number = '<- ' . $message_number .
' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)';
@ -2776,8 +2989,8 @@ class Net_SSH2
*
* Because some binary packets need to be ignored...
*
* @see Net_SSH2::_get_binary_packet()
* @return String
* @see self::_get_binary_packet()
* @return string
* @access private
*/
function _filter($payload)
@ -2811,7 +3024,7 @@ class Net_SSH2
}
// see http://tools.ietf.org/html/rfc4252#section-5.4; only called when the encryption has been activated and when we haven't already logged in
if (($this->bitmap & NET_SSH2_MASK_CONNECTED) && !($this->bitmap & NET_SSH2_MASK_LOGIN) && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) {
if (($this->bitmap & self::MASK_CONNECTED) && !($this->bitmap & self::MASK_LOGIN) && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) {
$this->_string_shift($payload, 1);
extract(unpack('Nlength', $this->_string_shift($payload, 4)));
$this->banner_message = utf8_decode($this->_string_shift($payload, $length));
@ -2819,12 +3032,11 @@ class Net_SSH2
}
// only called when we've already logged in
if (($this->bitmap & NET_SSH2_MASK_CONNECTED) && ($this->bitmap & NET_SSH2_MASK_LOGIN)) {
if (($this->bitmap & self::MASK_CONNECTED) && ($this->bitmap & self::MASK_LOGIN)) {
switch (ord($payload[0])) {
case NET_SSH2_MSG_GLOBAL_REQUEST: // see http://tools.ietf.org/html/rfc4254#section-4
$this->_string_shift($payload, 1);
extract(unpack('Nlength', $this->_string_shift($payload)));
$this->errors[] = 'SSH_MSG_GLOBAL_REQUEST: ' . utf8_decode($this->_string_shift($payload, $length));
extract(unpack('Nlength', $this->_string_shift($payload, 4)));
$this->errors[] = 'SSH_MSG_GLOBAL_REQUEST: ' . $this->_string_shift($payload, $length);
if (!$this->_send_binary_packet(pack('C', NET_SSH2_MSG_REQUEST_FAILURE))) {
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
@ -2835,18 +3047,55 @@ class Net_SSH2
case NET_SSH2_MSG_CHANNEL_OPEN: // see http://tools.ietf.org/html/rfc4254#section-5.1
$this->_string_shift($payload, 1);
extract(unpack('Nlength', $this->_string_shift($payload, 4)));
$this->errors[] = 'SSH_MSG_CHANNEL_OPEN: ' . utf8_decode($this->_string_shift($payload, $length));
$this->_string_shift($payload, 4); // skip over client channel
$data = $this->_string_shift($payload, $length);
extract(unpack('Nserver_channel', $this->_string_shift($payload, 4)));
switch ($data) {
case 'auth-agent':
case 'auth-agent@openssh.com':
if (isset($this->agent)) {
$new_channel = self::CHANNEL_AGENT_FORWARD;
$packet = pack('CN3a*Na*',
NET_SSH2_MSG_REQUEST_FAILURE, $server_channel, NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED, 0, '', 0, '');
extract(unpack('Nremote_window_size', $this->_string_shift($payload, 4)));
extract(unpack('Nremote_maximum_packet_size', $this->_string_shift($payload, 4)));
if (!$this->_send_binary_packet($packet)) {
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
$this->packet_size_client_to_server[$new_channel] = $remote_window_size;
$this->window_size_server_to_client[$new_channel] = $remote_maximum_packet_size;
$this->window_size_client_to_server[$new_channel] = $this->window_size;
$packet_size = 0x4000;
$packet = pack(
'CN4',
NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION,
$server_channel,
$new_channel,
$packet_size,
$packet_size
);
$this->server_channels[$new_channel] = $server_channel;
$this->channel_status[$new_channel] = NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION;
if (!$this->_send_binary_packet($packet)) {
return false;
}
}
break;
default:
$packet = pack(
'CN3a*Na*',
NET_SSH2_MSG_REQUEST_FAILURE,
$server_channel,
NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED,
0,
'',
0,
''
);
if (!$this->_send_binary_packet($packet)) {
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
}
}
$payload = $this->_get_binary_packet();
break;
case NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST:
@ -2855,7 +3104,7 @@ class Net_SSH2
extract(unpack('Nwindow_size', $this->_string_shift($payload, 4)));
$this->window_size_client_to_server[$channel]+= $window_size;
$payload = ($this->bitmap & NET_SSH2_MASK_WINDOW_ADJUST) ? true : $this->_get_binary_packet();
$payload = ($this->bitmap & self::MASK_WINDOW_ADJUST) ? true : $this->_get_binary_packet();
}
}
@ -2889,11 +3138,10 @@ class Net_SSH2
/**
* Returns whether Quiet Mode is enabled or not
*
* @see Net_SSH2::enableQuietMode()
* @see Net_SSH2::disableQuietMode()
*
* @see self::enableQuietMode()
* @see self::disableQuietMode()
* @access public
* @return boolean
* @return bool
*/
function isQuietModeEnabled()
{
@ -2923,11 +3171,10 @@ class Net_SSH2
/**
* Returns whether request-pty is enabled or not
*
* @see Net_SSH2::enablePTY()
* @see Net_SSH2::disablePTY()
*
* @see self::enablePTY()
* @see self::disablePTY()
* @access public
* @return boolean
* @return bool
*/
function isPTYEnabled()
{
@ -2940,7 +3187,7 @@ class Net_SSH2
* Returns the data as a string if it's available and false if not.
*
* @param $client_channel
* @return Mixed
* @return mixed
* @access private
*/
function _get_channel_packet($client_channel, $skip_extended = false)
@ -2959,7 +3206,7 @@ class Net_SSH2
$read = array($this->fsock);
$write = $except = null;
$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
$start = microtime(true);
$sec = floor($this->curTimeout);
$usec = 1000000 * ($this->curTimeout - $sec);
// on windows this returns a "Warning: Invalid CRT parameters detected" error
@ -2967,7 +3214,7 @@ class Net_SSH2
$this->is_timeout = true;
return true;
}
$elapsed = strtok(microtime(), ' ') + strtok('') - $start;
$elapsed = microtime(true) - $start;
$this->curTimeout-= $elapsed;
}
@ -2983,48 +3230,63 @@ class Net_SSH2
return '';
}
extract(unpack('Ctype/Nchannel', $this->_string_shift($response, 5)));
extract(unpack('Ctype', $this->_string_shift($response, 1)));
$this->window_size_server_to_client[$channel]-= strlen($response);
// resize the window, if appropriate
if ($this->window_size_server_to_client[$channel] < 0) {
$packet = pack('CNN', NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST, $this->server_channels[$channel], $this->window_size);
if (!$this->_send_binary_packet($packet)) {
return false;
}
$this->window_size_server_to_client[$channel]+= $this->window_size;
if ($type == NET_SSH2_MSG_CHANNEL_OPEN) {
extract(unpack('Nlength', $this->_string_shift($response, 4)));
} else {
extract(unpack('Nchannel', $this->_string_shift($response, 4)));
}
switch ($this->channel_status[$channel]) {
case NET_SSH2_MSG_CHANNEL_OPEN:
switch ($type) {
case NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
extract(unpack('Nserver_channel', $this->_string_shift($response, 4)));
$this->server_channels[$channel] = $server_channel;
extract(unpack('Nwindow_size', $this->_string_shift($response, 4)));
$this->window_size_client_to_server[$channel] = $window_size;
$temp = unpack('Npacket_size_client_to_server', $this->_string_shift($response, 4));
$this->packet_size_client_to_server[$channel] = $temp['packet_size_client_to_server'];
return $client_channel == $channel ? true : $this->_get_channel_packet($client_channel, $skip_extended);
//case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE:
default:
user_error('Unable to open channel');
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
// will not be setup yet on incoming channel open request
if (isset($channel) && isset($this->channel_status[$channel]) && isset($this->window_size_server_to_client[$channel])) {
$this->window_size_server_to_client[$channel]-= strlen($response);
// resize the window, if appropriate
if ($this->window_size_server_to_client[$channel] < 0) {
$packet = pack('CNN', NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST, $this->server_channels[$channel], $this->window_size);
if (!$this->_send_binary_packet($packet)) {
return false;
}
break;
case NET_SSH2_MSG_CHANNEL_REQUEST:
switch ($type) {
case NET_SSH2_MSG_CHANNEL_SUCCESS:
return true;
case NET_SSH2_MSG_CHANNEL_FAILURE:
return false;
default:
user_error('Unable to fulfill channel request');
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
}
case NET_SSH2_MSG_CHANNEL_CLOSE:
return $type == NET_SSH2_MSG_CHANNEL_CLOSE ? true : $this->_get_channel_packet($client_channel, $skip_extended);
$this->window_size_server_to_client[$channel]+= $this->window_size;
}
switch ($this->channel_status[$channel]) {
case NET_SSH2_MSG_CHANNEL_OPEN:
switch ($type) {
case NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
extract(unpack('Nserver_channel', $this->_string_shift($response, 4)));
$this->server_channels[$channel] = $server_channel;
extract(unpack('Nwindow_size', $this->_string_shift($response, 4)));
if ($window_size < 0) {
$window_size&= 0x7FFFFFFF;
$window_size+= 0x80000000;
}
$this->window_size_client_to_server[$channel] = $window_size;
$temp = unpack('Npacket_size_client_to_server', $this->_string_shift($response, 4));
$this->packet_size_client_to_server[$channel] = $temp['packet_size_client_to_server'];
$result = $client_channel == $channel ? true : $this->_get_channel_packet($client_channel, $skip_extended);
$this->_on_channel_open();
return $result;
//case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE:
default:
user_error('Unable to open channel');
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
}
break;
case NET_SSH2_MSG_CHANNEL_REQUEST:
switch ($type) {
case NET_SSH2_MSG_CHANNEL_SUCCESS:
return true;
case NET_SSH2_MSG_CHANNEL_FAILURE:
return false;
default:
user_error('Unable to fulfill channel request');
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
}
case NET_SSH2_MSG_CHANNEL_CLOSE:
return $type == NET_SSH2_MSG_CHANNEL_CLOSE ? true : $this->_get_channel_packet($client_channel, $skip_extended);
}
}
// ie. $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA
@ -3032,7 +3294,7 @@ class Net_SSH2
switch ($type) {
case NET_SSH2_MSG_CHANNEL_DATA:
/*
if ($channel == NET_SSH2_CHANNEL_EXEC) {
if ($channel == self::CHANNEL_EXEC) {
// SCP requires null packets, such as this, be sent. further, in the case of the ssh.com SSH server
// this actually seems to make things twice as fast. more to the point, the message right after
// SSH_MSG_CHANNEL_DATA (usually SSH_MSG_IGNORE) won't block for as long as it would have otherwise.
@ -3042,6 +3304,15 @@ class Net_SSH2
*/
extract(unpack('Nlength', $this->_string_shift($response, 4)));
$data = $this->_string_shift($response, $length);
if ($channel == self::CHANNEL_AGENT_FORWARD) {
$agent_response = $this->agent->_forward_data($data);
if (!is_bool($agent_response)) {
$this->_send_channel_packet($channel, $agent_response);
}
break;
}
if ($client_channel == $channel) {
return $data;
}
@ -3052,7 +3323,7 @@ class Net_SSH2
break;
case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
/*
if ($client_channel == NET_SSH2_CHANNEL_EXEC) {
if ($client_channel == self::CHANNEL_EXEC) {
$this->_send_channel_packet($client_channel, chr(0));
}
*/
@ -3108,15 +3379,17 @@ class Net_SSH2
case NET_SSH2_MSG_CHANNEL_CLOSE:
$this->curTimeout = 0;
if ($this->bitmap & NET_SSH2_MASK_SHELL) {
$this->bitmap&= ~NET_SSH2_MASK_SHELL;
if ($this->bitmap & self::MASK_SHELL) {
$this->bitmap&= ~self::MASK_SHELL;
}
if ($this->channel_status[$channel] != NET_SSH2_MSG_CHANNEL_EOF) {
$this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel]));
}
$this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_CLOSE;
return true;
if ($client_channel == $channel) {
return true;
}
case NET_SSH2_MSG_CHANNEL_EOF:
break;
default:
@ -3131,10 +3404,10 @@ class Net_SSH2
*
* See '6. Binary Packet Protocol' of rfc4253 for more info.
*
* @param String $data
* @param optional String $logged
* @see Net_SSH2::_get_binary_packet()
* @return Boolean
* @param string $data
* @param string $logged
* @see self::_get_binary_packet()
* @return bool
* @access private
*/
function _send_binary_packet($data, $logged = null)
@ -3157,7 +3430,7 @@ class Net_SSH2
$packet_length+= (($this->encrypt_block_size - 1) * $packet_length) % $this->encrypt_block_size;
// subtracting strlen($data) is obvious - subtracting 5 is necessary because of packet_length and padding_length
$padding_length = $packet_length - strlen($data) - 5;
$padding = crypt_random_string($padding_length);
$padding = Random::string($padding_length);
// we subtract 4 from packet_length because the packet_length field isn't supposed to include itself
$packet = pack('NCa*', $packet_length - 4, $padding_length, $data . $padding);
@ -3171,12 +3444,12 @@ class Net_SSH2
$packet.= $hmac;
$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
$start = microtime(true);
$result = strlen($packet) == fputs($this->fsock, $packet);
$stop = strtok(microtime(), ' ') + strtok('');
$stop = microtime(true);
if (defined('NET_SSH2_LOGGING')) {
$current = strtok(microtime(), ' ') + strtok('');
$current = microtime(true);
$message_number = isset($this->message_numbers[ord($data[0])]) ? $this->message_numbers[ord($data[0])] : 'UNKNOWN (' . ord($data[0]) . ')';
$message_number = '-> ' . $message_number .
' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)';
@ -3192,7 +3465,7 @@ class Net_SSH2
*
* Makes sure that only the last 1MB worth of packets will be logged
*
* @param String $data
* @param string $data
* @access private
*/
function _append_log($message_number, $message)
@ -3204,15 +3477,15 @@ class Net_SSH2
switch (NET_SSH2_LOGGING) {
// useful for benchmarks
case NET_SSH2_LOG_SIMPLE:
case self::LOG_SIMPLE:
$this->message_number_log[] = $message_number;
break;
// the most useful log for SSH2
case NET_SSH2_LOG_COMPLEX:
case self::LOG_COMPLEX:
$this->message_number_log[] = $message_number;
$this->log_size+= strlen($message);
$this->message_log[] = $message;
while ($this->log_size > NET_SSH2_LOG_MAX_SIZE) {
while ($this->log_size > self::LOG_MAX_SIZE) {
$this->log_size-= strlen(array_shift($this->message_log));
array_shift($this->message_number_log);
}
@ -3220,7 +3493,7 @@ class Net_SSH2
// dump the output out realtime; packets may be interspersed with non packets,
// passwords won't be filtered out and select other packets may not be correctly
// identified
case NET_SSH2_LOG_REALTIME:
case self::LOG_REALTIME:
switch (PHP_SAPI) {
case 'cli':
$start = $stop = "\r\n";
@ -3233,14 +3506,14 @@ class Net_SSH2
@flush();
@ob_flush();
break;
// basically the same thing as NET_SSH2_LOG_REALTIME with the caveat that NET_SSH2_LOG_REALTIME_FILE
// needs to be defined and that the resultant log file will be capped out at NET_SSH2_LOG_MAX_SIZE.
// basically the same thing as self::LOG_REALTIME with the caveat that self::LOG_REALTIME_FILE
// needs to be defined and that the resultant log file will be capped out at self::LOG_MAX_SIZE.
// the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily
// at the beginning of the file
case NET_SSH2_LOG_REALTIME_FILE:
case self::LOG_REALTIME_FILE:
if (!isset($this->realtime_log_file)) {
// PHP doesn't seem to like using constants in fopen()
$filename = NET_SSH2_LOG_REALTIME_FILENAME;
$filename = self::LOG_REALTIME_FILENAME;
$fp = fopen($filename, 'w');
$this->realtime_log_file = $fp;
}
@ -3254,7 +3527,7 @@ class Net_SSH2
fseek($this->realtime_log_file, ftell($this->realtime_log_file) - strlen($temp));
}
$this->realtime_log_size+= strlen($entry);
if ($this->realtime_log_size > NET_SSH2_LOG_MAX_SIZE) {
if ($this->realtime_log_size > self::LOG_MAX_SIZE) {
fseek($this->realtime_log_file, 0);
$this->realtime_log_size = strlen($entry);
$this->realtime_log_wrap = true;
@ -3268,19 +3541,19 @@ class Net_SSH2
*
* Spans multiple SSH_MSG_CHANNEL_DATAs if appropriate
*
* @param Integer $client_channel
* @param String $data
* @return Boolean
* @param int $client_channel
* @param string $data
* @return bool
* @access private
*/
function _send_channel_packet($client_channel, $data)
{
while (strlen($data)) {
if (!$this->window_size_client_to_server[$client_channel]) {
$this->bitmap^= NET_SSH2_MASK_WINDOW_ADJUST;
$this->bitmap^= self::MASK_WINDOW_ADJUST;
// using an invalid channel will let the buffers be built up for the valid channels
$this->_get_channel_packet(-1);
$this->bitmap^= NET_SSH2_MASK_WINDOW_ADJUST;
$this->bitmap^= self::MASK_WINDOW_ADJUST;
}
/* The maximum amount of data allowed is determined by the maximum
@ -3293,7 +3566,8 @@ class Net_SSH2
);
$temp = $this->_string_shift($data, $max_size);
$packet = pack('CN2a*',
$packet = pack(
'CN2a*',
NET_SSH2_MSG_CHANNEL_DATA,
$this->server_channels[$client_channel],
strlen($temp),
@ -3311,13 +3585,13 @@ class Net_SSH2
/**
* Closes and flushes a channel
*
* Net_SSH2 doesn't properly close most channels. For exec() channels are normally closed by the server
* \phpseclib\Net\SSH2 doesn't properly close most channels. For exec() channels are normally closed by the server
* and for SFTP channels are presumably closed when the client disconnects. This functions is intended
* for SCP more than anything.
*
* @param Integer $client_channel
* @param Boolean $want_reply
* @return Boolean
* @param int $client_channel
* @param bool $want_reply
* @return bool
* @access private
*/
function _close_channel($client_channel, $want_reply = false)
@ -3334,27 +3608,28 @@ class Net_SSH2
$this->curTimeout = 0;
while (!is_bool($this->_get_channel_packet($client_channel)));
while (!is_bool($this->_get_channel_packet($client_channel))) {
}
if ($want_reply) {
$this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel]));
}
if ($this->bitmap & NET_SSH2_MASK_SHELL) {
$this->bitmap&= ~NET_SSH2_MASK_SHELL;
if ($this->bitmap & self::MASK_SHELL) {
$this->bitmap&= ~self::MASK_SHELL;
}
}
/**
* Disconnect
*
* @param Integer $reason
* @return Boolean
* @param int $reason
* @return bool
* @access private
*/
function _disconnect($reason)
{
if ($this->bitmap & NET_SSH2_MASK_CONNECTED) {
if ($this->bitmap & self::MASK_CONNECTED) {
$data = pack('CNNa*Na*', NET_SSH2_MSG_DISCONNECT, $reason, 0, '', 0, '');
$this->_send_binary_packet($data);
$this->bitmap = 0;
@ -3368,9 +3643,9 @@ class Net_SSH2
*
* Inspired by array_shift
*
* @param String $string
* @param optional Integer $index
* @return String
* @param string $string
* @param int $index
* @return string
* @access private
*/
function _string_shift(&$string, $index = 1)
@ -3387,14 +3662,14 @@ class Net_SSH2
* named constants from it, using the value as the name of the constant and the index as the value of the constant.
* If any of the constants that would be defined already exists, none of the constants will be defined.
*
* @param Array $array
* @param array $array
* @access private
*/
function _define_array()
{
$args = func_get_args();
foreach ($args as $arg) {
foreach ($arg as $key=>$value) {
foreach ($arg as $key => $value) {
if (!defined($value)) {
define($value, $key);
} else {
@ -3407,10 +3682,10 @@ class Net_SSH2
/**
* Returns a log of the packets that have been sent and received.
*
* Returns a string if NET_SSH2_LOGGING == NET_SSH2_LOG_COMPLEX, an array if NET_SSH2_LOGGING == NET_SSH2_LOG_SIMPLE and false if !defined('NET_SSH2_LOGGING')
* Returns a string if NET_SSH2_LOGGING == self::LOG_COMPLEX, an array if NET_SSH2_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SSH2_LOGGING')
*
* @access public
* @return String or Array
* @return array|false|string
*/
function getLog()
{
@ -3419,10 +3694,10 @@ class Net_SSH2
}
switch (NET_SSH2_LOGGING) {
case NET_SSH2_LOG_SIMPLE:
case self::LOG_SIMPLE:
return $this->message_number_log;
break;
case NET_SSH2_LOG_COMPLEX:
case self::LOG_COMPLEX:
return $this->_format_log($this->message_log, $this->message_number_log);
break;
default:
@ -3433,10 +3708,10 @@ class Net_SSH2
/**
* Formats a log for printing
*
* @param Array $message_log
* @param Array $message_number_log
* @param array $message_log
* @param array $message_number_log
* @access private
* @return String
* @return string
*/
function _format_log($message_log, $message_number_log)
{
@ -3469,19 +3744,54 @@ class Net_SSH2
*
* For use with preg_replace_callback()
*
* @param Array $matches
* @param array $matches
* @access private
* @return String
* @return string
*/
function _format_log_helper($matches)
{
return $this->log_boundary . str_pad(dechex(ord($matches[0])), 2, '0', STR_PAD_LEFT);
}
/**
* Helper function for agent->_on_channel_open()
*
* Used when channels are created to inform agent
* of said channel opening. Must be called after
* channel open confirmation received
*
* @access private
*/
function _on_channel_open()
{
if (isset($this->agent)) {
$this->agent->_on_channel_open($this);
}
}
/**
* Returns the first value of the intersection of two arrays or false if
* the intersection is empty. The order is defined by the first parameter.
*
* @param array $array1
* @param array $array2
* @return mixed False if intersection is empty, else intersected value.
* @access private
*/
function _array_intersect_first($array1, $array2)
{
foreach ($array1 as $value) {
if (in_array($value, $array2)) {
return $value;
}
}
return false;
}
/**
* Returns all errors
*
* @return String
* @return string[]
* @access public
*/
function getErrors()
@ -3492,18 +3802,22 @@ class Net_SSH2
/**
* Returns the last error
*
* @return String
* @return string
* @access public
*/
function getLastError()
{
return $this->errors[count($this->errors) - 1];
$count = count($this->errors);
if ($count > 0) {
return $this->errors[$count - 1];
}
}
/**
* Return the server identification.
*
* @return String
* @return string
* @access public
*/
function getServerIdentification()
@ -3516,7 +3830,7 @@ class Net_SSH2
/**
* Return a list of the key exchange algorithms the server supports.
*
* @return Array
* @return array
* @access public
*/
function getKexAlgorithms()
@ -3529,7 +3843,7 @@ class Net_SSH2
/**
* Return a list of the host key (public key) algorithms the server supports.
*
* @return Array
* @return array
* @access public
*/
function getServerHostKeyAlgorithms()
@ -3542,7 +3856,7 @@ class Net_SSH2
/**
* Return a list of the (symmetric key) encryption algorithms the server supports, when receiving stuff from the client.
*
* @return Array
* @return array
* @access public
*/
function getEncryptionAlgorithmsClient2Server()
@ -3555,7 +3869,7 @@ class Net_SSH2
/**
* Return a list of the (symmetric key) encryption algorithms the server supports, when sending stuff to the client.
*
* @return Array
* @return array
* @access public
*/
function getEncryptionAlgorithmsServer2Client()
@ -3568,7 +3882,7 @@ class Net_SSH2
/**
* Return a list of the MAC algorithms the server supports, when receiving stuff from the client.
*
* @return Array
* @return array
* @access public
*/
function getMACAlgorithmsClient2Server()
@ -3581,7 +3895,7 @@ class Net_SSH2
/**
* Return a list of the MAC algorithms the server supports, when sending stuff to the client.
*
* @return Array
* @return array
* @access public
*/
function getMACAlgorithmsServer2Client()
@ -3594,7 +3908,7 @@ class Net_SSH2
/**
* Return a list of the compression algorithms the server supports, when receiving stuff from the client.
*
* @return Array
* @return array
* @access public
*/
function getCompressionAlgorithmsClient2Server()
@ -3607,7 +3921,7 @@ class Net_SSH2
/**
* Return a list of the compression algorithms the server supports, when sending stuff to the client.
*
* @return Array
* @return array
* @access public
*/
function getCompressionAlgorithmsServer2Client()
@ -3620,7 +3934,7 @@ class Net_SSH2
/**
* Return a list of the languages the server supports, when sending stuff to the client.
*
* @return Array
* @return array
* @access public
*/
function getLanguagesServer2Client()
@ -3633,7 +3947,7 @@ class Net_SSH2
/**
* Return a list of the languages the server supports, when receiving stuff from the client.
*
* @return Array
* @return array
* @access public
*/
function getLanguagesClient2Server()
@ -3649,7 +3963,7 @@ class Net_SSH2
* Quoting from the RFC, "in some jurisdictions, sending a warning message before
* authentication may be relevant for getting legal protection."
*
* @return String
* @return string
* @access public
*/
function getBannerMessage()
@ -3663,12 +3977,12 @@ class Net_SSH2
* Caching this the first time you connect to a server and checking the result on subsequent connections
* is recommended. Returns false if the server signature is not signed correctly with the public host key.
*
* @return Mixed
* @return mixed
* @access public
*/
function getServerPublicHostKey()
{
if (!($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR)) {
if (!($this->bitmap & self::MASK_CONSTRUCTOR)) {
if (!$this->_connect()) {
return false;
}
@ -3690,19 +4004,19 @@ class Net_SSH2
switch ($this->signature_format) {
case 'ssh-dss':
$zero = new Math_BigInteger();
$zero = new BigInteger();
$temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
$p = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
$p = new BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
$temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
$q = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
$q = new BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
$temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
$g = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
$g = new BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
$temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
$y = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
$y = new BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
/* The value for 'dss_signature_blob' is encoded as a string containing
r, followed by s (which are 160-bit integers, without lengths or
@ -3713,8 +4027,8 @@ class Net_SSH2
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
$r = new Math_BigInteger($this->_string_shift($signature, 20), 256);
$s = new Math_BigInteger($this->_string_shift($signature, 20), 256);
$r = new BigInteger($this->_string_shift($signature, 20), 256);
$s = new BigInteger($this->_string_shift($signature, 20), 256);
switch (true) {
case $r->equals($zero):
@ -3727,7 +4041,7 @@ class Net_SSH2
$w = $s->modInverse($q);
$u1 = $w->multiply(new Math_BigInteger(sha1($this->exchange_hash), 16));
$u1 = $w->multiply(new BigInteger(sha1($this->exchange_hash), 16));
list(, $u1) = $u1->divide($q);
$u2 = $w->multiply($r);
@ -3748,24 +4062,20 @@ class Net_SSH2
break;
case 'ssh-rsa':
$temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
$e = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
$e = new BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
$temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
$rawN = $this->_string_shift($server_public_host_key, $temp['length']);
$n = new Math_BigInteger($rawN, -256);
$n = new BigInteger($rawN, -256);
$nLength = strlen(ltrim($rawN, "\0"));
/*
$temp = unpack('Nlength', $this->_string_shift($signature, 4));
$signature = $this->_string_shift($signature, $temp['length']);
if (!class_exists('Crypt_RSA')) {
include_once 'Crypt/RSA.php';
}
$rsa = new Crypt_RSA();
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$rsa->loadKey(array('e' => $e, 'n' => $n), CRYPT_RSA_PUBLIC_FORMAT_RAW);
$rsa = new RSA();
$rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);
$rsa->loadKey(array('e' => $e, 'n' => $n), RSA::PUBLIC_FORMAT_RAW);
if (!$rsa->verify($this->exchange_hash, $signature)) {
user_error('Bad server signature');
return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
@ -3773,7 +4083,7 @@ class Net_SSH2
*/
$temp = unpack('Nlength', $this->_string_shift($signature, 4));
$s = new Math_BigInteger($this->_string_shift($signature, $temp['length']), 256);
$s = new BigInteger($this->_string_shift($signature, $temp['length']), 256);
// validate an RSA signature per "8.2 RSASSA-PKCS1-v1_5", "5.2.2 RSAVP1", and "9.1 EMSA-PSS" in the
// following URL:
@ -3781,7 +4091,7 @@ class Net_SSH2
// also, see SSHRSA.c (rsa2_verifysig) in PuTTy's source.
if ($s->compare(new Math_BigInteger()) < 0 || $s->compare($n->subtract(new Math_BigInteger(1))) > 0) {
if ($s->compare(new BigInteger()) < 0 || $s->compare($n->subtract(new BigInteger(1))) > 0) {
user_error('Invalid signature');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
@ -3808,7 +4118,7 @@ class Net_SSH2
/**
* Returns the exit status of an SSH command or false.
*
* @return Integer or false
* @return false|int
* @access public
*/
function getExitStatus()
@ -3822,7 +4132,7 @@ class Net_SSH2
/**
* Returns the number of columns for the terminal window size.
*
* @return Integer
* @return int
* @access public
*/
function getWindowColumns()
@ -3833,7 +4143,7 @@ class Net_SSH2
/**
* Returns the number of rows for the terminal window size.
*
* @return Integer
* @return int
* @access public
*/
function getWindowRows()
@ -3844,7 +4154,7 @@ class Net_SSH2
/**
* Sets the number of columns for the terminal window size.
*
* @param Integer $value
* @param int $value
* @access public
*/
function setWindowColumns($value)
@ -3855,7 +4165,7 @@ class Net_SSH2
/**
* Sets the number of rows for the terminal window size.
*
* @param Integer $value
* @param int $value
* @access public
*/
function setWindowRows($value)
@ -3866,8 +4176,8 @@ class Net_SSH2
/**
* Sets the number of columns and rows for the terminal window size.
*
* @param Integer $columns
* @param Integer $rows
* @param int $columns
* @param int $rows
* @access public
*/
function setWindowSize($columns = 80, $rows = 24)

View file

@ -1,18 +1,18 @@
<?php
/**
* Pure-PHP ssh-agent client.
*
* PHP versions 4 and 5
* PHP version 5
*
* Here are some examples of how to use this library:
* <code>
* <?php
* include 'System/SSH/Agent.php';
* include 'Net/SSH2.php';
* include 'vendor/autoload.php';
*
* $agent = new System_SSH_Agent();
* $agent = new \phpseclib\System\SSH\Agent();
*
* $ssh = new Net_SSH2('www.domain.tld');
* $ssh = new \phpseclib\Net\SSH2('www.domain.tld');
* if (!$ssh->login('username', $agent)) {
* exit('Login Failed');
* }
@ -22,26 +22,8 @@
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category System
* @package System_SSH_Agent
* @package SSH\Agent
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2014 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
@ -49,189 +31,93 @@
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent
*/
/**#@+
* Message numbers
*
* @access private
*/
// to request SSH1 keys you have to use SSH_AGENTC_REQUEST_RSA_IDENTITIES (1)
define('SYSTEM_SSH_AGENTC_REQUEST_IDENTITIES', 11);
// this is the SSH2 response; the SSH1 response is SSH_AGENT_RSA_IDENTITIES_ANSWER (2).
define('SYSTEM_SSH_AGENT_IDENTITIES_ANSWER', 12);
define('SYSTEM_SSH_AGENT_FAILURE', 5);
// the SSH1 request is SSH_AGENTC_RSA_CHALLENGE (3)
define('SYSTEM_SSH_AGENTC_SIGN_REQUEST', 13);
// the SSH1 response is SSH_AGENT_RSA_RESPONSE (4)
define('SYSTEM_SSH_AGENT_SIGN_RESPONSE', 14);
/**#@-*/
namespace phpseclib\System\SSH;
/**
* Pure-PHP ssh-agent client identity object
*
* Instantiation should only be performed by System_SSH_Agent class.
* This could be thought of as implementing an interface that Crypt_RSA
* implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something.
* The methods in this interface would be getPublicKey, setSignatureMode
* and sign since those are the methods phpseclib looks for to perform
* public key authentication.
*
* @package System_SSH_Agent
* @author Jim Wigginton <terrafrost@php.net>
* @access internal
*/
class System_SSH_Agent_Identity
{
/**
* Key Object
*
* @var Crypt_RSA
* @access private
* @see System_SSH_Agent_Identity::getPublicKey()
*/
var $key;
/**
* Key Blob
*
* @var String
* @access private
* @see System_SSH_Agent_Identity::sign()
*/
var $key_blob;
/**
* Socket Resource
*
* @var Resource
* @access private
* @see System_SSH_Agent_Identity::sign()
*/
var $fsock;
/**
* Default Constructor.
*
* @param Resource $fsock
* @return System_SSH_Agent_Identity
* @access private
*/
function System_SSH_Agent_Identity($fsock)
{
$this->fsock = $fsock;
}
/**
* Set Public Key
*
* Called by System_SSH_Agent::requestIdentities()
*
* @param Crypt_RSA $key
* @access private
*/
function setPublicKey($key)
{
$this->key = $key;
$this->key->setPublicKey();
}
/**
* Set Public Key
*
* Called by System_SSH_Agent::requestIdentities(). The key blob could be extracted from $this->key
* but this saves a small amount of computation.
*
* @param String $key_blob
* @access private
*/
function setPublicKeyBlob($key_blob)
{
$this->key_blob = $key_blob;
}
/**
* Get Public Key
*
* Wrapper for $this->key->getPublicKey()
*
* @param Integer $format optional
* @return Mixed
* @access public
*/
function getPublicKey($format = null)
{
return !isset($format) ? $this->key->getPublicKey() : $this->key->getPublicKey($format);
}
/**
* Set Signature Mode
*
* Doesn't do anything as ssh-agent doesn't let you pick and choose the signature mode. ie.
* ssh-agent's only supported mode is CRYPT_RSA_SIGNATURE_PKCS1
*
* @param Integer $mode
* @access public
*/
function setSignatureMode($mode)
{
}
/**
* Create a signature
*
* See "2.6.2 Protocol 2 private key signature request"
*
* @param String $message
* @return String
* @access public
*/
function sign($message)
{
// the last parameter (currently 0) is for flags and ssh-agent only defines one flag (for ssh-dss): SSH_AGENT_OLD_SIGNATURE
$packet = pack('CNa*Na*N', SYSTEM_SSH_AGENTC_SIGN_REQUEST, strlen($this->key_blob), $this->key_blob, strlen($message), $message, 0);
$packet = pack('Na*', strlen($packet), $packet);
if (strlen($packet) != fputs($this->fsock, $packet)) {
user_error('Connection closed during signing');
}
$length = current(unpack('N', fread($this->fsock, 4)));
$type = ord(fread($this->fsock, 1));
if ($type != SYSTEM_SSH_AGENT_SIGN_RESPONSE) {
user_error('Unable to retreive signature');
}
$signature_blob = fread($this->fsock, $length - 1);
// the only other signature format defined - ssh-dss - is the same length as ssh-rsa
// the + 12 is for the other various SSH added length fields
return substr($signature_blob, strlen('ssh-rsa') + 12);
}
}
use phpseclib\Crypt\RSA;
use phpseclib\System\SSH\Agent\Identity;
/**
* Pure-PHP ssh-agent client identity factory
*
* requestIdentities() method pumps out System_SSH_Agent_Identity objects
* requestIdentities() method pumps out \phpseclib\System\SSH\Agent\Identity objects
*
* @package System_SSH_Agent
* @package SSH\Agent
* @author Jim Wigginton <terrafrost@php.net>
* @access internal
*/
class System_SSH_Agent
class Agent
{
/**#@+
* Message numbers
*
* @access private
*/
// to request SSH1 keys you have to use SSH_AGENTC_REQUEST_RSA_IDENTITIES (1)
const SSH_AGENTC_REQUEST_IDENTITIES = 11;
// this is the SSH2 response; the SSH1 response is SSH_AGENT_RSA_IDENTITIES_ANSWER (2).
const SSH_AGENT_IDENTITIES_ANSWER = 12;
// the SSH1 request is SSH_AGENTC_RSA_CHALLENGE (3)
const SSH_AGENTC_SIGN_REQUEST = 13;
// the SSH1 response is SSH_AGENT_RSA_RESPONSE (4)
const SSH_AGENT_SIGN_RESPONSE = 14;
/**#@-*/
/**@+
* Agent forwarding status
*
* @access private
*/
// no forwarding requested and not active
const FORWARD_NONE = 0;
// request agent forwarding when opportune
const FORWARD_REQUEST = 1;
// forwarding has been request and is active
const FORWARD_ACTIVE = 2;
/**#@-*/
/**
* Unused
*/
const SSH_AGENT_FAILURE = 5;
/**
* Socket Resource
*
* @var Resource
* @var resource
* @access private
*/
var $fsock;
/**
* Agent forwarding status
*
* @access private
*/
var $forward_status = self::FORWARD_NONE;
/**
* Buffer for accumulating forwarded authentication
* agent data arriving on SSH data channel destined
* for agent unix socket
*
* @access private
*/
var $socket_buffer = '';
/**
* Tracking the number of bytes we are expecting
* to arrive for the agent socket on the SSH data
* channel
*/
var $expected_bytes = 0;
/**
* Default Constructor
*
* @return System_SSH_Agent
* @return \phpseclib\System\SSH\Agent
* @access public
*/
function System_SSH_Agent()
function __construct()
{
switch (true) {
case isset($_SERVER['SSH_AUTH_SOCK']):
@ -255,9 +141,9 @@ class System_SSH_Agent
* Request Identities
*
* See "2.5.2 Requesting a list of protocol 2 keys"
* Returns an array containing zero or more System_SSH_Agent_Identity objects
* Returns an array containing zero or more \phpseclib\System\SSH\Agent\Identity objects
*
* @return Array
* @return array
* @access public
*/
function requestIdentities()
@ -266,14 +152,14 @@ class System_SSH_Agent
return array();
}
$packet = pack('NC', 1, SYSTEM_SSH_AGENTC_REQUEST_IDENTITIES);
$packet = pack('NC', 1, self::SSH_AGENTC_REQUEST_IDENTITIES);
if (strlen($packet) != fputs($this->fsock, $packet)) {
user_error('Connection closed while requesting identities');
}
$length = current(unpack('N', fread($this->fsock, 4)));
$type = ord(fread($this->fsock, 1));
if ($type != SYSTEM_SSH_AGENT_IDENTITIES_ANSWER) {
if ($type != self::SSH_AGENT_IDENTITIES_ANSWER) {
user_error('Unable to request identities');
}
@ -282,17 +168,17 @@ class System_SSH_Agent
for ($i = 0; $i < $keyCount; $i++) {
$length = current(unpack('N', fread($this->fsock, 4)));
$key_blob = fread($this->fsock, $length);
$key_str = 'ssh-rsa ' . base64_encode($key_blob);
$length = current(unpack('N', fread($this->fsock, 4)));
$key_comment = fread($this->fsock, $length);
if ($length) {
$key_str.= ' ' . fread($this->fsock, $length);
}
$length = current(unpack('N', substr($key_blob, 0, 4)));
$key_type = substr($key_blob, 4, $length);
switch ($key_type) {
case 'ssh-rsa':
if (!class_exists('Crypt_RSA')) {
include_once 'Crypt/RSA.php';
}
$key = new Crypt_RSA();
$key->loadKey('ssh-rsa ' . base64_encode($key_blob) . ' ' . $key_comment);
$key = new RSA();
$key->loadKey($key_str);
break;
case 'ssh-dss':
// not currently supported
@ -300,7 +186,7 @@ class System_SSH_Agent
}
// resources are passed by reference by default
if (isset($key)) {
$identity = new System_SSH_Agent_Identity($this->fsock);
$identity = new Identity($this->fsock);
$identity->setPublicKey($key);
$identity->setPublicKeyBlob($key_blob);
$identities[] = $identity;
@ -310,4 +196,113 @@ class System_SSH_Agent
return $identities;
}
/**
* Signal that agent forwarding should
* be requested when a channel is opened
*
* @param Net_SSH2 $ssh
* @return bool
* @access public
*/
function startSSHForwarding($ssh)
{
if ($this->forward_status == self::FORWARD_NONE) {
$this->forward_status = self::FORWARD_REQUEST;
}
}
/**
* Request agent forwarding of remote server
*
* @param Net_SSH2 $ssh
* @return bool
* @access private
*/
function _request_forwarding($ssh)
{
$request_channel = $ssh->_get_open_channel();
if ($request_channel === false) {
return false;
}
$packet = pack(
'CNNa*C',
NET_SSH2_MSG_CHANNEL_REQUEST,
$ssh->server_channels[$request_channel],
strlen('auth-agent-req@openssh.com'),
'auth-agent-req@openssh.com',
1
);
$ssh->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_REQUEST;
if (!$ssh->_send_binary_packet($packet)) {
return false;
}
$response = $ssh->_get_channel_packet($request_channel);
if ($response === false) {
return false;
}
$ssh->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_OPEN;
$this->forward_status = self::FORWARD_ACTIVE;
return true;
}
/**
* On successful channel open
*
* This method is called upon successful channel
* open to give the SSH Agent an opportunity
* to take further action. i.e. request agent forwarding
*
* @param Net_SSH2 $ssh
* @access private
*/
function _on_channel_open($ssh)
{
if ($this->forward_status == self::FORWARD_REQUEST) {
$this->_request_forwarding($ssh);
}
}
/**
* Forward data to SSH Agent and return data reply
*
* @param string $data
* @return data from SSH Agent
* @access private
*/
function _forward_data($data)
{
if ($this->expected_bytes > 0) {
$this->socket_buffer.= $data;
$this->expected_bytes -= strlen($data);
} else {
$agent_data_bytes = current(unpack('N', $data));
$current_data_bytes = strlen($data);
$this->socket_buffer = $data;
if ($current_data_bytes != $agent_data_bytes + 4) {
$this->expected_bytes = ($agent_data_bytes + 4) - $current_data_bytes;
return false;
}
}
if (strlen($this->socket_buffer) != fwrite($this->fsock, $this->socket_buffer)) {
user_error('Connection closed attempting to forward data to SSH agent');
}
$this->socket_buffer = '';
$this->expected_bytes = 0;
$agent_reply_bytes = current(unpack('N', fread($this->fsock, 4)));
$agent_reply_data = fread($this->fsock, $agent_reply_bytes);
$agent_reply_data = current(unpack('a*', $agent_reply_data));
return pack('Na*', $agent_reply_bytes, $agent_reply_data);
}
}

View file

@ -0,0 +1,158 @@
<?php
/**
* Pure-PHP ssh-agent client.
*
* PHP version 5
*
* @category System
* @package SSH\Agent
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2009 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent
*/
namespace phpseclib\System\SSH\Agent;
use phpseclib\System\SSH\Agent;
/**
* Pure-PHP ssh-agent client identity object
*
* Instantiation should only be performed by \phpseclib\System\SSH\Agent class.
* This could be thought of as implementing an interface that phpseclib\Crypt\RSA
* implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something.
* The methods in this interface would be getPublicKey and sign since those are the
* methods phpseclib looks for to perform public key authentication.
*
* @package SSH\Agent
* @author Jim Wigginton <terrafrost@php.net>
* @access internal
*/
class Identity
{
/**
* Key Object
*
* @var \phpseclib\Crypt\RSA
* @access private
* @see self::getPublicKey()
*/
var $key;
/**
* Key Blob
*
* @var string
* @access private
* @see self::sign()
*/
var $key_blob;
/**
* Socket Resource
*
* @var resource
* @access private
* @see self::sign()
*/
var $fsock;
/**
* Default Constructor.
*
* @param resource $fsock
* @return \phpseclib\System\SSH\Agent\Identity
* @access private
*/
function __construct($fsock)
{
$this->fsock = $fsock;
}
/**
* Set Public Key
*
* Called by \phpseclib\System\SSH\Agent::requestIdentities()
*
* @param \phpseclib\Crypt\RSA $key
* @access private
*/
function setPublicKey($key)
{
$this->key = $key;
$this->key->setPublicKey();
}
/**
* Set Public Key
*
* Called by \phpseclib\System\SSH\Agent::requestIdentities(). The key blob could be extracted from $this->key
* but this saves a small amount of computation.
*
* @param string $key_blob
* @access private
*/
function setPublicKeyBlob($key_blob)
{
$this->key_blob = $key_blob;
}
/**
* Get Public Key
*
* Wrapper for $this->key->getPublicKey()
*
* @param int $format optional
* @return mixed
* @access public
*/
function getPublicKey($format = null)
{
return !isset($format) ? $this->key->getPublicKey() : $this->key->getPublicKey($format);
}
/**
* Set Signature Mode
*
* Doesn't do anything as ssh-agent doesn't let you pick and choose the signature mode. ie.
* ssh-agent's only supported mode is \phpseclib\Crypt\RSA::SIGNATURE_PKCS1
*
* @param int $mode
* @access public
*/
function setSignatureMode($mode)
{
}
/**
* Create a signature
*
* See "2.6.2 Protocol 2 private key signature request"
*
* @param string $message
* @return string
* @access public
*/
function sign($message)
{
// the last parameter (currently 0) is for flags and ssh-agent only defines one flag (for ssh-dss): SSH_AGENT_OLD_SIGNATURE
$packet = pack('CNa*Na*N', Agent::SSH_AGENTC_SIGN_REQUEST, strlen($this->key_blob), $this->key_blob, strlen($message), $message, 0);
$packet = pack('Na*', strlen($packet), $packet);
if (strlen($packet) != fputs($this->fsock, $packet)) {
user_error('Connection closed during signing');
}
$length = current(unpack('N', fread($this->fsock, 4)));
$type = ord(fread($this->fsock, 1));
if ($type != Agent::SSH_AGENT_SIGN_RESPONSE) {
user_error('Unable to retrieve signature');
}
$signature_blob = fread($this->fsock, $length - 1);
// the only other signature format defined - ssh-dss - is the same length as ssh-rsa
// the + 12 is for the other various SSH added length fields
return substr($signature_blob, strlen('ssh-rsa') + 12);
}
}

View file

@ -1,39 +0,0 @@
<?php
/**
* Pure-PHP ssh-agent client wrapper
*
* PHP versions 4 and 5
*
* Originally System_SSH_Agent was accessed as System/SSH_Agent.php instead of
* System/SSH/Agent.php. The problem with this is that PSR0 compatible autoloaders
* don't support that kind of directory layout hence the package being moved and
* this "alias" being created to maintain backwards compatibility.
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category System
* @package System_SSH_Agent
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2014 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent
*/
require_once 'SSH/Agent.php';

View file

@ -0,0 +1,16 @@
<?php
/**
* Bootstrapping File for phpseclib
*
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*/
if (extension_loaded('mbstring')) {
// 2 - MB_OVERLOAD_STRING
if (ini_get('mbstring.func_overload') & 2) {
throw new \UnexpectedValueException(
'Overloading of string functions using mbstring.func_overload ' .
'is not supported by phpseclib.'
);
}
}

View file

@ -0,0 +1,4 @@
.DS_Store
.tmp
pkg
tmp

View file

@ -0,0 +1,18 @@
language: php
php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
# - nightly
env:
- PHPSECLIB="2.0.0"
- PHPSECLIB="2.0.1"
- PHPSECLIB="2.0.2"
- PHPSECLIB="2.0.3"
- PHPSECLIB="2.0.4"
before_script: 'sed -i "s/\"phpseclib\/phpseclib\": \"[^\"]*/\"phpseclib\/phpseclib\": \"$PHPSECLIB/" composer.json && composer install --prefer-source --dev'

View file

@ -0,0 +1,1890 @@
# Doxyfile 1.8.4
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
#
# All text after a double hash (##) is considered a comment and is placed
# in front of the TAG it is preceding .
# All text after a hash (#) is considered a comment and will be ignored.
# The format is:
# TAG = value [value, ...]
# For lists items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (" ").
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
# This tag specifies the encoding used for all characters in the config file
# that follow. The default is UTF-8 which is also the encoding used for all
# text before the first occurrence of this tag. Doxygen uses libiconv (or the
# iconv built into libc) for the transcoding. See
# http://www.gnu.org/software/libiconv for the list of possible encodings.
DOXYFILE_ENCODING = UTF-8
# The PROJECT_NAME tag is a single word (or sequence of words) that should
# identify the project. Note that if you do not use Doxywizard you need
# to put quotes around the project name if it contains spaces.
PROJECT_NAME = "OpenPGP PHP"
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER =
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer
# a quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF =
# With the PROJECT_LOGO tag one can specify an logo or icon that is
# included in the documentation. The maximum height of the logo should not
# exceed 55 pixels and the maximum width should not exceed 200 pixels.
# Doxygen will copy the logo to the output directory.
PROJECT_LOGO =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = doc
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output
# format and will distribute the generated files over these directories.
# Enabling this option can be useful when feeding doxygen a huge amount of
# source files, where putting all generated files in the same directory would
# otherwise cause performance problems for the file system.
CREATE_SUBDIRS = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# The default language is English, other supported languages are:
# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
# messages), Korean, Korean-en, Latvian, Lithuanian, Norwegian, Macedonian,
# Persian, Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic,
# Slovak, Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
OUTPUT_LANGUAGE = English
# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
# include brief member descriptions after the members that are listed in
# the file and class documentation (similar to JavaDoc).
# Set to NO to disable this.
BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
# the brief description of a member or function before the detailed description.
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
REPEAT_BRIEF = YES
# This tag implements a quasi-intelligent brief description abbreviator
# that is used to form the text in various listings. Each string
# in this list, if found as the leading text of the brief description, will be
# stripped from the text and the result after processing the whole list, is
# used as the annotated text. Otherwise, the brief description is used as-is.
# If left blank, the following values are used ("$name" is automatically
# replaced with the name of the entity): "The $name class" "The $name widget"
# "The $name file" "is" "provides" "specifies" "contains"
# "represents" "a" "an" "the"
ABBREVIATE_BRIEF =
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# Doxygen will generate a detailed section even if there is only a brief
# description.
ALWAYS_DETAILED_SEC = NO
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
INLINE_INHERITED_MEMB = NO
# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.
FULL_PATH_NAMES = YES
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
# can be used to strip a user-defined part of the path. Stripping is
# only done if one of the specified strings matches the left-hand part of
# the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the
# path to strip. Note that you specify absolute paths here, but also
# relative paths, which will be relative from the directory where doxygen is
# started.
STRIP_FROM_PATH =
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
# the path mentioned in the documentation of a class, which tells
# the reader which header file to include in order to use a class.
# If left blank only the name of the header file containing the class
# definition is used. Otherwise one should specify the include paths that
# are normally passed to the compiler using the -I flag.
STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
# (but less readable) file names. This can be useful if your file system
# doesn't support long names like on DOS, Mac, or CD-ROM.
SHORT_NAMES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
# will interpret the first line (until the first dot) of a JavaDoc-style
# comment as the brief description. If set to NO, the JavaDoc
# comments will behave just like regular Qt-style comments
# (thus requiring an explicit @brief command for a brief description.)
JAVADOC_AUTOBRIEF = YES
# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
# interpret the first line (until the first dot) of a Qt-style
# comment as the brief description. If set to NO, the comments
# will behave just like regular Qt-style comments (thus requiring
# an explicit \brief command for a brief description.)
QT_AUTOBRIEF = NO
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
# treat a multi-line C++ special comment block (i.e. a block of //! or ///
# comments) as a brief description. This used to be the default behaviour.
# The new default is to treat a multi-line C++ comment block as a detailed
# description. Set this tag to YES if you prefer the old behaviour instead.
MULTILINE_CPP_IS_BRIEF = NO
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
# member inherits the documentation from any documented member that it
# re-implements.
INHERIT_DOCS = YES
# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
# a new page for each member. If set to NO, the documentation of a member will
# be part of the file/class/namespace that contains it.
SEPARATE_MEMBER_PAGES = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.
TAB_SIZE = 4
# This tag can be used to specify a number of aliases that acts
# as commands in the documentation. An alias has the form "name=value".
# For example adding "sideeffect=\par Side Effects:\n" will allow you to
# put the command \sideeffect (or @sideeffect) in the documentation, which
# will result in a user-defined paragraph with heading "Side Effects:".
# You can put \n's in the value part of an alias to insert newlines.
ALIASES =
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding
# "class=itcl::class" will allow you to use the command class in the
# itcl::class meaning.
TCL_SUBST =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
# sources only. Doxygen will then generate output that is more tailored for C.
# For instance, some of the names that are used will be different. The list
# of all members will be omitted, etc.
OPTIMIZE_OUTPUT_FOR_C = NO
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
# sources only. Doxygen will then generate output that is more tailored for
# Java. For instance, namespaces will be presented as packages, qualified
# scopes will look different, etc.
OPTIMIZE_OUTPUT_JAVA = NO
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
# sources only. Doxygen will then generate output that is more tailored for
# Fortran.
OPTIMIZE_FOR_FORTRAN = NO
# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
# sources. Doxygen will then generate output that is tailored for
# VHDL.
OPTIMIZE_OUTPUT_VHDL = NO
# Doxygen selects the parser to use depending on the extension of the files it
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension,
# and language is one of the parsers supported by doxygen: IDL, Java,
# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
# C++. For instance to make doxygen treat .inc files as Fortran files (default
# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note
# that for custom extensions you also need to set FILE_PATTERNS otherwise the
# files are not read by doxygen.
EXTENSION_MAPPING =
# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
# comments according to the Markdown format, which allows for more readable
# documentation. See http://daringfireball.net/projects/markdown/ for details.
# The output of markdown processing is further processed by doxygen, so you
# can mix doxygen, HTML, and XML commands with Markdown formatting.
# Disable only in case of backward compatibilities issues.
MARKDOWN_SUPPORT = YES
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
# be prevented in individual cases by by putting a % sign in front of the word
# or globally by setting AUTOLINK_SUPPORT to NO.
AUTOLINK_SUPPORT = NO
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should
# set this tag to YES in order to let doxygen match functions declarations and
# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
# func(std::string) {}). This also makes the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
BUILTIN_STL_SUPPORT = NO
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
CPP_CLI_SUPPORT = NO
# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
# Doxygen will parse them like normal C++ but will assume all classes use public
# instead of private inheritance when no explicit protection keyword is present.
SIP_SUPPORT = NO
# For Microsoft's IDL there are propget and propput attributes to indicate
# getter and setter methods for a property. Setting this option to YES (the
# default) will make doxygen replace the get and set methods by a property in
# the documentation. This will only work if the methods are indeed getting or
# setting a simple type. If this is not the case, or you want to show the
# methods anyway, you should set this option to NO.
IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES, then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
DISTRIBUTE_GROUP_DOC = NO
# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
# the same type (for instance a group of public functions) to be put as a
# subgroup of that type (e.g. under the Public Functions section). Set it to
# NO to prevent subgrouping. Alternatively, this can be done per class using
# the \nosubgrouping command.
SUBGROUPING = YES
# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
# unions are shown inside the group in which they are included (e.g. using
# @ingroup) instead of on a separate page (for HTML and Man pages) or
# section (for LaTeX and RTF).
INLINE_GROUPED_CLASSES = NO
# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
# unions with only public data fields or simple typedef fields will be shown
# inline in the documentation of the scope in which they are defined (i.e. file,
# namespace, or group documentation), provided this scope is documented. If set
# to NO (the default), structs, classes, and unions are shown on a separate
# page (for HTML and Man pages) or section (for LaTeX and RTF).
INLINE_SIMPLE_STRUCTS = NO
# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
# is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
# with name TypeT. When disabled the typedef will appear as a member of a file,
# namespace, or class. And the struct will be named TypeS. This can typically
# be useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
TYPEDEF_HIDES_STRUCT = NO
# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
# cache is used to resolve symbols given their name and scope. Since this can
# be an expensive process and often the same symbol appear multiple times in
# the code, doxygen keeps a cache of pre-resolved symbols. If the cache is too
# small doxygen will become slower. If the cache is too large, memory is wasted.
# The cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid
# range is 0..9, the default is 0, corresponding to a cache size of 2^16 = 65536
# symbols.
LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# documentation are documented, even if no documentation was available.
# Private class members and static file members will be hidden unless
# the EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES
EXTRACT_ALL = YES
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
EXTRACT_PRIVATE = NO
# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
# scope will be included in the documentation.
EXTRACT_PACKAGE = NO
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
EXTRACT_STATIC = NO
# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
# defined locally in source files will be included in the documentation.
# If set to NO only classes defined in header files are included.
EXTRACT_LOCAL_CLASSES = YES
# This flag is only useful for Objective-C code. When set to YES local
# methods, which are defined in the implementation section but not in
# the interface are included in the documentation.
# If set to NO (the default) only methods in the interface are included.
EXTRACT_LOCAL_METHODS = NO
# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
# 'anonymous_namespace{file}', where file will be replaced with the base
# name of the file that contains the anonymous namespace. By default
# anonymous namespaces are hidden.
EXTRACT_ANON_NSPACES = NO
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
# undocumented members of documented classes, files or namespaces.
# If set to NO (the default) these members will be included in the
# various overviews, but no documentation section is generated.
# This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy.
# If set to NO (the default) these classes will be included in the various
# overviews. This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
# friend (class|struct|union) declarations.
# If set to NO (the default) these declarations will be included in the
# documentation.
HIDE_FRIEND_COMPOUNDS = NO
# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
# documentation blocks found inside the body of a function.
# If set to NO (the default) these blocks will be appended to the
# function's detailed documentation block.
HIDE_IN_BODY_DOCS = NO
# The INTERNAL_DOCS tag determines if documentation
# that is typed after a \internal command is included. If the tag is set
# to NO (the default) then the documentation will be excluded.
# Set it to YES to include the internal documentation.
INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
# file names in lower-case letters. If set to YES upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.
HIDE_SCOPE_NAMES = NO
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
# will put a list of the files that are included by a file in the documentation
# of that file.
SHOW_INCLUDE_FILES = YES
# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
# will list include files with double quotes in the documentation
# rather than with sharp brackets.
FORCE_LOCAL_INCLUDES = NO
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.
INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
# will sort the (detailed) documentation of file and class members
# alphabetically by member name. If set to NO the members will appear in
# declaration order.
SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
# brief documentation of file, namespace and class members alphabetically
# by member name. If set to NO (the default) the members will appear in
# declaration order.
SORT_BRIEF_DOCS = NO
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
# will sort the (brief and detailed) documentation of class members so that
# constructors and destructors are listed first. If set to NO (the default)
# the constructors will appear in the respective orders defined by
# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
SORT_MEMBERS_CTORS_1ST = NO
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
# hierarchy of group names into alphabetical order. If set to NO (the default)
# the group names will appear in their defined order.
SORT_GROUP_NAMES = NO
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
# sorted by fully-qualified names, including namespaces. If set to
# NO (the default), the class list will be sorted only by class name,
# not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option applies only to the class list, not to the
# alphabetical list.
SORT_BY_SCOPE_NAME = NO
# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
# do proper type resolution of all parameters of a function it will reject a
# match between the prototype and the implementation of a member function even
# if there is only one candidate or it is obvious which candidate to choose
# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
# will still accept a match between prototype and implementation in such cases.
STRICT_PROTO_MATCHING = NO
# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
# commands in the documentation.
GENERATE_TODOLIST = YES
# The GENERATE_TESTLIST tag can be used to enable (YES) or
# disable (NO) the test list. This list is created by putting \test
# commands in the documentation.
GENERATE_TESTLIST = YES
# The GENERATE_BUGLIST tag can be used to enable (YES) or
# disable (NO) the bug list. This list is created by putting \bug
# commands in the documentation.
GENERATE_BUGLIST = YES
# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
# disable (NO) the deprecated list. This list is created by putting
# \deprecated commands in the documentation.
GENERATE_DEPRECATEDLIST= YES
# The ENABLED_SECTIONS tag can be used to enable conditional
# documentation sections, marked by \if section-label ... \endif
# and \cond section-label ... \endcond blocks.
ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
# the initial value of a variable or macro consists of for it to appear in
# the documentation. If the initializer consists of more lines than specified
# here it will be hidden. Use a value of 0 to hide initializers completely.
# The appearance of the initializer of individual variables and macros in the
# documentation can be controlled using \showinitializer or \hideinitializer
# command in the documentation regardless of this setting.
MAX_INITIALIZER_LINES = 30
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
SHOW_USED_FILES = NO
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
# This will remove the Files entry from the Quick Index and from the
# Folder Tree View (if specified). The default is YES.
SHOW_FILES = NO
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
# Namespaces page.
# This will remove the Namespaces entry from the Quick Index
# and from the Folder Tree View (if specified). The default is YES.
SHOW_NAMESPACES = NO
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
# the version control system). Doxygen will invoke the program by executing (via
# popen()) the command <command> <input-file>, where <command> is the value of
# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
# provided by doxygen. Whatever the program writes to standard output
# is used as the file version. See the manual for examples.
FILE_VERSION_FILTER = "git log --pretty=\"format:%ci, author:%aN <%aE>, commit:%h\" -1"
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
# output files in an output format independent way. To create the layout file
# that represents doxygen's defaults, run doxygen with the -l option.
# You can optionally specify a file name after the option, if omitted
# DoxygenLayout.xml will be used as the name of the layout file.
LAYOUT_FILE =
# The CITE_BIB_FILES tag can be used to specify one or more bib files
# containing the references data. This must be a list of .bib files. The
# .bib extension is automatically appended if omitted. Using this command
# requires the bibtex tool to be installed. See also
# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
# feature you need bibtex and perl available in the search path. Do not use
# file names with spaces, bibtex cannot handle them.
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
# The QUIET tag can be used to turn on/off the messages that are generated
# by doxygen. Possible values are YES and NO. If left blank NO is used.
QUIET = NO
# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated by doxygen. Possible values are YES and NO. If left blank
# NO is used.
WARNINGS = YES
# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
# automatically be disabled.
WARN_IF_UNDOCUMENTED = YES
# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
# potential errors in the documentation, such as not documenting some
# parameters in a documented function, or documenting parameters that
# don't exist or using markup commands wrongly.
WARN_IF_DOC_ERROR = YES
# The WARN_NO_PARAMDOC option can be enabled to get warnings for
# functions that are documented, but have no documentation for their parameters
# or return value. If set to NO (the default) doxygen will only warn about
# wrong or incomplete parameter documentation, but not about the absence of
# documentation.
WARN_NO_PARAMDOC = NO
# The WARN_FORMAT tag determines the format of the warning messages that
# doxygen can produce. The string should contain the $file, $line, and $text
# tags, which will be replaced by the file and line number from which the
# warning originated and the warning text. Optionally the format may contain
# $version, which will be replaced by the version of the file (if it could
# be obtained via FILE_VERSION_FILTER)
WARN_FORMAT = "$file:$line: $text"
# The WARN_LOGFILE tag can be used to specify a file to which warning
# and error messages should be written. If left blank the output is written
# to stderr.
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag can be used to specify the files and/or directories that contain
# documented source files. You may enter file names like "myfile.cpp" or
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = lib/ README.md
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
# also the default input encoding. Doxygen uses libiconv (or the iconv built
# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
# the list of possible encodings.
INPUT_ENCODING = UTF-8
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank the following patterns are tested:
# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
# *.f90 *.f *.for *.vhd *.vhdl
FILE_PATTERNS =
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.
# If left blank NO is used.
RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
# Note that relative paths are relative to the directory from which doxygen is
# run.
EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories. Note that the wildcards are matched
# against the file with absolute path, so to exclude all test directories
# for example use the pattern */test/*
EXCLUDE_PATTERNS =
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
EXCLUDE_SYMBOLS =
# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
# the \include command).
EXAMPLE_PATH = examples/
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank all files are included.
EXAMPLE_PATTERNS =
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude
# commands irrespective of the value of the RECURSIVE tag.
# Possible values are YES and NO. If left blank NO is used.
EXAMPLE_RECURSIVE = NO
# The IMAGE_PATH tag can be used to specify one or more files or
# directories that contain image that are included in the documentation (see
# the \image command).
IMAGE_PATH =
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command <filter> <input-file>, where <filter>
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
# input file. Doxygen will then use the output that the filter program writes
# to standard output.
# If FILTER_PATTERNS is specified, this tag will be ignored.
# Note that the filter must not add or remove lines; it is applied before the
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis.
# Doxygen will compare the file name with each pattern and apply the
# filter if there is a match.
# The filters are a list of the form:
# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
# info on how filters are used. If FILTER_PATTERNS is empty or if
# non of the patterns match the file name, INPUT_FILTER is applied.
FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will be used to filter the input files when producing source
# files to browse (i.e. when SOURCE_BROWSER is set to YES).
FILTER_SOURCE_FILES = NO
# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
# and it is also possible to disable source filtering for a specific pattern
# using *.ext= (so without naming a filter). This option only has effect when
# FILTER_SOURCE_FILES is enabled.
FILTER_SOURCE_PATTERNS =
# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
# is part of the input, its contents will be placed on the main page
# (index.html). This can be useful if you have a project on for instance GitHub
# and want reuse the introduction page also for the doxygen output.
USE_MDFILE_AS_MAINPAGE = README.md
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
# If the SOURCE_BROWSER tag is set to YES then a list of source files will
# be generated. Documented entities will be cross-referenced with these sources.
# Note: To get rid of all source code in the generated output, make sure also
# VERBATIM_HEADERS is set to NO.
SOURCE_BROWSER = YES
# Setting the INLINE_SOURCES tag to YES will include the body
# of functions and classes directly in the documentation.
INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
# doxygen to hide any special comment blocks from generated source code
# fragments. Normal C, C++ and Fortran comments will always remain visible.
STRIP_CODE_COMMENTS = YES
# If the REFERENCED_BY_RELATION tag is set to YES
# then for each documented function all documented
# functions referencing it will be listed.
REFERENCED_BY_RELATION = NO
# If the REFERENCES_RELATION tag is set to YES
# then for each documented function all documented entities
# called/used by that function will be listed.
REFERENCES_RELATION = NO
# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
# link to the source code.
# Otherwise they will link to the documentation.
REFERENCES_LINK_SOURCE = YES
# If the USE_HTAGS tag is set to YES then the references to source code
# will point to the HTML generated by the htags(1) tool instead of doxygen
# built-in source browser. The htags tool is part of GNU's global source
# tagging system (see http://www.gnu.org/software/global/global.html). You
# will need version 4.8.6 or higher.
USE_HTAGS = NO
# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
# will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this.
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
# of all compounds will be generated. Enable this if the project
# contains a lot of classes, structs, unions or interfaces.
ALPHABETICAL_INDEX = YES
# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
# in which this list will be split (can be a number in the range [1..20])
COLS_IN_ALPHA_INDEX = 5
# In case all classes in a project start with a common prefix, all
# classes will be put under the same header in the alphabetical index.
# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
# should be ignored while generating the index headers.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
# generate HTML output.
GENERATE_HTML = YES
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `html' will be used as the default path.
HTML_OUTPUT = html
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
# doxygen will generate files with .html extension.
HTML_FILE_EXTENSION = .html
# The HTML_HEADER tag can be used to specify a personal HTML header for
# each generated HTML page. If it is left blank doxygen will generate a
# standard header. Note that when using a custom header you are responsible
# for the proper inclusion of any scripts and style sheets that doxygen
# needs, which is dependent on the configuration options used.
# It is advised to generate a default header using "doxygen -w html
# header.html footer.html stylesheet.css YourConfigFile" and then modify
# that header. Note that the header is subject to change so you typically
# have to redo this when upgrading to a newer version of doxygen or when
# changing the value of configuration settings such as GENERATE_TREEVIEW!
HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
# each generated HTML page. If it is left blank doxygen will generate a
# standard footer.
HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
# style sheet that is used by each HTML page. It can be used to
# fine-tune the look of the HTML output. If left blank doxygen will
# generate a default style sheet. Note that it is recommended to use
# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
# tag will in the future become obsolete.
HTML_STYLESHEET =
# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
# user-defined cascading style sheet that is included after the standard
# style sheets created by doxygen. Using this option one can overrule
# certain style aspects. This is preferred over using HTML_STYLESHEET
# since it does not replace the standard style sheet and is therefor more
# robust against future updates. Doxygen will copy the style sheet file to
# the output directory.
HTML_EXTRA_STYLESHEET =
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
# that these files will be copied to the base HTML output directory. Use the
# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
# files. In the HTML_STYLESHEET file, use the file name only. Also note that
# the files will be copied as-is; there are no commands or markers available.
HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
# Doxygen will adjust the colors in the style sheet and background images
# according to this color. Hue is specified as an angle on a colorwheel,
# see http://en.wikipedia.org/wiki/Hue for more information.
# For instance the value 0 represents red, 60 is yellow, 120 is green,
# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
# The allowed range is 0 to 359.
HTML_COLORSTYLE_HUE = 220
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
# the colors in the HTML output. For a value of 0 the output will use
# grayscales only. A value of 255 will produce the most vivid colors.
HTML_COLORSTYLE_SAT = 100
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
# the luminance component of the colors in the HTML output. Values below
# 100 gradually make the output lighter, whereas values above 100 make
# the output darker. The value divided by 100 is the actual gamma applied,
# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
# and 100 does not change the gamma.
HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting
# this to NO can help when comparing the output of multiple runs.
HTML_TIMESTAMP = YES
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded.
HTML_DYNAMIC_SECTIONS = NO
# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
# entries shown in the various tree structured indices initially; the user
# can expand and collapse entries dynamically later on. Doxygen will expand
# the tree to such a level that at most the specified number of entries are
# visible (unless a fully collapsed tree already exceeds this amount).
# So setting the number of entries 1 will produce a full collapsed tree by
# default. 0 is a special value representing an infinite number of entries
# and will result in a full expanded tree by default.
HTML_INDEX_NUM_ENTRIES = 100
# If the GENERATE_DOCSET tag is set to YES, additional index files
# will be generated that can be used as input for Apple's Xcode 3
# integrated development environment, introduced with OSX 10.5 (Leopard).
# To create a documentation set, doxygen will generate a Makefile in the
# HTML output directory. Running make will produce the docset in that
# directory and running "make install" will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
# it at startup.
# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
# for more information.
GENERATE_DOCSET = NO
# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
# feed. A documentation feed provides an umbrella under which multiple
# documentation sets from a single provider (such as a company or product suite)
# can be grouped.
DOCSET_FEEDNAME = "Doxygen generated docs"
# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
# should uniquely identify the documentation set bundle. This should be a
# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
# will append .docset to the name.
DOCSET_BUNDLE_ID = org.doxygen.Project
# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely
# identify the documentation publisher. This should be a reverse domain-name
# style string, e.g. com.mycompany.MyDocSet.documentation.
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
DOCSET_PUBLISHER_NAME = Publisher
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
# of the generated HTML documentation.
GENERATE_HTMLHELP = NO
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
# be used to specify the file name of the resulting .chm file. You
# can add a path in front of the file if the result should not be
# written to the html output directory.
CHM_FILE =
# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
# be used to specify the location (absolute path including file name) of
# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
# the HTML help compiler on the generated index.hhp.
HHC_LOCATION =
# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
# controls if a separate .chi index file is generated (YES) or that
# it should be included in the master .chm file (NO).
GENERATE_CHI = NO
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
# is used to encode HtmlHelp index (hhk), content (hhc) and project file
# content.
CHM_INDEX_ENCODING =
# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
# controls whether a binary table of contents is generated (YES) or a
# normal table of contents (NO) in the .chm file.
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members
# to the contents of the HTML help documentation and to the tree view.
TOC_EXPAND = NO
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
# that can be used as input for Qt's qhelpgenerator to generate a
# Qt Compressed Help (.qch) of the generated HTML documentation.
GENERATE_QHP = NO
# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
# be used to specify the file name of the resulting .qch file.
# The path specified is relative to the HTML output folder.
QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating
# Qt Help Project output. For more information please see
# http://doc.trolltech.com/qthelpproject.html#namespace
QHP_NAMESPACE = org.doxygen.Project
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
# Qt Help Project output. For more information please see
# http://doc.trolltech.com/qthelpproject.html#virtual-folders
QHP_VIRTUAL_FOLDER = doc
# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
# add. For more information please see
# http://doc.trolltech.com/qthelpproject.html#custom-filters
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see
# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
# Qt Help Project / Custom Filters</a>.
QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's
# filter section matches.
# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
# Qt Help Project / Filter Attributes</a>.
QHP_SECT_FILTER_ATTRS =
# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
# be used to specify the location of Qt's qhelpgenerator.
# If non-empty doxygen will try to run qhelpgenerator on the generated
# .qhp file.
QHG_LOCATION =
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
# will be generated, which together with the HTML files, form an Eclipse help
# plugin. To install this plugin and make it available under the help contents
# menu in Eclipse, the contents of the directory containing the HTML and XML
# files needs to be copied into the plugins directory of eclipse. The name of
# the directory within the plugins directory should be the same as
# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
# the help appears.
GENERATE_ECLIPSEHELP = NO
# A unique identifier for the eclipse help plugin. When installing the plugin
# the directory name containing the HTML and XML files should also have
# this name.
ECLIPSE_DOC_ID = org.doxygen.Project
# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
# at top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it. Since the tabs have the same information as the
# navigation tree you can set this option to NO if you already set
# GENERATE_TREEVIEW to YES.
DISABLE_INDEX = NO
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information.
# If the tag value is set to YES, a side panel will be generated
# containing a tree-like index structure (just like the one that
# is generated for HTML Help). For this to work a browser that supports
# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
# Windows users are probably better off using the HTML help feature.
# Since the tree basically has the same information as the tab index you
# could consider to set DISABLE_INDEX to NO when enabling this option.
GENERATE_TREEVIEW = NO
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
# (range [0,1..20]) that doxygen will group on one line in the generated HTML
# documentation. Note that a value of 0 will completely suppress the enum
# values from appearing in the overview section.
ENUM_VALUES_PER_LINE = 4
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree
# is shown.
TREEVIEW_WIDTH = 250
# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
# links to external symbols imported via tag files in a separate window.
EXT_LINKS_IN_WINDOW = NO
# Use this tag to change the font size of Latex formulas included
# as images in the HTML documentation. The default is 10. Note that
# when you change the font size after a successful doxygen run you need
# to manually remove any form_*.png images from the HTML output directory
# to force them to be regenerated.
FORMULA_FONTSIZE = 10
# Use the FORMULA_TRANPARENT tag to determine whether or not the images
# generated for formulas are transparent PNGs. Transparent PNGs are
# not supported properly for IE 6.0, but are supported on all modern browsers.
# Note that when changing this option you need to delete any form_*.png files
# in the HTML output before the changes have effect.
FORMULA_TRANSPARENT = YES
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
# (see http://www.mathjax.org) which uses client side Javascript for the
# rendering instead of using prerendered bitmaps. Use this if you do not
# have LaTeX installed or if you want to formulas look prettier in the HTML
# output. When enabled you may also need to install MathJax separately and
# configure the path to it using the MATHJAX_RELPATH option.
USE_MATHJAX = NO
# When MathJax is enabled you can set the default output format to be used for
# the MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and
# SVG. The default value is HTML-CSS, which is slower, but has the best
# compatibility.
MATHJAX_FORMAT = HTML-CSS
# When MathJax is enabled you need to specify the location relative to the
# HTML output directory using the MATHJAX_RELPATH option. The destination
# directory should contain the MathJax.js script. For instance, if the mathjax
# directory is located at the same level as the HTML output directory, then
# MATHJAX_RELPATH should be ../mathjax. The default value points to
# the MathJax Content Delivery Network so you can quickly see the result without
# installing MathJax.
# However, it is strongly recommended to install a local
# copy of MathJax from http://www.mathjax.org before deployment.
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
# names that should be enabled during MathJax rendering.
MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript
# pieces of code that will be used on startup of the MathJax code.
MATHJAX_CODEFILE =
# When the SEARCHENGINE tag is enabled doxygen will generate a search box
# for the HTML output. The underlying search engine uses javascript
# and DHTML and should work on any modern browser. Note that when using
# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
# (GENERATE_DOCSET) there is already a search function so this one should
# typically be disabled. For large projects the javascript based search engine
# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a web server instead of a web client using Javascript.
# There are two flavours of web server based search depending on the
# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
# searching and an index file used by the script. When EXTERNAL_SEARCH is
# enabled the indexing and searching needs to be provided by external tools.
# See the manual for details.
SERVER_BASED_SEARCH = NO
# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP
# script for searching. Instead the search results are written to an XML file
# which needs to be processed by an external indexer. Doxygen will invoke an
# external search engine pointed to by the SEARCHENGINE_URL option to obtain
# the search results. Doxygen ships with an example indexer (doxyindexer) and
# search engine (doxysearch.cgi) which are based on the open source search
# engine library Xapian. See the manual for configuration details.
EXTERNAL_SEARCH = NO
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
# which will returned the search results when EXTERNAL_SEARCH is enabled.
# Doxygen ships with an example search engine (doxysearch) which is based on
# the open source search engine library Xapian. See the manual for configuration
# details.
SEARCHENGINE_URL =
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
# search data is written to a file for indexing by an external tool. With the
# SEARCHDATA_FILE tag the name of this file can be specified.
SEARCHDATA_FILE = searchdata.xml
# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the
# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
# projects and redirect the results back to the right project.
EXTERNAL_SEARCH_ID =
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
# projects other than the one defined by this configuration file, but that are
# all added to the same external search index. Each project needs to have a
# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id
# of to a relative location where the documentation can be found.
# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ...
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = NO
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `latex' will be used as the default path.
LATEX_OUTPUT = latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked. If left blank `latex' will be used as the default command name.
# Note that when enabling USE_PDFLATEX this option is only used for
# generating bitmaps for formulas in the HTML output, but not in the
# Makefile that is written to the output directory.
LATEX_CMD_NAME = latex
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
# generate index for LaTeX. If left blank `makeindex' will be used as the
# default command name.
MAKEINDEX_CMD_NAME = makeindex
# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used
# by the printer. Possible values are: a4, letter, legal and
# executive. If left blank a4 will be used.
PAPER_TYPE = a4
# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
# packages that should be included in the LaTeX output.
EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
# the generated latex document. The header should contain everything until
# the first chapter. If it is left blank doxygen will generate a
# standard header. Notice: only use this tag if you know what you are doing!
LATEX_HEADER =
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
# the generated latex document. The footer should contain everything after
# the last chapter. If it is left blank doxygen will generate a
# standard footer. Notice: only use this tag if you know what you are doing!
LATEX_FOOTER =
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images
# or other source files which should be copied to the LaTeX output directory.
# Note that the files will be copied as-is; there are no commands or markers
# available.
LATEX_EXTRA_FILES =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
# contain links (just like the HTML output) instead of page references
# This makes the output suitable for online browsing using a pdf viewer.
PDF_HYPERLINKS = YES
# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
# plain latex in the generated Makefile. Set this option to YES to get a
# higher quality PDF documentation.
USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
# command to the generated LaTeX files. This will instruct LaTeX to keep
# running if errors occur, instead of asking the user for help.
# This option is also used when generating formulas in HTML.
LATEX_BATCHMODE = NO
# If LATEX_HIDE_INDICES is set to YES then doxygen will not
# include the index chapters (such as File Index, Compound Index, etc.)
# in the output.
LATEX_HIDE_INDICES = NO
# If LATEX_SOURCE_CODE is set to YES then doxygen will include
# source code with syntax highlighting in the LaTeX output.
# Note that which sources are shown also depends on other settings
# such as SOURCE_BROWSER.
LATEX_SOURCE_CODE = NO
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
# http://en.wikipedia.org/wiki/BibTeX for more info.
LATEX_BIB_STYLE = plain
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
# The RTF output is optimized for Word 97 and may not look very pretty with
# other RTF readers or editors.
GENERATE_RTF = NO
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `rtf' will be used as the default path.
RTF_OUTPUT = rtf
# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
# RTF documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_RTF = NO
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
# will contain hyperlink fields. The RTF file will
# contain links (just like the HTML output) instead of page references.
# This makes the output suitable for online browsing using WORD or other
# programs which support those fields.
# Note: wordpad (write) and others do not support links.
RTF_HYPERLINKS = NO
# Load style sheet definitions from file. Syntax is similar to doxygen's
# config file, i.e. a series of assignments. You only have to provide
# replacements, missing definitions are set to their default value.
RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an rtf document.
# Syntax is similar to doxygen's config file.
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
# generate man pages
GENERATE_MAN = NO
# The MAN_OUTPUT tag is used to specify where the man pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `man' will be used as the default path.
MAN_OUTPUT = man
# The MAN_EXTENSION tag determines the extension that is added to
# the generated man pages (default is the subroutine's section .3)
MAN_EXTENSION = .3
# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
# then it will generate one additional man file for each entity
# documented in the real man page(s). These additional files
# only source the real man page, but without them the man command
# would be unable to find the correct page. The default is NO.
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
# If the GENERATE_XML tag is set to YES Doxygen will
# generate an XML file that captures the structure of
# the code including all documentation.
GENERATE_XML = NO
# The XML_OUTPUT tag is used to specify where the XML pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `xml' will be used as the default path.
XML_OUTPUT = xml
# The XML_SCHEMA tag can be used to specify an XML schema,
# which can be used by a validating XML parser to check the
# syntax of the XML files.
XML_SCHEMA =
# The XML_DTD tag can be used to specify an XML DTD,
# which can be used by a validating XML parser to check the
# syntax of the XML files.
XML_DTD =
# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
# dump the program listings (including syntax highlighting
# and cross-referencing information) to the XML output. Note that
# enabling this will significantly increase the size of the XML output.
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
# If the GENERATE_DOCBOOK tag is set to YES Doxygen will generate DOCBOOK files
# that can be used to generate PDF.
GENERATE_DOCBOOK = NO
# The DOCBOOK_OUTPUT tag is used to specify where the DOCBOOK pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
# front of it. If left blank docbook will be used as the default path.
DOCBOOK_OUTPUT = docbook
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
# generate an AutoGen Definitions (see autogen.sf.net) file
# that captures the structure of the code including all
# documentation. Note that this feature is still experimental
# and incomplete at the moment.
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
# If the GENERATE_PERLMOD tag is set to YES Doxygen will
# generate a Perl module file that captures the structure of
# the code including all documentation. Note that this
# feature is still experimental and incomplete at the
# moment.
GENERATE_PERLMOD = NO
# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
# the necessary Makefile rules, Perl scripts and LaTeX code to be able
# to generate PDF and DVI output from the Perl module output.
PERLMOD_LATEX = NO
# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
# nicely formatted so it can be parsed by a human reader.
# This is useful
# if you want to understand what is going on.
# On the other hand, if this
# tag is set to NO the size of the Perl module output will be much smaller
# and Perl will parse it just the same.
PERLMOD_PRETTY = YES
# The names of the make variables in the generated doxyrules.make file
# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
# This is useful so different doxyrules.make files included by the same
# Makefile don't overwrite each other's variables.
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
# evaluate all C-preprocessor directives found in the sources and include
# files.
ENABLE_PREPROCESSING = YES
# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
# names in the source code. If set to NO (the default) only conditional
# compilation will be performed. Macro expansion can be done in a controlled
# way by setting EXPAND_ONLY_PREDEF to YES.
MACRO_EXPANSION = NO
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
# then the macro expansion is limited to the macros specified with the
# PREDEFINED and EXPAND_AS_DEFINED tags.
EXPAND_ONLY_PREDEF = NO
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
# pointed to by INCLUDE_PATH will be searched when a #include is found.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by
# the preprocessor.
INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will
# be used.
INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that
# are defined before the preprocessor is started (similar to the -D option of
# gcc). The argument of the tag is a list of macros of the form: name
# or name=definition (no spaces). If the definition and the = are
# omitted =1 is assumed. To prevent a macro definition from being
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
PREDEFINED =
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
# The macro definition that is found in the sources will be used.
# Use the PREDEFINED tag if you want to use a different macro definition that
# overrules the definition found in the source code.
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
# doxygen's preprocessor will remove all references to function-like macros
# that are alone on a line, have an all uppercase name, and do not end with a
# semicolon, because these will confuse the parser if not removed.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
# The TAGFILES option can be used to specify one or more tagfiles. For each
# tag file the location of the external documentation should be added. The
# format of a tag file without this location is as follows:
#
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
#
# TAGFILES = file1=loc1 "file2 = loc2" ...
# where "loc1" and "loc2" can be relative or absolute paths
# or URLs. Note that each tag file must have a unique name (where the name does
# NOT include the path). If a tag file is not located in the directory in which
# doxygen is run, you must also specify the path to the tagfile here.
TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create
# a tag file that is based on the input files it reads.
GENERATE_TAGFILE =
# If the ALLEXTERNALS tag is set to YES all external classes will be listed
# in the class index. If set to NO only the inherited external classes
# will be listed.
ALLEXTERNALS = NO
# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
# in the modules index. If set to NO, only the current project's groups will
# be listed.
EXTERNAL_GROUPS = YES
# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed
# in the related pages index. If set to NO, only the current project's
# pages will be listed.
EXTERNAL_PAGES = YES
# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of `which perl').
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
# or super classes. Setting the tag to NO turns the diagrams off. Note that
# this option also works with HAVE_DOT disabled, but it is recommended to
# install and use dot, since it yields more powerful graphs.
CLASS_DIAGRAMS = YES
# You can define message sequence charts within doxygen comments using the \msc
# command. Doxygen will then run the mscgen tool (see
# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
# the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path.
MSCGEN_PATH =
# If set to YES, the inheritance and collaboration graphs will hide
# inheritance and usage relations if the target is undocumented
# or is not a class.
HIDE_UNDOC_RELATIONS = YES
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz, a graph visualization
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)
HAVE_DOT = NO
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
# allowed to run in parallel. When set to 0 (the default) doxygen will
# base this on the number of processors available in the system. You can set it
# explicitly to a value larger than 0 to get control over the balance
# between CPU load and processing speed.
DOT_NUM_THREADS = 0
# By default doxygen will use the Helvetica font for all dot files that
# doxygen generates. When you want a differently looking font you can specify
# the font name using DOT_FONTNAME. You need to make sure dot is able to find
# the font, which can be done by putting it in a standard location or by setting
# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
# directory containing the font.
DOT_FONTNAME = Helvetica
# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
# The default size is 10pt.
DOT_FONTSIZE = 10
# By default doxygen will tell dot to use the Helvetica font.
# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
# set the path where dot can find it.
DOT_FONTPATH =
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect inheritance relations. Setting this tag to YES will force the
# CLASS_DIAGRAMS tag to NO.
CLASS_GRAPH = YES
# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect implementation dependencies (inheritance, containment, and
# class references variables) of the class with other documented classes.
COLLABORATION_GRAPH = YES
# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for groups, showing the direct groups dependencies
GROUP_GRAPHS = YES
# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
UML_LOOK = NO
# If the UML_LOOK tag is enabled, the fields and methods are shown inside
# the class node. If there are many fields or methods and many nodes the
# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
# threshold limits the number of items for each type to make the size more
# manageable. Set this to 0 for no limit. Note that the threshold may be
# exceeded by 50% before the limit is enforced.
UML_LIMIT_NUM_FIELDS = 10
# If set to YES, the inheritance and collaboration graphs will show the
# relations between templates and their instances.
TEMPLATE_RELATIONS = NO
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
# tags are set to YES then doxygen will generate a graph for each documented
# file showing the direct and indirect include dependencies of the file with
# other documented files.
INCLUDE_GRAPH = YES
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
# documented header file showing the documented files that directly or
# indirectly include this file.
INCLUDED_BY_GRAPH = YES
# If the CALL_GRAPH and HAVE_DOT options are set to YES then
# doxygen will generate a call dependency graph for every global function
# or class method. Note that enabling this option will significantly increase
# the time of a run. So in most cases it will be better to enable call graphs
# for selected functions only using the \callgraph command.
CALL_GRAPH = NO
# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
# doxygen will generate a caller dependency graph for every global function
# or class method. Note that enabling this option will significantly increase
# the time of a run. So in most cases it will be better to enable caller
# graphs for selected functions only using the \callergraph command.
CALLER_GRAPH = NO
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will generate a graphical hierarchy of all classes instead of a textual one.
GRAPHICAL_HIERARCHY = YES
# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
# then doxygen will show the dependencies a directory has on other directories
# in a graphical way. The dependency relations are determined by the #include
# relations between the files in the directories.
DIRECTORY_GRAPH = YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. Possible values are svg, png, jpg, or gif.
# If left blank png will be used. If you choose svg you need to set
# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
# visible in IE 9+ (other browsers do not have this requirement).
DOT_IMAGE_FORMAT = png
# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
# enable generation of interactive SVG images that allow zooming and panning.
# Note that this requires a modern browser other than Internet Explorer.
# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
# visible. Older versions of IE do not have SVG support.
INTERACTIVE_SVG = NO
# The tag DOT_PATH can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
DOT_PATH =
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the
# \dotfile command).
DOTFILE_DIRS =
# The MSCFILE_DIRS tag can be used to specify one or more directories that
# contain msc files that are included in the documentation (see the
# \mscfile command).
MSCFILE_DIRS =
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
# nodes that will be shown in the graph. If the number of nodes in a graph
# becomes larger than this value, doxygen will truncate the graph, which is
# visualized by representing a node as a red box. Note that doxygen if the
# number of direct children of the root node in a graph is already larger than
# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
DOT_GRAPH_MAX_NODES = 50
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
# graphs generated by dot. A depth value of 3 means that only nodes reachable
# from the root by following a path via at most 3 edges will be shown. Nodes
# that lay further from the root node will be omitted. Note that setting this
# option to 1 or 2 may greatly reduce the computation time needed for large
# code bases. Also note that the size of a graph can be further restricted by
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
MAX_DOT_GRAPH_DEPTH = 0
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is disabled by default, because dot on Windows does not
# seem to support this out of the box. Warning: Depending on the platform used,
# enabling this option may lead to badly anti-aliased labels on the edges of
# a graph (i.e. they become hard to read).
DOT_TRANSPARENT = NO
# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10)
# support this, this feature is disabled by default.
DOT_MULTI_TARGETS = YES
# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
# generate a legend page explaining the meaning of the various boxes and
# arrows in the dot generated graphs.
GENERATE_LEGEND = YES
# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
# remove the intermediate dot files that are used to generate
# the various graphs.
DOT_CLEANUP = YES

View file

@ -0,0 +1 @@
README.md

View file

@ -30,7 +30,8 @@ Users
OpenPGP.php is currently being used in the following projects:
* <http://drupal.org/project/openpgp>
* <https://drupal.org/project/openpgp>
* <https://wordpress.org/plugins/wp-pgp-encrypted-emails/>
Download
--------

View file

@ -1 +1 @@
0.0.1
0.3.0

View file

@ -0,0 +1,24 @@
{
"name": "singpolyma/openpgp-php",
"description": "Pure-PHP implementation of the OpenPGP Message Format (RFC 4880)",
"license": "Unlicense",
"authors": [
{
"name": "Arto Bendiken",
"email": "arto.bendiken@gmail.com"
},
{
"name": "Stephen Paul Weber",
"email": "singpolyma@singpolyma.net"
}
],
"require": {
"phpseclib/phpseclib": ">=2.0.0 <=2.0.4"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"autoload": {
"classmap": ["lib/"]
}
}

View file

@ -0,0 +1,31 @@
<?php
require_once dirname(__FILE__).'/../lib/openpgp.php';
require_once dirname(__FILE__).'/../lib/openpgp_crypt_rsa.php';
/* Parse secret key from STDIN, the key must not be password protected */
$wkey = OpenPGP_Message::parse(file_get_contents('php://stdin'));
$wkey = $wkey[0];
$string = "This\nis\na\ntest.";
/* Create a new literal data packet */
$data = new OpenPGP_LiteralDataPacket($string, array('format' => 'u', 'filename' => 'stuff.txt'));
$data->normalize(true); // Clearsign-style normalization of the LiteralDataPacket
/* Create a signer from the key */
$sign = new OpenPGP_Crypt_RSA($wkey);
/* The message is the signed data packet */
$m = $sign->sign($data);
/* Generate clearsigned data */
$packets = $m->signatures()[0];
echo "-----BEGIN PGP SIGNED MESSAGE-----\nHash: SHA256\n\n";
// Output normalised data. You could convert line endings here
// without breaking the signature, but do not add any
// trailing whitespace to lines.
echo preg_replace("/^-/", "- -", $packets[0]->data)."\n";
echo OpenPGP::enarmor($packets[1][0]->to_bytes(), "PGP SIGNATURE");
?>

View file

@ -0,0 +1,27 @@
<?php
// USAGE: php examples/deASCIIdeCrypt.php secretkey.asc password message.asc
// This will fail if the algo on key or message is not 3DES or AES
require_once dirname(__FILE__).'/../lib/openpgp.php';
require_once dirname(__FILE__).'/../lib/openpgp_crypt_rsa.php';
require_once dirname(__FILE__).'/../lib/openpgp_crypt_symmetric.php';
$keyASCII = file_get_contents($argv[1]);
$msgASCII = file_get_contents($argv[3]);
$keyEncrypted = OpenPGP_Message::parse(OpenPGP::unarmor($keyASCII, 'PGP PRIVATE KEY BLOCK'));
// Try each secret key packet
foreach($keyEncrypted as $p) {
if(!($p instanceof OpenPGP_SecretKeyPacket)) continue;
$key = OpenPGP_Crypt_Symmetric::decryptSecretKey($argv[2], $p);
$msg = OpenPGP_Message::parse(OpenPGP::unarmor($msgASCII, 'PGP MESSAGE'));
$decryptor = new OpenPGP_Crypt_RSA($key);
$decrypted = $decryptor->decrypt($msg);
var_dump($decrypted);
}

View file

@ -0,0 +1,15 @@
<?php
require_once dirname(__FILE__).'/../lib/openpgp.php';
require_once dirname(__FILE__).'/../lib/openpgp_crypt_rsa.php';
require_once dirname(__FILE__).'/../lib/openpgp_crypt_symmetric.php';
$key = OpenPGP_Message::parse(file_get_contents(dirname(__FILE__) . '/../tests/data/helloKey.gpg'));
$data = new OpenPGP_LiteralDataPacket('This is text.', array('format' => 'u', 'filename' => 'stuff.txt'));
$encrypted = OpenPGP_Crypt_Symmetric::encrypt($key, new OpenPGP_Message(array($data)));
// Now decrypt it with the same key
$decryptor = new OpenPGP_Crypt_RSA($key);
$decrypted = $decryptor->decrypt($encrypted);
var_dump($decrypted);

View file

@ -0,0 +1,31 @@
<?php
require_once dirname(__FILE__).'/../lib/openpgp.php';
require_once dirname(__FILE__).'/../lib/openpgp_crypt_rsa.php';
$rsa = new \phpseclib\Crypt\RSA();
$k = $rsa->createKey(512);
$rsa->loadKey($k['privatekey']);
$nkey = new OpenPGP_SecretKeyPacket(array(
'n' => $rsa->modulus->toBytes(),
'e' => $rsa->publicExponent->toBytes(),
'd' => $rsa->exponent->toBytes(),
'p' => $rsa->primes[2]->toBytes(),
'q' => $rsa->primes[1]->toBytes(),
'u' => $rsa->coefficients[2]->toBytes()
));
$uid = new OpenPGP_UserIDPacket('Test <test@example.com>');
$wkey = new OpenPGP_Crypt_RSA($nkey);
$m = $wkey->sign_key_userid(array($nkey, $uid));
// Serialize private key
print $m->to_bytes();
// Serialize public key message
$pubm = clone($m);
$pubm[0] = new OpenPGP_PublicKeyPacket($pubm[0]);
$public_bytes = $pubm->to_bytes();

View file

@ -0,0 +1,22 @@
<?php
require_once dirname(__FILE__).'/../lib/openpgp.php';
require_once dirname(__FILE__).'/../lib/openpgp_crypt_rsa.php';
/* Parse secret key from STDIN, the key must not be password protected */
$wkey = OpenPGP_Message::parse(file_get_contents('php://stdin'));
$wkey = $wkey[0];
/* Create a new literal data packet */
$data = new OpenPGP_LiteralDataPacket('This is text.', array('format' => 'u', 'filename' => 'stuff.txt'));
/* Create a signer from the key */
$sign = new OpenPGP_Crypt_RSA($wkey);
/* The message is the signed data packet */
$m = $sign->sign($data);
/* Output the raw message bytes to STDOUT */
echo $m->to_bytes();
?>

View file

@ -0,0 +1,18 @@
<?php
require_once dirname(__FILE__).'/../lib/openpgp.php';
require_once dirname(__FILE__).'/../lib/openpgp_crypt_rsa.php';
/* Parse public key from STDIN */
$wkey = OpenPGP_Message::parse(file_get_contents('php://stdin'));
/* Parse signed message from file named "t" */
$m = OpenPGP_Message::parse(file_get_contents('t'));
/* Create a verifier for the key */
$verify = new OpenPGP_Crypt_RSA($wkey);
/* Dump verification information to STDOUT */
var_dump($verify->verify($m));
?>

View file

@ -5,7 +5,7 @@
* (RFC 4880).
*
* @package OpenPGP
* @version 0.0.1
* @version 0.3.0
* @author Arto Bendiken <arto.bendiken@gmail.com>
* @author Stephen Paul Weber <singpolyma@singpolyma.net>
* @see http://github.com/bendiken/openpgp-php
@ -1327,15 +1327,32 @@ class OpenPGP_PublicKeyPacket extends OpenPGP_Packet {
function __construct($key=array(), $algorithm='RSA', $timestamp=NULL, $version=4) {
parent::__construct();
$this->key = $key;
if(is_string($this->algorithm = $algorithm)) {
$this->algorithm = array_search($this->algorithm, self::$algorithms);
}
$this->timestamp = $timestamp ? $timestamp : time();
$this->version = $version;
if(count($this->key) > 0) {
$this->key_id = substr($this->fingerprint(), -8);
if($key instanceof OpenPGP_PublicKeyPacket) {
$this->algorithm = $key->algorithm;
$this->key = array();
// Restrict to only the fields we need
foreach (self::$key_fields[$this->algorithm] as $field) {
$this->key[$field] = $key->key[$field];
}
$this->key_id = $key->key_id;
$this->fingerprint = $key->fingerprint;
$this->timestamp = $key->timestamp;
$this->version = $key->version;
$this->v3_days_of_validity = $key->v3_days_of_validity;
} else {
$this->key = $key;
if(is_string($this->algorithm = $algorithm)) {
$this->algorithm = array_search($this->algorithm, self::$algorithms);
}
$this->timestamp = $timestamp ? $timestamp : time();
$this->version = $version;
if(count($this->key) > 0) {
$this->key_id = substr($this->fingerprint(), -8);
}
}
}
@ -1685,10 +1702,19 @@ class OpenPGP_LiteralDataPacket extends OpenPGP_Packet {
$this->timestamp = isset($opt['timestamp']) ? $opt['timestamp'] : time();
}
function normalize() {
function normalize($clearsign=false) {
if($clearsign && ($this->format != 'u' && $this->format != 't')) {
$this->format = 'u'; // Clearsign must be text
}
if($this->format == 'u' || $this->format == 't') { // Normalize line endings
$this->data = str_replace("\n", "\r\n", str_replace("\r", "\n", str_replace("\r\n", "\n", $this->data)));
}
if($clearsign) {
// When clearsigning, do not sign over trailing whitespace
$this->data = preg_replace('/\s+\r/', "\r", $this->data);
}
}
function read() {

View file

@ -7,7 +7,11 @@
*/
// From http://phpseclib.sourceforge.net/
require_once 'Crypt/RSA.php';
use phpseclib\Crypt\RSA as Crypt_RSA;
use phpseclib\Math\BigInteger as Math_BigInteger;
define('CRYPT_RSA_ENCRYPTION_PKCS1', Crypt_RSA::ENCRYPTION_PKCS1);
define('CRYPT_RSA_SIGNATURE_PKCS1', Crypt_RSA::SIGNATURE_PKCS1);
require_once dirname(__FILE__).'/openpgp.php';
@include_once dirname(__FILE__).'/openpgp_crypt_symmetric.php'; /* For encrypt/decrypt */
@ -150,7 +154,7 @@ class OpenPGP_Crypt_RSA {
if(!$sig) {
$sig = new OpenPGP_SignaturePacket($packet, 'RSA', strtoupper($hash));
$sig->signature_type = 0x13;
$sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_KeyFlagsPacket(array(0x01, 0x02));
$sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_KeyFlagsPacket(array(0x01 | 0x02));
$sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_IssuerPacket($keyid);
$packet[] = $sig;
}
@ -241,8 +245,18 @@ class OpenPGP_Crypt_RSA {
$rsa = self::crypt_rsa_key($mod, $exp);
if($private) {
if($packet->key['p'] && $packet->key['q']) $rsa->primes = array($packet->key['p'], $packet->key['q']);
if($packet->key['u']) $rsa->coefficients = array($packet->key['u']);
/**
* @see https://github.com/phpseclib/phpseclib/issues/1113
* Primes and coefficients now use BigIntegers.
**/
//set the primes
if($packet->key['p'] && $packet->key['q'])
$rsa->primes = array(
1 => new Math_BigInteger($packet->key['p'], 256),
2 => new Math_BigInteger($packet->key['q'], 256)
);
// set the coefficients
if($packet->key['u']) $rsa->coefficients = array(2 => new Math_BigInteger($packet->key['u'], 256));
}
return $rsa;

View file

@ -1,20 +1,24 @@
<?php
use phpseclib\Crypt\TripleDES as Crypt_TripleDES;
use phpseclib\Crypt\AES as Crypt_AES;
use phpseclib\Crypt\Random;
define('CRYPT_DES_MODE_CFB', Crypt_TripleDES::MODE_CFB);
define('CRYPT_AES_MODE_CFB', Crypt_AES::MODE_CFB);
require_once dirname(__FILE__).'/openpgp.php';
@include_once dirname(__FILE__).'/openpgp_crypt_rsa.php';
@include_once dirname(__FILE__).'/openpgp_mcrypt_wrapper.php';
@include_once 'Crypt/AES.php';
@include_once 'Crypt/TripleDES.php';
require_once 'Crypt/Random.php'; // part of phpseclib is absolutely required
class OpenPGP_Crypt_Symmetric {
public static function encrypt($passphrases_and_keys, $message, $symmetric_algorithm=9) {
list($cipher, $key_bytes, $key_block_bytes) = self::getCipher($symmetric_algorithm);
if(!$cipher) throw new Exception("Unsupported cipher");
$prefix = crypt_random_string($key_block_bytes);
$prefix = Random::string($key_block_bytes);
$prefix .= substr($prefix, -2);
$key = crypt_random_string($key_bytes);
$key = Random::string($key_bytes);
$cipher->setKey($key);
$to_encrypt = $prefix . $message->to_bytes();
@ -36,7 +40,7 @@ class OpenPGP_Crypt_Symmetric {
$esk = pack('n', OpenPGP::bitlength($esk)) . $esk;
array_unshift($encrypted, new OpenPGP_AsymmetricSessionKeyPacket($pass->algorithm, $pass->fingerprint(), $esk));
} else if(is_string($pass)) {
$s2k = new OpenPGP_S2K(crypt_random_string(10));
$s2k = new OpenPGP_S2K(Random::string(10));
$cipher->setKey($s2k->make_key($pass, $key_bytes));
$esk = $cipher->encrypt(chr($symmetric_algorithm) . $key);
array_unshift($encrypted, new OpenPGP_SymmetricSessionKeyPacket($s2k, $esk, $symmetric_algorithm));
@ -143,38 +147,32 @@ class OpenPGP_Crypt_Symmetric {
$cipher = NULL;
switch($algo) {
case 2:
if(class_exists('Crypt_TripleDES')) {
$cipher = new Crypt_TripleDES(CRYPT_DES_MODE_CFB);
$key_bytes = 24;
$key_block_bytes = 8;
}
break;
case 3:
if(defined('MCRYPT_CAST_128')) {
$cipher = new MCryptWrapper(MCRYPT_CAST_128);
} else {
throw new Exception("Unsupported cipher: you must have mcrypt installed to use CAST5");
}
break;
case 7:
if(class_exists('Crypt_AES')) {
$cipher = new Crypt_AES(CRYPT_AES_MODE_CFB);
$cipher->setKeyLength(128);
}
break;
case 8:
if(class_exists('Crypt_AES')) {
$cipher = new Crypt_AES(CRYPT_AES_MODE_CFB);
$cipher->setKeyLength(192);
}
break;
case 9:
if(class_exists('Crypt_AES')) {
$cipher = new Crypt_AES(CRYPT_AES_MODE_CFB);
$cipher->setKeyLength(256);
}
break;
}
if(!$cipher) return array(NULL, NULL, NULL); // Unsupported cipher
if(!isset($key_bytes)) $key_bytes = $cipher->key_size;
if(!isset($key_bytes)) $key_bytes = isset($cipher->key_size)?$cipher->key_size:$cipher->key_length;
if(!isset($key_block_bytes)) $key_block_bytes = $cipher->block_size;
return array($cipher, $key_bytes, $key_block_bytes);
}

View file

@ -0,0 +1,27 @@
<phpunit bootstrap="tests/bootstrap.php">
<testsuites>
<testsuite name="Serialization">
<file>tests/suite.php</file>
</testsuite>
<testsuite name="Fingerprint">
<file>tests/suite.php</file>
</testsuite>
<testsuite name="MessageVerification">
<file>tests/phpseclib_suite.php</file>
</testsuite>
<testsuite name="KeyVerification">
<file>tests/phpseclib_suite.php</file>
</testsuite>
<testsuite name="Decryption">
<file>tests/phpseclib_suite.php</file>
</testsuite>
<testsuite name="Encryption">
<file>tests/phpseclib_suite.php</file>
</testsuite>
</testsuites>
</phpunit>

View file

@ -0,0 +1,2 @@
<?php
@include_once dirname(__FILE__) . '/../vendor/autoload.php';

View file

@ -0,0 +1 @@
´$Test Key (RSA) <testkey@example.org>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1 @@
´$Test Key (DSA) <testkey@example.com>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1 @@
´+Test Key (DSA sign-only) <test@example.net>

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1 @@
´.Test Key (RSA sign-only) <testkey@example.net>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1 @@
´$Test Key (RSA) <testkey@example.org>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1 @@
´$Test Key (DSA) <testkey@example.com>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1 @@
´+Test Key (DSA sign-only) <test@example.net>

Binary file not shown.

View file

@ -0,0 +1 @@
´.Test Key (RSA sign-only) <testkey@example.net>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1 @@
<EFBFBD>  »†F<E280A0>yDד`ׂ>ל~i•XaMי©Mֲ<4D>7*W£<57>K1®I÷ֹ&¢·U<C2B7>]-axףsצn´לםײ<D79D>ל©ף§jUִ<55>ַ•%ְרװ©e<1E>

View file

@ -0,0 +1 @@
Ś “9ĆÖF‡-`Ň2ľč<C4BE>—w¦¨DżĘş0q<30>,Čůzřý}Zϲ֣‡#Öľźí aŮ!ţ!Í

View file

@ -0,0 +1,2 @@
[╗║JHвBи`и#╔{у%МШ▒|·│╘6≥buБC╩ gщ+
HчдХ

View file

@ -0,0 +1,135 @@
<?php
/* The tests which require phpseclib */
require_once dirname(__FILE__).'/../lib/openpgp.php';
require_once dirname(__FILE__).'/../lib/openpgp_crypt_rsa.php';
require_once dirname(__FILE__).'/../lib/openpgp_crypt_symmetric.php';
class MessageVerification extends PHPUnit_Framework_TestCase {
public function oneMessageRSA($pkey, $path) {
$pkeyM = OpenPGP_Message::parse(file_get_contents(dirname(__FILE__) . '/data/' . $pkey));
$m = OpenPGP_Message::parse(file_get_contents(dirname(__FILE__) . '/data/' . $path));
$verify = new OpenPGP_Crypt_RSA($pkeyM);
$this->assertSame($verify->verify($m), $m->signatures());
}
public function testUncompressedOpsRSA() {
$this->oneMessageRSA('pubring.gpg', 'uncompressed-ops-rsa.gpg');
}
public function testCompressedSig() {
$this->oneMessageRSA('pubring.gpg', 'compressedsig.gpg');
}
public function testCompressedSigZLIB() {
$this->oneMessageRSA('pubring.gpg', 'compressedsig-zlib.gpg');
}
public function testCompressedSigBzip2() {
$this->oneMessageRSA('pubring.gpg', 'compressedsig-bzip2.gpg');
}
public function testSigningMessages() {
$wkey = OpenPGP_Message::parse(file_get_contents(dirname(__FILE__) . '/data/helloKey.gpg'));
$data = new OpenPGP_LiteralDataPacket('This is text.', array('format' => 'u', 'filename' => 'stuff.txt'));
$sign = new OpenPGP_Crypt_RSA($wkey);
$m = $sign->sign($data)->to_bytes();
$reparsedM = OpenPGP_Message::parse($m);
$this->assertSame($sign->verify($reparsedM), $reparsedM->signatures());
}
/*
public function testUncompressedOpsDSA() {
$this->oneMessageDSA('pubring.gpg', 'uncompressed-ops-dsa.gpg');
}
public function testUncompressedOpsDSAsha384() {
$this->oneMessageDSA('pubring.gpg', 'uncompressed-ops-dsa-sha384.gpg');
}
*/
}
class KeyVerification extends PHPUnit_Framework_TestCase {
public function oneKeyRSA($path) {
$m = OpenPGP_Message::parse(file_get_contents(dirname(__FILE__) . '/data/' . $path));
$verify = new OpenPGP_Crypt_RSA($m);
$this->assertSame($verify->verify($m), $m->signatures());
}
public function testHelloKey() {
$this->oneKeyRSA("helloKey.gpg");
}
}
class Decryption extends PHPUnit_Framework_TestCase {
public function oneSymmetric($pass, $cnt, $path) {
$m = OpenPGP_Message::parse(file_get_contents(dirname(__FILE__) . '/data/' . $path));
$m2 = OpenPGP_Crypt_Symmetric::decryptSymmetric($pass, $m);
while($m2[0] instanceof OpenPGP_CompressedDataPacket) $m2 = $m2[0]->data;
foreach($m2 as $p) {
if($p instanceof OpenPGP_LiteralDataPacket) {
$this->assertEquals($p->data, $cnt);
}
}
}
public function testDecryptAES() {
$this->oneSymmetric("hello", "PGP\n", "symmetric-aes.gpg");
}
public function testDecrypt3DES() {
$this->oneSymmetric("hello", "PGP\n", "symmetric-3des.gpg");
}
public function testDecryptCAST5() { // Requires mcrypt
$this->oneSymmetric("hello", "PGP\n", "symmetric-cast5.gpg");
}
public function testDecryptSessionKey() {
$this->oneSymmetric("hello", "PGP\n", "symmetric-with-session-key.gpg");
}
public function testDecryptNoMDC() {
$this->oneSymmetric("hello", "PGP\n", "symmetric-no-mdc.gpg");
}
public function testDecryptAsymmetric() {
$m = OpenPGP_Message::parse(file_get_contents(dirname(__FILE__) . '/data/hello.gpg'));
$key = OpenPGP_Message::parse(file_get_contents(dirname(__FILE__) . '/data/helloKey.gpg'));
$decryptor = new OpenPGP_Crypt_RSA($key);
$m2 = $decryptor->decrypt($m);
while($m2[0] instanceof OpenPGP_CompressedDataPacket) $m2 = $m2[0]->data;
foreach($m2 as $p) {
if($p instanceof OpenPGP_LiteralDataPacket) {
$this->assertEquals($p->data, "hello\n");
}
}
}
public function testDecryptSecretKey() {
$key = OpenPGP_Message::parse(file_get_contents(dirname(__FILE__) . '/data/encryptedSecretKey.gpg'));
$skey = OpenPGP_Crypt_Symmetric::decryptSecretKey("hello", $key[0]);
$this->assertSame(!!$skey, true);
}
}
class Encryption extends PHPUnit_Framework_TestCase {
public function testEncryptSymmetric() {
$data = new OpenPGP_LiteralDataPacket('This is text.', array('format' => 'u', 'filename' => 'stuff.txt'));
$encrypted = OpenPGP_Crypt_Symmetric::encrypt('secret', new OpenPGP_Message(array($data)));
$decrypted = OpenPGP_Crypt_Symmetric::decryptSymmetric('secret', $encrypted);
$this->assertEquals($decrypted[0]->data, 'This is text.');
}
public function testEncryptAsymmetric() {
$key = OpenPGP_Message::parse(file_get_contents(dirname(__FILE__) . '/data/helloKey.gpg'));
$data = new OpenPGP_LiteralDataPacket('This is text.', array('format' => 'u', 'filename' => 'stuff.txt'));
$encrypted = OpenPGP_Crypt_Symmetric::encrypt($key, new OpenPGP_Message(array($data)));
$decryptor = new OpenPGP_Crypt_RSA($key);
$decrypted = $decryptor->decrypt($encrypted);
$this->assertEquals($decrypted[0]->data, 'This is text.');
}
}

View file

@ -0,0 +1,400 @@
<?php
require_once dirname(__FILE__).'/../lib/openpgp.php';
class Serialization extends PHPUnit_Framework_TestCase {
public function oneSerialization($path) {
$in = OpenPGP_Message::parse(file_get_contents(dirname(__FILE__) . '/data/' . $path));
$mid = $in->to_bytes();
$out = OpenPGP_Message::parse($mid);
$this->assertEquals($in, $out);
}
public function test000001006public_key() {
$this->oneSerialization("000001-006.public_key");
}
public function test000002013user_id() {
$this->oneSerialization("000002-013.user_id");
}
public function test000003002sig() {
$this->oneSerialization("000003-002.sig");
}
public function test000004012ring_trust() {
$this->oneSerialization("000004-012.ring_trust");
}
public function test000005002sig() {
$this->oneSerialization("000005-002.sig");
}
public function test000006012ring_trust() {
$this->oneSerialization("000006-012.ring_trust");
}
public function test000007002sig() {
$this->oneSerialization("000007-002.sig");
}
public function test000008012ring_trust() {
$this->oneSerialization("000008-012.ring_trust");
}
public function test000009002sig() {
$this->oneSerialization("000009-002.sig");
}
public function test000010012ring_trust() {
$this->oneSerialization("000010-012.ring_trust");
}
public function test000011002sig() {
$this->oneSerialization("000011-002.sig");
}
public function test000012012ring_trust() {
$this->oneSerialization("000012-012.ring_trust");
}
public function test000013014public_subkey() {
$this->oneSerialization("000013-014.public_subkey");
}
public function test000014002sig() {
$this->oneSerialization("000014-002.sig");
}
public function test000015012ring_trust() {
$this->oneSerialization("000015-012.ring_trust");
}
public function test000016006public_key() {
$this->oneSerialization("000016-006.public_key");
}
public function test000017002sig() {
$this->oneSerialization("000017-002.sig");
}
public function test000018012ring_trust() {
$this->oneSerialization("000018-012.ring_trust");
}
public function test000019013user_id() {
$this->oneSerialization("000019-013.user_id");
}
public function test000020002sig() {
$this->oneSerialization("000020-002.sig");
}
public function test000021012ring_trust() {
$this->oneSerialization("000021-012.ring_trust");
}
public function test000022002sig() {
$this->oneSerialization("000022-002.sig");
}
public function test000023012ring_trust() {
$this->oneSerialization("000023-012.ring_trust");
}
public function test000024014public_subkey() {
$this->oneSerialization("000024-014.public_subkey");
}
public function test000025002sig() {
$this->oneSerialization("000025-002.sig");
}
public function test000026012ring_trust() {
$this->oneSerialization("000026-012.ring_trust");
}
public function test000027006public_key() {
$this->oneSerialization("000027-006.public_key");
}
public function test000028002sig() {
$this->oneSerialization("000028-002.sig");
}
public function test000029012ring_trust() {
$this->oneSerialization("000029-012.ring_trust");
}
public function test000030013user_id() {
$this->oneSerialization("000030-013.user_id");
}
public function test000031002sig() {
$this->oneSerialization("000031-002.sig");
}
public function test000032012ring_trust() {
$this->oneSerialization("000032-012.ring_trust");
}
public function test000033002sig() {
$this->oneSerialization("000033-002.sig");
}
public function test000034012ring_trust() {
$this->oneSerialization("000034-012.ring_trust");
}
public function test000035006public_key() {
$this->oneSerialization("000035-006.public_key");
}
public function test000036013user_id() {
$this->oneSerialization("000036-013.user_id");
}
public function test000037002sig() {
$this->oneSerialization("000037-002.sig");
}
public function test000038012ring_trust() {
$this->oneSerialization("000038-012.ring_trust");
}
public function test000039002sig() {
$this->oneSerialization("000039-002.sig");
}
public function test000040012ring_trust() {
$this->oneSerialization("000040-012.ring_trust");
}
public function test000041017attribute() {
$this->oneSerialization("000041-017.attribute");
}
public function test000042002sig() {
$this->oneSerialization("000042-002.sig");
}
public function test000043012ring_trust() {
$this->oneSerialization("000043-012.ring_trust");
}
public function test000044014public_subkey() {
$this->oneSerialization("000044-014.public_subkey");
}
public function test000045002sig() {
$this->oneSerialization("000045-002.sig");
}
public function test000046012ring_trust() {
$this->oneSerialization("000046-012.ring_trust");
}
public function test000047005secret_key() {
$this->oneSerialization("000047-005.secret_key");
}
public function test000048013user_id() {
$this->oneSerialization("000048-013.user_id");
}
public function test000049002sig() {
$this->oneSerialization("000049-002.sig");
}
public function test000050012ring_trust() {
$this->oneSerialization("000050-012.ring_trust");
}
public function test000051007secret_subkey() {
$this->oneSerialization("000051-007.secret_subkey");
}
public function test000052002sig() {
$this->oneSerialization("000052-002.sig");
}
public function test000053012ring_trust() {
$this->oneSerialization("000053-012.ring_trust");
}
public function test000054005secret_key() {
$this->oneSerialization("000054-005.secret_key");
}
public function test000055002sig() {
$this->oneSerialization("000055-002.sig");
}
public function test000056012ring_trust() {
$this->oneSerialization("000056-012.ring_trust");
}
public function test000057013user_id() {
$this->oneSerialization("000057-013.user_id");
}
public function test000058002sig() {
$this->oneSerialization("000058-002.sig");
}
public function test000059012ring_trust() {
$this->oneSerialization("000059-012.ring_trust");
}
public function test000060007secret_subkey() {
$this->oneSerialization("000060-007.secret_subkey");
}
public function test000061002sig() {
$this->oneSerialization("000061-002.sig");
}
public function test000062012ring_trust() {
$this->oneSerialization("000062-012.ring_trust");
}
public function test000063005secret_key() {
$this->oneSerialization("000063-005.secret_key");
}
public function test000064002sig() {
$this->oneSerialization("000064-002.sig");
}
public function test000065012ring_trust() {
$this->oneSerialization("000065-012.ring_trust");
}
public function test000066013user_id() {
$this->oneSerialization("000066-013.user_id");
}
public function test000067002sig() {
$this->oneSerialization("000067-002.sig");
}
public function test000068012ring_trust() {
$this->oneSerialization("000068-012.ring_trust");
}
public function test000069005secret_key() {
$this->oneSerialization("000069-005.secret_key");
}
public function test000070013user_id() {
$this->oneSerialization("000070-013.user_id");
}
public function test000071002sig() {
$this->oneSerialization("000071-002.sig");
}
public function test000072012ring_trust() {
$this->oneSerialization("000072-012.ring_trust");
}
public function test000073017attribute() {
$this->oneSerialization("000073-017.attribute");
}
public function test000074002sig() {
$this->oneSerialization("000074-002.sig");
}
public function test000075012ring_trust() {
$this->oneSerialization("000075-012.ring_trust");
}
public function test000076007secret_subkey() {
$this->oneSerialization("000076-007.secret_subkey");
}
public function test000077002sig() {
$this->oneSerialization("000077-002.sig");
}
public function test000078012ring_trust() {
$this->oneSerialization("000078-012.ring_trust");
}
public function test002182002sig() {
$this->oneSerialization("002182-002.sig");
}
public function testpubringgpg() {
$this->oneSerialization("pubring.gpg");
}
public function testsecringgpg() {
$this->oneSerialization("secring.gpg");
}
public function testcompressedsiggpg() {
$this->oneSerialization("compressedsig.gpg");
}
public function testcompressedsigzlibgpg() {
$this->oneSerialization("compressedsig-zlib.gpg");
}
public function testcompressedsigbzip2gpg() {
$this->oneSerialization("compressedsig-bzip2.gpg");
}
public function testonepass_sig() {
$this->oneSerialization("onepass_sig");
}
public function testsymmetrically_encrypted() {
$this->oneSerialization("symmetrically_encrypted");
}
public function testuncompressedopsdsagpg() {
$this->oneSerialization("uncompressed-ops-dsa.gpg");
}
public function testuncompressedopsdsasha384txtgpg() {
$this->oneSerialization("uncompressed-ops-dsa-sha384.txt.gpg");
}
public function testuncompressedopsrsagpg() {
$this->oneSerialization("uncompressed-ops-rsa.gpg");
}
public function testSymmetricAES() {
$this->oneSerialization("symmetric-aes.gpg");
}
public function testSymmetricNoMDC() {
$this->oneSerialization("symmetric-no-mdc.gpg");
}
}
class Fingerprint extends PHPUnit_Framework_TestCase {
public function oneFingerprint($path, $kf) {
$m = OpenPGP_Message::parse(file_get_contents(dirname(__FILE__) . '/data/' . $path));
$this->assertEquals($m[0]->fingerprint(), $kf);
}
public function test000001006public_key() {
$this->oneFingerprint("000001-006.public_key", "421F28FEAAD222F856C8FFD5D4D54EA16F87040E");
}
public function test000016006public_key() {
$this->oneFingerprint("000016-006.public_key", "AF95E4D7BAC521EE9740BED75E9F1523413262DC");
}
public function test000027006public_key() {
$this->oneFingerprint("000027-006.public_key", "1EB20B2F5A5CC3BEAFD6E5CB7732CF988A63EA86");
}
public function test000035006public_key() {
$this->oneFingerprint("000035-006.public_key", "CB7933459F59C70DF1C3FBEEDEDC3ECF689AF56D");
}
}