[CORE] Downgrade phpseclib to a working state
This commit is contained in:
parent
c1c2a9f1a1
commit
411e8ed79d
|
@ -24,7 +24,7 @@
|
|||
"michelf/php-markdown": "^1.8.0",
|
||||
"openid/php-openid": "^2.3",
|
||||
"paragonie/constant_time_encoding": "^1.0.4",
|
||||
"phpseclib/phpseclib": "^2.0.19",
|
||||
"phpseclib/phpseclib": "dev-master#f815e43077da67d3dd5b4d18a45753f5b79c1ab9",
|
||||
"stomp-php/stomp-php": "^4.5.1"
|
||||
},
|
||||
"require-dev": {
|
||||
|
|
73
composer.lock
generated
73
composer.lock
generated
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "1511cdda74eee145816ad9fe85138588",
|
||||
"content-hash": "ac49a57ede587e949b9bad4b3c080a1d",
|
||||
"packages": [
|
||||
{
|
||||
"name": "apereo/phpcas",
|
||||
|
@ -461,21 +461,72 @@
|
|||
"time": "2018-04-30T17:57:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpseclib/phpseclib",
|
||||
"version": "2.0.19",
|
||||
"name": "paragonie/random_compat",
|
||||
"version": "v2.0.18",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||
"reference": "d2085db7b7394baa071a69c8f9159723c250f2ba"
|
||||
"url": "https://github.com/paragonie/random_compat.git",
|
||||
"reference": "0a58ef6e3146256cc3dc7cc393927bcc7d1b72db"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d2085db7b7394baa071a69c8f9159723c250f2ba",
|
||||
"reference": "d2085db7b7394baa071a69c8f9159723c250f2ba",
|
||||
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/0a58ef6e3146256cc3dc7cc393927bcc7d1b72db",
|
||||
"reference": "0a58ef6e3146256cc3dc7cc393927bcc7d1b72db",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
"php": ">=5.2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "4.*|5.*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"lib/random.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Paragon Initiative Enterprises",
|
||||
"email": "security@paragonie.com",
|
||||
"homepage": "https://paragonie.com"
|
||||
}
|
||||
],
|
||||
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
|
||||
"keywords": [
|
||||
"csprng",
|
||||
"polyfill",
|
||||
"pseudorandom",
|
||||
"random"
|
||||
],
|
||||
"time": "2019-01-03T20:59:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpseclib/phpseclib",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||
"reference": "f815e43077da67d3dd5b4d18a45753f5b79c1ab9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/f815e43077da67d3dd5b4d18a45753f5b79c1ab9",
|
||||
"reference": "f815e43077da67d3dd5b4d18a45753f5b79c1ab9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"paragonie/constant_time_encoding": "^1",
|
||||
"paragonie/random_compat": "^1.4|^2.0",
|
||||
"php": ">=5.6.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phing/phing": "~2.7",
|
||||
|
@ -550,7 +601,7 @@
|
|||
"x.509",
|
||||
"x509"
|
||||
],
|
||||
"time": "2019-06-20T03:34:11+00:00"
|
||||
"time": "2019-06-23T16:33:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "stomp-php/stomp-php",
|
||||
|
@ -5822,7 +5873,9 @@
|
|||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "dev",
|
||||
"stability-flags": [],
|
||||
"stability-flags": {
|
||||
"phpseclib/phpseclib": 20
|
||||
},
|
||||
"prefer-stable": true,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
|
|
12
vendor/composer/autoload_classmap.php
vendored
12
vendor/composer/autoload_classmap.php
vendored
|
@ -474,10 +474,22 @@ return array(
|
|||
'phpseclib\\Crypt\\RC2' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RC2.php',
|
||||
'phpseclib\\Crypt\\RC4' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RC4.php',
|
||||
'phpseclib\\Crypt\\RSA' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RSA.php',
|
||||
'phpseclib\\Crypt\\RSA\\MSBLOB' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RSA/MSBLOB.php',
|
||||
'phpseclib\\Crypt\\RSA\\OpenSSH' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RSA/OpenSSH.php',
|
||||
'phpseclib\\Crypt\\RSA\\PKCS' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RSA/PKCS.php',
|
||||
'phpseclib\\Crypt\\RSA\\PKCS1' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RSA/PKCS1.php',
|
||||
'phpseclib\\Crypt\\RSA\\PKCS8' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RSA/PKCS8.php',
|
||||
'phpseclib\\Crypt\\RSA\\PuTTY' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RSA/PuTTY.php',
|
||||
'phpseclib\\Crypt\\RSA\\Raw' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RSA/Raw.php',
|
||||
'phpseclib\\Crypt\\RSA\\XML' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RSA/XML.php',
|
||||
'phpseclib\\Crypt\\Random' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Random.php',
|
||||
'phpseclib\\Crypt\\Rijndael' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php',
|
||||
'phpseclib\\Crypt\\TripleDES' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php',
|
||||
'phpseclib\\Crypt\\Twofish' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php',
|
||||
'phpseclib\\Exception\\BadConfigurationException' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Exception/BadConfigurationException.php',
|
||||
'phpseclib\\Exception\\FileNotFoundException' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Exception/FileNotFoundException.php',
|
||||
'phpseclib\\Exception\\NoSupportedAlgorithmsException' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Exception/NoSupportedAlgorithmsException.php',
|
||||
'phpseclib\\Exception\\UnsupportedAlgorithmException' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Exception/UnsupportedAlgorithmException.php',
|
||||
'phpseclib\\File\\ANSI' => $vendorDir . '/phpseclib/phpseclib/phpseclib/File/ANSI.php',
|
||||
'phpseclib\\File\\ASN1' => $vendorDir . '/phpseclib/phpseclib/phpseclib/File/ASN1.php',
|
||||
'phpseclib\\File\\ASN1\\Element' => $vendorDir . '/phpseclib/phpseclib/phpseclib/File/ASN1/Element.php',
|
||||
|
|
1
vendor/composer/autoload_files.php
vendored
1
vendor/composer/autoload_files.php
vendored
|
@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__));
|
|||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php',
|
||||
'2cffec82183ee1cea088009cef9a6fc3' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
|
||||
'757772e28a0943a9afe83def8db95bdf' => $vendorDir . '/mf2/mf2/Mf2/Parser.php',
|
||||
'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
|
||||
|
|
13
vendor/composer/autoload_static.php
vendored
13
vendor/composer/autoload_static.php
vendored
|
@ -7,6 +7,7 @@ namespace Composer\Autoload;
|
|||
class ComposerStaticInit444c3f31864f68a3f466e2c19837e185
|
||||
{
|
||||
public static $files = array (
|
||||
'5255c38a0faeba867671b61dfda6d864' => __DIR__ . '/..' . '/paragonie/random_compat/lib/random.php',
|
||||
'2cffec82183ee1cea088009cef9a6fc3' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
|
||||
'757772e28a0943a9afe83def8db95bdf' => __DIR__ . '/..' . '/mf2/mf2/Mf2/Parser.php',
|
||||
'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
|
||||
|
@ -542,10 +543,22 @@ class ComposerStaticInit444c3f31864f68a3f466e2c19837e185
|
|||
'phpseclib\\Crypt\\RC2' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RC2.php',
|
||||
'phpseclib\\Crypt\\RC4' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RC4.php',
|
||||
'phpseclib\\Crypt\\RSA' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RSA.php',
|
||||
'phpseclib\\Crypt\\RSA\\MSBLOB' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RSA/MSBLOB.php',
|
||||
'phpseclib\\Crypt\\RSA\\OpenSSH' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RSA/OpenSSH.php',
|
||||
'phpseclib\\Crypt\\RSA\\PKCS' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RSA/PKCS.php',
|
||||
'phpseclib\\Crypt\\RSA\\PKCS1' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RSA/PKCS1.php',
|
||||
'phpseclib\\Crypt\\RSA\\PKCS8' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RSA/PKCS8.php',
|
||||
'phpseclib\\Crypt\\RSA\\PuTTY' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RSA/PuTTY.php',
|
||||
'phpseclib\\Crypt\\RSA\\Raw' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RSA/Raw.php',
|
||||
'phpseclib\\Crypt\\RSA\\XML' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RSA/XML.php',
|
||||
'phpseclib\\Crypt\\Random' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Random.php',
|
||||
'phpseclib\\Crypt\\Rijndael' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php',
|
||||
'phpseclib\\Crypt\\TripleDES' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php',
|
||||
'phpseclib\\Crypt\\Twofish' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php',
|
||||
'phpseclib\\Exception\\BadConfigurationException' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Exception/BadConfigurationException.php',
|
||||
'phpseclib\\Exception\\FileNotFoundException' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Exception/FileNotFoundException.php',
|
||||
'phpseclib\\Exception\\NoSupportedAlgorithmsException' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Exception/NoSupportedAlgorithmsException.php',
|
||||
'phpseclib\\Exception\\UnsupportedAlgorithmException' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Exception/UnsupportedAlgorithmException.php',
|
||||
'phpseclib\\File\\ANSI' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/File/ANSI.php',
|
||||
'phpseclib\\File\\ASN1' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/File/ASN1.php',
|
||||
'phpseclib\\File\\ASN1\\Element' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/File/ASN1/Element.php',
|
||||
|
|
71
vendor/composer/installed.json
vendored
71
vendor/composer/installed.json
vendored
|
@ -470,22 +470,75 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"name": "phpseclib/phpseclib",
|
||||
"version": "2.0.19",
|
||||
"version_normalized": "2.0.19.0",
|
||||
"name": "paragonie/random_compat",
|
||||
"version": "v2.0.18",
|
||||
"version_normalized": "2.0.18.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||
"reference": "d2085db7b7394baa071a69c8f9159723c250f2ba"
|
||||
"url": "https://github.com/paragonie/random_compat.git",
|
||||
"reference": "0a58ef6e3146256cc3dc7cc393927bcc7d1b72db"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d2085db7b7394baa071a69c8f9159723c250f2ba",
|
||||
"reference": "d2085db7b7394baa071a69c8f9159723c250f2ba",
|
||||
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/0a58ef6e3146256cc3dc7cc393927bcc7d1b72db",
|
||||
"reference": "0a58ef6e3146256cc3dc7cc393927bcc7d1b72db",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
"php": ">=5.2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "4.*|5.*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
|
||||
},
|
||||
"time": "2019-01-03T20:59:08+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"lib/random.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Paragon Initiative Enterprises",
|
||||
"email": "security@paragonie.com",
|
||||
"homepage": "https://paragonie.com"
|
||||
}
|
||||
],
|
||||
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
|
||||
"keywords": [
|
||||
"csprng",
|
||||
"polyfill",
|
||||
"pseudorandom",
|
||||
"random"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "phpseclib/phpseclib",
|
||||
"version": "dev-master",
|
||||
"version_normalized": "9999999-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||
"reference": "f815e43077da67d3dd5b4d18a45753f5b79c1ab9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/f815e43077da67d3dd5b4d18a45753f5b79c1ab9",
|
||||
"reference": "f815e43077da67d3dd5b4d18a45753f5b79c1ab9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"paragonie/constant_time_encoding": "^1",
|
||||
"paragonie/random_compat": "^1.4|^2.0",
|
||||
"php": ">=5.6.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phing/phing": "~2.7",
|
||||
|
@ -499,7 +552,7 @@
|
|||
"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": "2019-06-20T03:34:11+00:00",
|
||||
"time": "2019-06-23T16:33:59+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
|
|
68
vendor/phpseclib/phpseclib/README.md
vendored
68
vendor/phpseclib/phpseclib/README.md
vendored
|
@ -1,43 +1,22 @@
|
|||
# phpseclib - PHP Secure Communications Library
|
||||
|
||||
[![Build Status](https://travis-ci.org/phpseclib/phpseclib.svg?branch=2.0)](https://travis-ci.org/phpseclib/phpseclib)
|
||||
[![Build Status](https://travis-ci.org/phpseclib/phpseclib.svg?branch=master)](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 (1.0.2)](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.2.zip/download)
|
||||
* [Browse Git](https://github.com/phpseclib/phpseclib)
|
||||
* [Code Coverage Report](https://coverage.phpseclib.org/2.0/latest/)
|
||||
* [Code Coverage Report](http://phpseclib.bantux.org/code_coverage/master/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)
|
||||
|
||||
## Documentation
|
||||
|
||||
* [Documentation / Manual](http://phpseclib.sourceforge.net/)
|
||||
* [API Documentation](https://api.phpseclib.org/2.0/) (generated by Sami)
|
||||
|
||||
## Branches
|
||||
|
||||
### master
|
||||
|
||||
* Development Branch
|
||||
* Unstable API
|
||||
* Do not use in production
|
||||
|
||||
### 2.0
|
||||
|
||||
* Long term support (LTS) release
|
||||
* Modernized version of 1.0
|
||||
* Minimum PHP version: 5.3.3
|
||||
* PSR-4 autoloading with namespace rooted at `\phpseclib`
|
||||
* Install via Composer: `composer require phpseclib/phpseclib ~2.0`
|
||||
|
||||
### 1.0
|
||||
|
||||
* Long term support (LTS) release
|
||||
* PHP4 compatible
|
||||
* Composer compatible (PSR-0 autoloading)
|
||||
* Install using Composer: `composer require phpseclib/phpseclib ~1.0`
|
||||
* Install using PEAR: See [phpseclib PEAR Channel Documentation](http://phpseclib.sourceforge.net/pear.htm)
|
||||
* [Download 1.0.16 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.16.zip/download)
|
||||
* [API Documentation](http://phpseclib.bantux.org/api/master/) (generated by Sami)
|
||||
|
||||
## Support
|
||||
|
||||
|
@ -47,29 +26,40 @@ Need Support?
|
|||
* [Create a Support Ticket on GitHub](https://github.com/phpseclib/phpseclib/issues/new)
|
||||
* [Browse the Support Forum](http://www.frostjedi.com/phpbb/viewforum.php?f=46) (no longer in use)
|
||||
|
||||
## Installing Development Dependencies
|
||||
|
||||
Dependencies are managed via Composer.
|
||||
|
||||
1. Download the [`composer.phar`](https://getcomposer.org/composer.phar) executable as per the
|
||||
[Composer Download Instructions](https://getcomposer.org/download/), e.g. by running
|
||||
|
||||
``` sh
|
||||
curl -sS https://getcomposer.org/installer | php
|
||||
```
|
||||
|
||||
2. Install Dependencies
|
||||
|
||||
``` sh
|
||||
php composer.phar install
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork the Project
|
||||
|
||||
2. Ensure you have Composer installed (see [Composer Download Instructions](https://getcomposer.org/download/))
|
||||
2. Install Development Dependencies
|
||||
|
||||
3. Install Development Dependencies
|
||||
3. Create a Feature Branch
|
||||
|
||||
``` sh
|
||||
composer install
|
||||
```
|
||||
|
||||
4. Create a Feature Branch
|
||||
|
||||
5. (Recommended) Run the Test Suite
|
||||
4. (Recommended) Run the Test Suite
|
||||
|
||||
``` sh
|
||||
vendor/bin/phpunit
|
||||
```
|
||||
6. (Recommended) Check whether your code conforms to our Coding Standards by running
|
||||
5. (Recommended) Check whether your code conforms to our Coding Standards by running
|
||||
|
||||
``` sh
|
||||
vendor/bin/phing -f build/build.xml sniff
|
||||
```
|
||||
|
||||
7. Send us a Pull Request
|
||||
6. Send us a Pull Request
|
||||
|
|
27
vendor/phpseclib/phpseclib/appveyor.yml
vendored
27
vendor/phpseclib/phpseclib/appveyor.yml
vendored
|
@ -1,27 +0,0 @@
|
|||
build: false
|
||||
shallow_clone: false
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
clone_folder: C:\projects\phpseclib
|
||||
|
||||
install:
|
||||
- cinst -y OpenSSL.Light
|
||||
- SET PATH=C:\Program Files\OpenSSL;%PATH%
|
||||
- sc config wuauserv start= auto
|
||||
- net start wuauserv
|
||||
- cinst -y php --version 5.6.30
|
||||
- cd c:\tools\php56
|
||||
- copy php.ini-production php.ini
|
||||
- echo date.timezone="UTC" >> php.ini
|
||||
- echo extension_dir=ext >> php.ini
|
||||
- echo extension=php_openssl.dll >> php.ini
|
||||
- echo extension=php_gmp.dll >> php.ini
|
||||
- cd C:\projects\phpseclib
|
||||
- SET PATH=C:\tools\php56;%PATH%
|
||||
- php.exe -r "readfile('http://getcomposer.org/installer');" | php.exe
|
||||
- php.exe composer.phar install --prefer-source --no-interaction
|
||||
|
||||
test_script:
|
||||
- cd C:\projects\phpseclib
|
||||
- vendor\bin\phpunit.bat tests/Windows32Test.php
|
4
vendor/phpseclib/phpseclib/composer.json
vendored
4
vendor/phpseclib/phpseclib/composer.json
vendored
|
@ -51,11 +51,13 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"paragonie/constant_time_encoding": "^1|^2",
|
||||
"paragonie/random_compat": "^1.4|^2.0",
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phing/phing": "~2.7",
|
||||
"phpunit/phpunit": "^4.8.35|^5.7|^6.0",
|
||||
"phpunit/phpunit": "~4.0",
|
||||
"sami/sami": "~2.0",
|
||||
"squizlabs/php_codesniffer": "~2.0"
|
||||
},
|
||||
|
|
|
@ -66,30 +66,32 @@ class AES extends Rijndael
|
|||
* @see \phpseclib\Crypt\Rijndael::setBlockLength()
|
||||
* @access public
|
||||
* @param int $length
|
||||
* @throws \BadMethodCallException anytime it's called
|
||||
*/
|
||||
function setBlockLength($length)
|
||||
{
|
||||
return;
|
||||
throw new \BadMethodCallException('The block length cannot be set for AES.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key length
|
||||
*
|
||||
* 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.
|
||||
* Valid key lengths are 128, 192, and 256. Set the link to bool(false) to disable a fixed key length
|
||||
*
|
||||
* @see \phpseclib\Crypt\Rijndael:setKeyLength()
|
||||
* @access public
|
||||
* @param int $length
|
||||
* @throws \LengthException if the key length isn't supported
|
||||
*/
|
||||
function setKeyLength($length)
|
||||
{
|
||||
switch ($length) {
|
||||
case 160:
|
||||
$length = 192;
|
||||
case 128:
|
||||
case 192:
|
||||
case 256:
|
||||
break;
|
||||
case 224:
|
||||
$length = 256;
|
||||
default:
|
||||
throw new \LengthException('Key of size ' . $length . ' not supported by this algorithm. Only keys of sizes 128, 192 or 256 supported');
|
||||
}
|
||||
parent::setKeyLength($length);
|
||||
}
|
||||
|
@ -103,24 +105,19 @@ class AES extends Rijndael
|
|||
* @see setKeyLength()
|
||||
* @access public
|
||||
* @param string $key
|
||||
* @throws \LengthException if the key length isn't supported
|
||||
*/
|
||||
function setKey($key)
|
||||
{
|
||||
parent::setKey($key);
|
||||
|
||||
if (!$this->explicit_key_length) {
|
||||
$length = strlen($key);
|
||||
switch (true) {
|
||||
case $length <= 16:
|
||||
$this->key_length = 16;
|
||||
break;
|
||||
case $length <= 24:
|
||||
$this->key_length = 24;
|
||||
break;
|
||||
default:
|
||||
$this->key_length = 32;
|
||||
}
|
||||
$this->_setEngine();
|
||||
switch (strlen($key)) {
|
||||
case 16:
|
||||
case 24:
|
||||
case 32:
|
||||
break;
|
||||
default:
|
||||
throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported');
|
||||
}
|
||||
|
||||
parent::setKey($key);
|
||||
}
|
||||
}
|
||||
|
|
367
vendor/phpseclib/phpseclib/phpseclib/Crypt/Base.php
vendored
367
vendor/phpseclib/phpseclib/phpseclib/Crypt/Base.php
vendored
|
@ -76,10 +76,6 @@ abstract class Base
|
|||
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
|
||||
*/
|
||||
const MODE_CFB = 3;
|
||||
/**
|
||||
* Encrypt / decrypt using the Cipher Feedback mode (8bit)
|
||||
*/
|
||||
const MODE_CFB8 = 38;
|
||||
/**
|
||||
* Encrypt / decrypt using the Output Feedback mode.
|
||||
*
|
||||
|
@ -143,7 +139,7 @@ abstract class Base
|
|||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
|
||||
var $key = false;
|
||||
|
||||
/**
|
||||
* The Initialization Vector
|
||||
|
@ -152,7 +148,7 @@ abstract class Base
|
|||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $iv;
|
||||
var $iv = false;
|
||||
|
||||
/**
|
||||
* A "sliding" Initialization Vector
|
||||
|
@ -433,15 +429,6 @@ abstract class Base
|
|||
*/
|
||||
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
|
||||
*
|
||||
|
@ -452,9 +439,16 @@ abstract class Base
|
|||
var $skip_key_adjustment = false;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
* Has the key length explicitly been set or should it be derived from the key, itself?
|
||||
*
|
||||
* Determines whether or not the mcrypt extension should be used.
|
||||
* @see self::setKeyLength()
|
||||
* @var bool
|
||||
* @access private
|
||||
*/
|
||||
var $explicit_key_length = false;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* $mode could be:
|
||||
*
|
||||
|
@ -468,54 +462,59 @@ abstract class Base
|
|||
*
|
||||
* - self::MODE_OFB
|
||||
*
|
||||
* If not explicitly set, self::MODE_CBC will be used.
|
||||
*
|
||||
* @param int $mode
|
||||
* @access public
|
||||
* @throws \InvalidArgumentException if an invalid / unsupported mode is provided
|
||||
*/
|
||||
function __construct($mode = self::MODE_CBC)
|
||||
function __construct($mode)
|
||||
{
|
||||
// $mode dependent settings
|
||||
switch ($mode) {
|
||||
case self::MODE_ECB:
|
||||
case self::MODE_CBC:
|
||||
$this->paddable = true;
|
||||
$this->mode = self::MODE_ECB;
|
||||
break;
|
||||
case self::MODE_CTR:
|
||||
case self::MODE_CFB:
|
||||
case self::MODE_CFB8:
|
||||
case self::MODE_OFB:
|
||||
case self::MODE_STREAM:
|
||||
$this->mode = $mode;
|
||||
$this->paddable = false;
|
||||
break;
|
||||
case self::MODE_CBC:
|
||||
default:
|
||||
$this->paddable = true;
|
||||
$this->mode = self::MODE_CBC;
|
||||
throw new \InvalidArgumentException('No valid mode has been specified');
|
||||
}
|
||||
|
||||
$this->_setEngine();
|
||||
$this->mode = $mode;
|
||||
|
||||
// Determining whether inline crypting can be used by the cipher
|
||||
if ($this->use_inline_crypt !== false) {
|
||||
$this->use_inline_crypt = version_compare(PHP_VERSION, '5.3.0') >= 0 || function_exists('create_function');
|
||||
if ($this->use_inline_crypt !== false && function_exists('create_function')) {
|
||||
$this->use_inline_crypt = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the initialization vector. (optional)
|
||||
* Sets the initialization vector.
|
||||
*
|
||||
* 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.
|
||||
* setIV() is not required when self::MODE_ECB (or ie for AES: \phpseclib\Crypt\AES::MODE_ECB) is being used.
|
||||
*
|
||||
* @access public
|
||||
* @param string $iv
|
||||
* @throws \LengthException if the IV length isn't equal to the block size
|
||||
* @throws \InvalidArgumentException if an IV is provided when one shouldn't be
|
||||
* @internal Can be overwritten by a sub class, but does not have to be
|
||||
*/
|
||||
function setIV($iv)
|
||||
{
|
||||
if ($this->mode == self::MODE_ECB) {
|
||||
return;
|
||||
throw new \InvalidArgumentException('This mode does not require an IV.');
|
||||
}
|
||||
|
||||
if ($this->mode == self::MODE_STREAM && $this->usesIV()) {
|
||||
throw new \InvalidArgumentException('This algorithm does not use an IV.');
|
||||
}
|
||||
|
||||
if (strlen($iv) != $this->block_size) {
|
||||
throw new \LengthException('Received initialization vector of size ' . strlen($iv) . ', but size ' . $this->block_size . ' is required');
|
||||
}
|
||||
|
||||
$this->iv = $iv;
|
||||
|
@ -523,18 +522,14 @@ abstract class Base
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the key length.
|
||||
*
|
||||
* Keys with explicitly set lengths need to be treated accordingly
|
||||
* Returns whether or not the algorithm uses an IV
|
||||
*
|
||||
* @access public
|
||||
* @param int $length
|
||||
* @return bool
|
||||
*/
|
||||
function setKeyLength($length)
|
||||
function usesIV()
|
||||
{
|
||||
$this->explicit_key_length = true;
|
||||
$this->changed = true;
|
||||
$this->_setEngine();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -559,6 +554,24 @@ abstract class Base
|
|||
return $this->block_size << 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = $length >> 3;
|
||||
|
||||
if (is_string($this->key) && strlen($this->key) != $this->explicit_key_length) {
|
||||
$this->key = false;
|
||||
throw new \LengthException('Key has already been set and is not ' .$this->explicit_key_length . ' bytes long');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key.
|
||||
*
|
||||
|
@ -575,12 +588,12 @@ abstract class Base
|
|||
*/
|
||||
function setKey($key)
|
||||
{
|
||||
if (!$this->explicit_key_length) {
|
||||
$this->setKeyLength(strlen($key) << 3);
|
||||
$this->explicit_key_length = false;
|
||||
if ($this->explicit_key_length !== false && strlen($key) != $this->explicit_key_length) {
|
||||
throw new \LengthException('Key length has already been set to ' . $this->explicit_key_length . ' bytes and this key is ' . strlen($key) . ' bytes');
|
||||
}
|
||||
|
||||
$this->key = $key;
|
||||
$this->key_length = strlen($key);
|
||||
$this->changed = true;
|
||||
$this->_setEngine();
|
||||
}
|
||||
|
@ -597,6 +610,7 @@ abstract class Base
|
|||
* @see Crypt/Hash.php
|
||||
* @param string $password
|
||||
* @param string $method
|
||||
* @throws \LengthException if pbkdf1 is being used and the derived key length exceeds the hash length
|
||||
* @return bool
|
||||
* @access public
|
||||
* @internal Could, but not must, extend by the child Crypt_* class
|
||||
|
@ -623,7 +637,8 @@ abstract class Base
|
|||
if (isset($func_args[5])) {
|
||||
$dkLen = $func_args[5];
|
||||
} else {
|
||||
$dkLen = $method == 'pbkdf1' ? 2 * $this->key_length : $this->key_length;
|
||||
$key_length = $this->explicit_key_length !== false ? $this->explicit_key_length : $this->key_length;
|
||||
$dkLen = $method == 'pbkdf1' ? 2 * $key_length : $key_length;
|
||||
}
|
||||
|
||||
switch (true) {
|
||||
|
@ -631,8 +646,7 @@ abstract class Base
|
|||
$hashObj = new Hash();
|
||||
$hashObj->setHash($hash);
|
||||
if ($dkLen > $hashObj->getLength()) {
|
||||
user_error('Derived key too long');
|
||||
return false;
|
||||
throw new \LengthException('Derived key length cannot be longer than the hash length');
|
||||
}
|
||||
$t = $password . $salt;
|
||||
for ($i = 0; $i < $count; ++$i) {
|
||||
|
@ -649,10 +663,10 @@ abstract class Base
|
|||
case !function_exists('hash_algos'):
|
||||
case !in_array($hash, hash_algos()):
|
||||
$i = 1;
|
||||
$hmac = new Hash();
|
||||
$hmac->setHash($hash);
|
||||
$hmac->setKey($password);
|
||||
while (strlen($key) < $dkLen) {
|
||||
$hmac = new Hash();
|
||||
$hmac->setHash($hash);
|
||||
$hmac->setKey($password);
|
||||
$f = $u = $hmac->hash($salt . pack('N', $i++));
|
||||
for ($j = 2; $j <= $count; ++$j) {
|
||||
$u = $hmac->hash($u);
|
||||
|
@ -707,7 +721,7 @@ abstract class Base
|
|||
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);
|
||||
$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);
|
||||
|
@ -767,16 +781,6 @@ abstract class Base
|
|||
$iv = substr($ciphertext, -$this->block_size);
|
||||
}
|
||||
|
||||
return $ciphertext;
|
||||
case self::MODE_CFB8:
|
||||
$ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->encryptIV);
|
||||
if ($this->continuousBuffer) {
|
||||
if (($len = strlen($ciphertext)) >= $this->block_size) {
|
||||
$this->encryptIV = substr($ciphertext, -$this->block_size);
|
||||
} else {
|
||||
$this->encryptIV = substr($this->encryptIV, $len - $this->block_size) . substr($ciphertext, -$len);
|
||||
}
|
||||
}
|
||||
return $ciphertext;
|
||||
case self::MODE_OFB:
|
||||
return $this->_openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
|
||||
|
@ -789,7 +793,7 @@ abstract class Base
|
|||
$this->changed = false;
|
||||
}
|
||||
if ($this->enchanged) {
|
||||
@mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
|
||||
mcrypt_generic_init($this->enmcrypt, $this->key, $this->_getIV($this->encryptIV));
|
||||
$this->enchanged = false;
|
||||
}
|
||||
|
||||
|
@ -822,15 +826,15 @@ abstract class 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;
|
||||
|
@ -839,7 +843,7 @@ abstract class 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;
|
||||
|
@ -849,10 +853,10 @@ abstract class Base
|
|||
return $ciphertext;
|
||||
}
|
||||
|
||||
$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->_getIV($this->encryptIV));
|
||||
}
|
||||
|
||||
return $ciphertext;
|
||||
|
@ -957,24 +961,6 @@ abstract class Base
|
|||
$pos = $len;
|
||||
}
|
||||
break;
|
||||
case self::MODE_CFB8:
|
||||
$ciphertext = '';
|
||||
$len = strlen($plaintext);
|
||||
$iv = $this->encryptIV;
|
||||
|
||||
for ($i = 0; $i < $len; ++$i) {
|
||||
$ciphertext .= ($c = $plaintext[$i] ^ $this->_encryptBlock($iv));
|
||||
$iv = substr($iv, 1) . $c;
|
||||
}
|
||||
|
||||
if ($this->continuousBuffer) {
|
||||
if ($len >= $block_size) {
|
||||
$this->encryptIV = substr($ciphertext, -$block_size);
|
||||
} else {
|
||||
$this->encryptIV = substr($this->encryptIV, $len - $block_size) . substr($ciphertext, -$len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case self::MODE_OFB:
|
||||
$xor = $this->encryptIV;
|
||||
if (strlen($buffer['xor'])) {
|
||||
|
@ -1019,14 +1005,13 @@ abstract class Base
|
|||
* @access public
|
||||
* @param string $ciphertext
|
||||
* @return string $plaintext
|
||||
* @throws \LengthException if we're inside a block cipher and the ciphertext length is not a multiple of the block size
|
||||
* @internal Could, but not must, extend by the child Crypt_* class
|
||||
*/
|
||||
function decrypt($ciphertext)
|
||||
{
|
||||
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->paddable && strlen($ciphertext) % $this->block_size) {
|
||||
throw new \LengthException('The ciphertext length (' . strlen($ciphertext) . ') needs to be a multiple of the block size (' . $this->block_size . ')');
|
||||
}
|
||||
|
||||
if ($this->engine === self::ENGINE_OPENSSL) {
|
||||
|
@ -1040,14 +1025,14 @@ abstract class Base
|
|||
break;
|
||||
case self::MODE_ECB:
|
||||
if (!defined('OPENSSL_RAW_DATA')) {
|
||||
$ciphertext.= @openssl_encrypt('', $this->cipher_name_openssl_ecb, $this->key, true);
|
||||
$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);
|
||||
$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;
|
||||
|
@ -1105,16 +1090,6 @@ abstract class Base
|
|||
$iv = substr($ciphertext, -$this->block_size);
|
||||
}
|
||||
break;
|
||||
case self::MODE_CFB8:
|
||||
$plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->decryptIV);
|
||||
if ($this->continuousBuffer) {
|
||||
if (($len = strlen($ciphertext)) >= $this->block_size) {
|
||||
$this->decryptIV = substr($ciphertext, -$this->block_size);
|
||||
} else {
|
||||
$this->decryptIV = substr($this->decryptIV, $len - $this->block_size) . substr($ciphertext, -$len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case self::MODE_OFB:
|
||||
$plaintext = $this->_openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer);
|
||||
}
|
||||
|
@ -1129,7 +1104,7 @@ abstract class Base
|
|||
$this->changed = false;
|
||||
}
|
||||
if ($this->dechanged) {
|
||||
@mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
|
||||
mcrypt_generic_init($this->demcrypt, $this->key, $this->_getIV($this->decryptIV));
|
||||
$this->dechanged = false;
|
||||
}
|
||||
|
||||
|
@ -1157,12 +1132,12 @@ abstract class 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;
|
||||
|
@ -1171,10 +1146,10 @@ abstract class Base
|
|||
return $plaintext;
|
||||
}
|
||||
|
||||
$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->_getIV($this->decryptIV));
|
||||
}
|
||||
|
||||
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
|
||||
|
@ -1278,24 +1253,6 @@ abstract class Base
|
|||
$pos = $len;
|
||||
}
|
||||
break;
|
||||
case self::MODE_CFB8:
|
||||
$plaintext = '';
|
||||
$len = strlen($ciphertext);
|
||||
$iv = $this->decryptIV;
|
||||
|
||||
for ($i = 0; $i < $len; ++$i) {
|
||||
$plaintext .= $ciphertext[$i] ^ $this->_encryptBlock($iv);
|
||||
$iv = substr($iv, 1) . $ciphertext[$i];
|
||||
}
|
||||
|
||||
if ($this->continuousBuffer) {
|
||||
if ($len >= $block_size) {
|
||||
$this->decryptIV = substr($ciphertext, -$block_size);
|
||||
} else {
|
||||
$this->decryptIV = substr($this->decryptIV, $len - $block_size) . substr($ciphertext, -$len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case self::MODE_OFB:
|
||||
$xor = $this->decryptIV;
|
||||
if (strlen($buffer['xor'])) {
|
||||
|
@ -1329,13 +1286,29 @@ abstract class Base
|
|||
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the IV
|
||||
*
|
||||
* mcrypt requires an IV even if ECB is used
|
||||
*
|
||||
* @see self::encrypt()
|
||||
* @see self::decrypt()
|
||||
* @param string $iv
|
||||
* @return string
|
||||
* @access private
|
||||
*/
|
||||
function _getIV($iv)
|
||||
{
|
||||
return $this->mode == self::MODE_ECB ? str_repeat("\0", $this->block_size) : $iv;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* function will emulate CTR with ECB when necesary.
|
||||
*
|
||||
* @see self::encrypt()
|
||||
* @see self::decrypt()
|
||||
|
@ -1358,7 +1331,7 @@ abstract class Base
|
|||
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 = 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;
|
||||
}
|
||||
|
@ -1369,7 +1342,7 @@ abstract class Base
|
|||
} 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 = 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;
|
||||
|
@ -1413,7 +1386,7 @@ abstract class Base
|
|||
}
|
||||
if ($this->continuousBuffer) {
|
||||
if (!defined('OPENSSL_RAW_DATA')) {
|
||||
$encryptIV.= @openssl_encrypt('', $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
|
||||
$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) {
|
||||
|
@ -1496,8 +1469,6 @@ abstract class Base
|
|||
return 'ctr';
|
||||
case self::MODE_CFB:
|
||||
return 'cfb';
|
||||
case self::MODE_CFB8:
|
||||
return 'cfb8';
|
||||
case self::MODE_OFB:
|
||||
return 'ofb';
|
||||
}
|
||||
|
@ -1656,7 +1627,7 @@ abstract class Base
|
|||
case self::ENGINE_MCRYPT:
|
||||
return $this->cipher_name_mcrypt &&
|
||||
extension_loaded('mcrypt') &&
|
||||
in_array($this->cipher_name_mcrypt, @mcrypt_list_algorithms());
|
||||
in_array($this->cipher_name_mcrypt, mcrypt_list_algorithms());
|
||||
case self::ENGINE_INTERNAL:
|
||||
return true;
|
||||
}
|
||||
|
@ -1735,13 +1706,13 @@ abstract class Base
|
|||
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);
|
||||
mcrypt_module_close($this->enmcrypt);
|
||||
mcrypt_module_close($this->demcrypt);
|
||||
$this->enmcrypt = null;
|
||||
$this->demcrypt = null;
|
||||
|
||||
if ($this->ecb) {
|
||||
@mcrypt_module_close($this->ecb);
|
||||
mcrypt_module_close($this->ecb);
|
||||
$this->ecb = null;
|
||||
}
|
||||
}
|
||||
|
@ -1851,24 +1822,23 @@ abstract class Base
|
|||
self::MODE_ECB => MCRYPT_MODE_ECB,
|
||||
self::MODE_CBC => MCRYPT_MODE_CBC,
|
||||
self::MODE_CFB => 'ncfb',
|
||||
self::MODE_CFB8 => MCRYPT_MODE_CFB,
|
||||
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 == self::MODE_CFB) {
|
||||
$this->ecb = @mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
|
||||
$this->ecb = mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
|
||||
}
|
||||
} // else should mcrypt_generic_deinit be called?
|
||||
|
||||
if ($this->mode == self::MODE_CFB) {
|
||||
@mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size));
|
||||
mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1884,6 +1854,7 @@ abstract class Base
|
|||
*
|
||||
* @see self::_unpad()
|
||||
* @param string $text
|
||||
* @throws \LengthException if padding is disabled and the plaintext's length is not a multiple of the block size
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
|
@ -1895,8 +1866,7 @@ abstract class Base
|
|||
if ($length % $this->block_size == 0) {
|
||||
return $text;
|
||||
} else {
|
||||
user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})");
|
||||
$this->padding = true;
|
||||
throw new \LengthException("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size}). Try enabling padding.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1913,6 +1883,7 @@ abstract class Base
|
|||
*
|
||||
* @see self::_pad()
|
||||
* @param string $text
|
||||
* @throws \LengthException if the ciphertext's length is not a multiple of the block size
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
|
@ -1925,7 +1896,7 @@ abstract class Base
|
|||
$length = ord($text[strlen($text) - 1]);
|
||||
|
||||
if (!$length || $length > $this->block_size) {
|
||||
return false;
|
||||
throw new \LengthException("The ciphertext has an invalid padding length ($length) compared to the block size ({$this->block_size})");
|
||||
}
|
||||
|
||||
return substr($text, 0, -$length);
|
||||
|
@ -1938,20 +1909,19 @@ abstract class Base
|
|||
* after disableContinuousBuffer() or on cipher $engine (re)init
|
||||
* ie after setKey() or setIV()
|
||||
*
|
||||
* @access public
|
||||
* @access private
|
||||
* @internal Could, but not must, extend by the child Crypt_* class
|
||||
* @throws \UnexpectedValueException when an IV is required but not defined
|
||||
*/
|
||||
function _clearBuffers()
|
||||
{
|
||||
$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");
|
||||
if ($this->iv === false && !in_array($this->mode, array(self::MODE_STREAM, self::MODE_ECB))) {
|
||||
throw new \UnexpectedValueException('No IV has been defined');
|
||||
}
|
||||
|
||||
$this->encryptIV = $this->decryptIV = $this->iv;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2423,52 +2393,6 @@ abstract class Base
|
|||
$_pos = $_len;
|
||||
}
|
||||
|
||||
return $_plaintext;
|
||||
';
|
||||
break;
|
||||
case self::MODE_CFB8:
|
||||
$encrypt = $init_encrypt . '
|
||||
$_ciphertext = "";
|
||||
$_len = strlen($_text);
|
||||
$_iv = $self->encryptIV;
|
||||
|
||||
for ($_i = 0; $_i < $_len; ++$_i) {
|
||||
$in = $_iv;
|
||||
'.$encrypt_block.'
|
||||
$_ciphertext .= ($_c = $_text[$_i] ^ $in);
|
||||
$_iv = substr($_iv, 1) . $_c;
|
||||
}
|
||||
|
||||
if ($self->continuousBuffer) {
|
||||
if ($_len >= '.$block_size.') {
|
||||
$self->encryptIV = substr($_ciphertext, -'.$block_size.');
|
||||
} else {
|
||||
$self->encryptIV = substr($self->encryptIV, $_len - '.$block_size.') . substr($_ciphertext, -$_len);
|
||||
}
|
||||
}
|
||||
|
||||
return $_ciphertext;
|
||||
';
|
||||
$decrypt = $init_encrypt . '
|
||||
$_plaintext = "";
|
||||
$_len = strlen($_text);
|
||||
$_iv = $self->decryptIV;
|
||||
|
||||
for ($_i = 0; $_i < $_len; ++$_i) {
|
||||
$in = $_iv;
|
||||
'.$encrypt_block.'
|
||||
$_plaintext .= $_text[$_i] ^ $in;
|
||||
$_iv = substr($_iv, 1) . $_text[$_i];
|
||||
}
|
||||
|
||||
if ($self->continuousBuffer) {
|
||||
if ($_len >= '.$block_size.') {
|
||||
$self->decryptIV = substr($_text, -'.$block_size.');
|
||||
} else {
|
||||
$self->decryptIV = substr($self->decryptIV, $_len - '.$block_size.') . substr($_text, -$_len);
|
||||
}
|
||||
}
|
||||
|
||||
return $_plaintext;
|
||||
';
|
||||
break;
|
||||
|
@ -2602,11 +2526,6 @@ abstract class Base
|
|||
}
|
||||
|
||||
// Create the $inline function and return its name as string. Ready to run!
|
||||
if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
|
||||
eval('$func = function ($_action, &$self, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' } };');
|
||||
return $func;
|
||||
}
|
||||
|
||||
return create_function('$_action, &$self, $_text', $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }');
|
||||
}
|
||||
|
||||
|
@ -2618,7 +2537,7 @@ abstract class Base
|
|||
* is stored, classwide (!), here for reusing.
|
||||
*
|
||||
* The string-based index of $function is a classwide
|
||||
* unique value representing, at least, the $mode of
|
||||
* uniqe value representing, at least, the $mode of
|
||||
* operation (or more... depends of the optimizing level)
|
||||
* for which $mode the lambda function was created.
|
||||
*
|
||||
|
@ -2659,50 +2578,10 @@ abstract class Base
|
|||
$len = strlen($bytes);
|
||||
for ($i = 0; $i < $len; $i+=20) {
|
||||
$t = substr($bytes, $i, 20);
|
||||
$hash = pack('H*', sha1($hash));
|
||||
$hash = sha1($hash, true);
|
||||
$result .= $t ^ $hash;
|
||||
}
|
||||
return $result . pack('H*', sha1($hash));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert float to int
|
||||
*
|
||||
* On ARM CPUs converting floats to ints doesn't always work
|
||||
*
|
||||
* @access private
|
||||
* @param string $x
|
||||
* @return int
|
||||
*/
|
||||
function safe_intval($x)
|
||||
{
|
||||
switch (true) {
|
||||
case is_int($x):
|
||||
// PHP 5.3, per http://php.net/releases/5_3_0.php, introduced "more consistent float rounding"
|
||||
case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
|
||||
return $x;
|
||||
}
|
||||
return (fmod($x, 0x80000000) & 0x7FFFFFFF) |
|
||||
((fmod(floor($x / 0x80000000), 2) & 1) << 31);
|
||||
}
|
||||
|
||||
/**
|
||||
* eval()'able string for in-line float to int
|
||||
*
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
function safe_intval_inline()
|
||||
{
|
||||
switch (true) {
|
||||
case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
|
||||
case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
|
||||
return '%s';
|
||||
break;
|
||||
default:
|
||||
$safeint = '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | ';
|
||||
return $safeint . '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))';
|
||||
return $result . sha1($hash, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -283,6 +283,22 @@ class Blowfish extends Base
|
|||
*/
|
||||
var $key_length = 16;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* @param int $mode
|
||||
* @access public
|
||||
* @throws \InvalidArgumentException if an invalid / unsupported mode is provided
|
||||
*/
|
||||
function __construct($mode)
|
||||
{
|
||||
if ($mode == self::MODE_STREAM) {
|
||||
throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode');
|
||||
}
|
||||
|
||||
parent::__construct($mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key length.
|
||||
*
|
||||
|
@ -293,14 +309,12 @@ class Blowfish extends Base
|
|||
*/
|
||||
function setKeyLength($length)
|
||||
{
|
||||
if ($length < 32) {
|
||||
$this->key_length = 4;
|
||||
} elseif ($length > 448) {
|
||||
$this->key_length = 56;
|
||||
} else {
|
||||
$this->key_length = $length >> 3;
|
||||
if ($length < 32 || $length > 448) {
|
||||
throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes between 32 and 448 bits are supported');
|
||||
}
|
||||
|
||||
$this->key_length = $length >> 3;
|
||||
|
||||
parent::setKeyLength($length);
|
||||
}
|
||||
|
||||
|
@ -317,10 +331,7 @@ class Blowfish extends Base
|
|||
function isValidEngine($engine)
|
||||
{
|
||||
if ($engine == self::ENGINE_OPENSSL) {
|
||||
if (version_compare(PHP_VERSION, '5.3.7') < 0 && $this->key_length != 16) {
|
||||
return false;
|
||||
}
|
||||
if ($this->key_length < 16) {
|
||||
if ($this->key_length != 16) {
|
||||
return false;
|
||||
}
|
||||
$this->cipher_name_openssl_ecb = 'bf-ecb';
|
||||
|
@ -408,14 +419,16 @@ class Blowfish extends Base
|
|||
|
||||
for ($i = 0; $i < 16; $i+= 2) {
|
||||
$l^= $p[$i];
|
||||
$r^= $this->safe_intval(($this->safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^
|
||||
$r^= ($sb_0[$l >> 24 & 0xff] +
|
||||
$sb_1[$l >> 16 & 0xff] ^
|
||||
$sb_2[$l >> 8 & 0xff]) +
|
||||
$sb_3[$l & 0xff]);
|
||||
$sb_3[$l & 0xff];
|
||||
|
||||
$r^= $p[$i + 1];
|
||||
$l^= $this->safe_intval(($this->safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^
|
||||
$l^= ($sb_0[$r >> 24 & 0xff] +
|
||||
$sb_1[$r >> 16 & 0xff] ^
|
||||
$sb_2[$r >> 8 & 0xff]) +
|
||||
$sb_3[$r & 0xff]);
|
||||
$sb_3[$r & 0xff];
|
||||
}
|
||||
return pack("N*", $r ^ $p[17], $l ^ $p[16]);
|
||||
}
|
||||
|
@ -441,14 +454,16 @@ class Blowfish extends Base
|
|||
|
||||
for ($i = 17; $i > 2; $i-= 2) {
|
||||
$l^= $p[$i];
|
||||
$r^= $this->safe_intval(($this->safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^
|
||||
$r^= ($sb_0[$l >> 24 & 0xff] +
|
||||
$sb_1[$l >> 16 & 0xff] ^
|
||||
$sb_2[$l >> 8 & 0xff]) +
|
||||
$sb_3[$l & 0xff]);
|
||||
$sb_3[$l & 0xff];
|
||||
|
||||
$r^= $p[$i - 1];
|
||||
$l^= $this->safe_intval(($this->safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^
|
||||
$l^= ($sb_0[$r >> 24 & 0xff] +
|
||||
$sb_1[$r >> 16 & 0xff] ^
|
||||
$sb_2[$r >> 8 & 0xff]) +
|
||||
$sb_3[$r & 0xff]);
|
||||
$sb_3[$r & 0xff];
|
||||
}
|
||||
return pack("N*", $r ^ $p[0], $l ^ $p[1]);
|
||||
}
|
||||
|
@ -474,8 +489,6 @@ class Blowfish extends Base
|
|||
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
|
||||
}
|
||||
|
||||
$safeint = $this->safe_intval_inline();
|
||||
|
||||
if (!isset($lambda_functions[$code_hash])) {
|
||||
switch (true) {
|
||||
case $gen_hi_opt_code:
|
||||
|
@ -511,14 +524,16 @@ class Blowfish extends Base
|
|||
for ($i = 0; $i < 16; $i+= 2) {
|
||||
$encrypt_block.= '
|
||||
$l^= ' . $p[$i] . ';
|
||||
$r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^
|
||||
$r^= ($sb_0[$l >> 24 & 0xff] +
|
||||
$sb_1[$l >> 16 & 0xff] ^
|
||||
$sb_2[$l >> 8 & 0xff]) +
|
||||
$sb_3[$l & 0xff]') . ';
|
||||
$sb_3[$l & 0xff];
|
||||
|
||||
$r^= ' . $p[$i + 1] . ';
|
||||
$l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . ' ^
|
||||
$l^= ($sb_0[$r >> 24 & 0xff] +
|
||||
$sb_1[$r >> 16 & 0xff] ^
|
||||
$sb_2[$r >> 8 & 0xff]) +
|
||||
$sb_3[$r & 0xff]') . ';
|
||||
$sb_3[$r & 0xff];
|
||||
';
|
||||
}
|
||||
$encrypt_block.= '
|
||||
|
@ -538,14 +553,16 @@ class Blowfish extends Base
|
|||
for ($i = 17; $i > 2; $i-= 2) {
|
||||
$decrypt_block.= '
|
||||
$l^= ' . $p[$i] . ';
|
||||
$r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^
|
||||
$r^= ($sb_0[$l >> 24 & 0xff] +
|
||||
$sb_1[$l >> 16 & 0xff] ^
|
||||
$sb_2[$l >> 8 & 0xff]) +
|
||||
$sb_3[$l & 0xff]') . ';
|
||||
$sb_3[$l & 0xff];
|
||||
|
||||
$r^= ' . $p[$i - 1] . ';
|
||||
$l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . ' ^
|
||||
$l^= ($sb_0[$r >> 24 & 0xff] +
|
||||
$sb_1[$r >> 16 & 0xff] ^
|
||||
$sb_2[$r >> 8 & 0xff]) +
|
||||
$sb_3[$r & 0xff]') . ';
|
||||
$sb_3[$r & 0xff];
|
||||
';
|
||||
}
|
||||
|
||||
|
|
|
@ -578,6 +578,22 @@ class DES extends Base
|
|||
0x00000820, 0x00020020, 0x08000000, 0x08020800
|
||||
);
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* @param int $mode
|
||||
* @access public
|
||||
* @throws \InvalidArgumentException if an invalid / unsupported mode is provided
|
||||
*/
|
||||
function __construct($mode)
|
||||
{
|
||||
if ($mode == self::MODE_STREAM) {
|
||||
throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode');
|
||||
}
|
||||
|
||||
parent::__construct($mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for engine validity
|
||||
*
|
||||
|
@ -603,24 +619,18 @@ class DES extends Base
|
|||
/**
|
||||
* Sets the key.
|
||||
*
|
||||
* Keys can be of any length. DES, itself, uses 64-bit keys (eg. strlen($key) == 8), however, we
|
||||
* only use the first eight, if $key has more then eight characters in it, and pad $key with the
|
||||
* null byte if it is less then eight characters long.
|
||||
* Keys must be 64-bits long or 8 bytes long.
|
||||
*
|
||||
* DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
|
||||
*
|
||||
* If the key is not explicitly set, it'll be assumed to be all zero's.
|
||||
*
|
||||
* @see \phpseclib\Crypt\Base::setKey()
|
||||
* @access public
|
||||
* @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_length_max) {
|
||||
$key = substr($key, 0, $this->key_length_max);
|
||||
if (!($this instanceof TripleDES) && strlen($key) != 8) {
|
||||
throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of size 8 are supported');
|
||||
}
|
||||
|
||||
// Sets the key
|
||||
|
@ -1302,7 +1312,7 @@ class DES extends Base
|
|||
// 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 unique hash for our generated code
|
||||
// Generation of a uniqe 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
|
||||
|
@ -1357,8 +1367,8 @@ class DES extends Base
|
|||
$k[self::ENCRYPT][$i] = '$ke[' . $i . ']';
|
||||
$k[self::DECRYPT][$i] = '$kd[' . $i . ']';
|
||||
}
|
||||
$init_encrypt = '$ke = $self->keys[$self::ENCRYPT];';
|
||||
$init_decrypt = '$kd = $self->keys[$self::DECRYPT];';
|
||||
$init_encrypt = '$ke = $self->keys[self::ENCRYPT];';
|
||||
$init_decrypt = '$kd = $self->keys[self::DECRYPT];';
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
687
vendor/phpseclib/phpseclib/phpseclib/Crypt/Hash.php
vendored
687
vendor/phpseclib/phpseclib/phpseclib/Crypt/Hash.php
vendored
|
@ -1,26 +1,19 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
|
||||
* Wrapper around hash() and hash_hmac() functions supporting truncated hashes
|
||||
* such as sha256-96. Any hash algorithm returned by hash_algos() (and
|
||||
* truncated versions thereof) are supported.
|
||||
*
|
||||
* Uses hash() or mhash() if available and an internal implementation, otherwise. Currently supports the following:
|
||||
*
|
||||
* md2, md5, md5-96, sha1, sha1-96, sha256, sha256-96, sha384, and sha512, sha512-96
|
||||
*
|
||||
* 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 version 5
|
||||
*
|
||||
* {@internal The variable names are the same as those in
|
||||
* {@link http://tools.ietf.org/html/rfc2104#section-2 RFC2104}.}}
|
||||
* If {@link self::setKey() setKey()} is called, {@link self::hash() hash()} will
|
||||
* return the HMAC as opposed to the hash.
|
||||
*
|
||||
* Here's a short example of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include 'vendor/autoload.php';
|
||||
*
|
||||
* $hash = new \phpseclib\Crypt\Hash('sha1');
|
||||
* $hash = new \phpseclib\Crypt\Hash('sha512');
|
||||
*
|
||||
* $hash->setKey('abcdefg');
|
||||
*
|
||||
|
@ -31,7 +24,9 @@
|
|||
* @category Crypt
|
||||
* @package Hash
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2007 Jim Wigginton
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @author Andreas Fischer <bantu@phpbb.com>
|
||||
* @copyright 2015 Andreas Fischer
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
@ -39,34 +34,16 @@
|
|||
namespace phpseclib\Crypt;
|
||||
|
||||
use phpseclib\Math\BigInteger;
|
||||
use phpseclib\Exception\UnsupportedAlgorithmException;
|
||||
|
||||
/**
|
||||
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
|
||||
*
|
||||
* @package Hash
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @author Andreas Fischer <bantu@phpbb.com>
|
||||
* @access public
|
||||
*/
|
||||
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
|
||||
*
|
||||
|
@ -76,15 +53,6 @@ class Hash
|
|||
*/
|
||||
var $hashParam;
|
||||
|
||||
/**
|
||||
* Byte-length of compression blocks / key (Internal HMAC)
|
||||
*
|
||||
* @see self::setAlgorithm()
|
||||
* @var int
|
||||
* @access private
|
||||
*/
|
||||
var $b;
|
||||
|
||||
/**
|
||||
* Byte-length of hash output (Internal HMAC)
|
||||
*
|
||||
|
@ -92,7 +60,7 @@ class Hash
|
|||
* @var int
|
||||
* @access private
|
||||
*/
|
||||
var $l = false;
|
||||
var $length;
|
||||
|
||||
/**
|
||||
* Hash Algorithm
|
||||
|
@ -113,18 +81,22 @@ class Hash
|
|||
var $key = false;
|
||||
|
||||
/**
|
||||
* Computed Key
|
||||
* Initial Hash
|
||||
*
|
||||
* @see self::_computeKey()
|
||||
* @var string
|
||||
* Used only for sha512/*
|
||||
*
|
||||
* @see self::_sha512()
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
var $computedKey = false;
|
||||
var $initial = false;
|
||||
|
||||
/**
|
||||
* Outer XOR (Internal HMAC)
|
||||
*
|
||||
* @see self::setKey()
|
||||
* Used only for sha512/*
|
||||
*
|
||||
* @see self::hash()
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
|
@ -133,44 +105,26 @@ class Hash
|
|||
/**
|
||||
* Inner XOR (Internal HMAC)
|
||||
*
|
||||
* @see self::setKey()
|
||||
* Used only for sha512/*
|
||||
*
|
||||
* @see self::hash()
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $ipad;
|
||||
|
||||
/**
|
||||
* Engine
|
||||
*
|
||||
* @see self::setHash()
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $engine;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* @param string $hash
|
||||
* @return \phpseclib\Crypt\Hash
|
||||
* @access public
|
||||
*/
|
||||
function __construct($hash = 'sha1')
|
||||
function __construct($hash = 'sha256')
|
||||
{
|
||||
if (!defined('CRYPT_HASH_MODE')) {
|
||||
switch (true) {
|
||||
case extension_loaded('hash'):
|
||||
define('CRYPT_HASH_MODE', self::MODE_HASH);
|
||||
break;
|
||||
case extension_loaded('mhash'):
|
||||
define('CRYPT_HASH_MODE', self::MODE_MHASH);
|
||||
break;
|
||||
default:
|
||||
define('CRYPT_HASH_MODE', self::MODE_INTERNAL);
|
||||
}
|
||||
}
|
||||
|
||||
$this->setHash($hash);
|
||||
|
||||
$this->ipad = str_repeat(chr(0x36), 128);
|
||||
$this->opad = str_repeat(chr(0x5C), 128);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -184,43 +138,6 @@ class Hash
|
|||
function setKey($key = false)
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->_computeKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-compute the key used by the HMAC
|
||||
*
|
||||
* Quoting http://tools.ietf.org/html/rfc2104#section-2, "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."
|
||||
*
|
||||
* As documented in https://www.reddit.com/r/PHP/comments/9nct2l/symfonypolyfill_hash_pbkdf2_correct_fix_for/
|
||||
* when doing an HMAC multiple times it's faster to compute the hash once instead of computing it during
|
||||
* every call
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
function _computeKey()
|
||||
{
|
||||
if ($this->key === false) {
|
||||
$this->computedKey = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlen($this->key) <= $this->b) {
|
||||
$this->computedKey = $this->key;
|
||||
return;
|
||||
}
|
||||
|
||||
switch ($this->engine) {
|
||||
case self::MODE_MHASH:
|
||||
$this->computedKey = mhash($this->hash, $this->key);
|
||||
break;
|
||||
case self::MODE_HASH:
|
||||
$this->computedKey = hash($this->hash, $this->key, true);
|
||||
break;
|
||||
case self::MODE_INTERNAL:
|
||||
$this->computedKey = call_user_func($this->hash, $this->key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -246,119 +163,77 @@ class Hash
|
|||
{
|
||||
$this->hashParam = $hash = strtolower($hash);
|
||||
switch ($hash) {
|
||||
case 'md2-96':
|
||||
case 'md5-96':
|
||||
case 'sha1-96':
|
||||
case 'sha256-96':
|
||||
case 'sha512-96':
|
||||
case 'sha512/224-96':
|
||||
case 'sha512/256-96':
|
||||
$hash = substr($hash, 0, -3);
|
||||
$this->l = 12; // 96 / 8 = 12
|
||||
$this->length = 12; // 96 / 8 = 12
|
||||
break;
|
||||
case 'md2':
|
||||
case 'md5':
|
||||
$this->l = 16;
|
||||
$this->length = 16;
|
||||
break;
|
||||
case 'sha1':
|
||||
$this->l = 20;
|
||||
$this->length = 20;
|
||||
break;
|
||||
case 'sha256':
|
||||
$this->l = 32;
|
||||
break;
|
||||
case 'sha384':
|
||||
$this->l = 48;
|
||||
break;
|
||||
case 'sha512':
|
||||
$this->l = 64;
|
||||
}
|
||||
|
||||
switch ($hash) {
|
||||
case 'md2-96':
|
||||
case 'md2':
|
||||
$this->b = 16;
|
||||
case 'md5-96':
|
||||
case 'sha1-96':
|
||||
case 'sha224-96':
|
||||
case 'sha256-96':
|
||||
case 'md2':
|
||||
case 'md5':
|
||||
case 'sha1':
|
||||
case 'sha224':
|
||||
case 'sha256':
|
||||
$this->b = 64;
|
||||
break;
|
||||
default:
|
||||
$this->b = 128;
|
||||
}
|
||||
|
||||
switch ($hash) {
|
||||
case 'md2':
|
||||
$this->engine = CRYPT_HASH_MODE == self::MODE_HASH && in_array('md2', hash_algos()) ?
|
||||
self::MODE_HASH : self::MODE_INTERNAL;
|
||||
break;
|
||||
case 'sha384':
|
||||
case 'sha512':
|
||||
$this->engine = CRYPT_HASH_MODE == self::MODE_MHASH ? self::MODE_INTERNAL : CRYPT_HASH_MODE;
|
||||
break;
|
||||
default:
|
||||
$this->engine = CRYPT_HASH_MODE;
|
||||
}
|
||||
|
||||
switch ($this->engine) {
|
||||
case self::MODE_MHASH:
|
||||
switch ($hash) {
|
||||
case 'md5':
|
||||
$this->hash = MHASH_MD5;
|
||||
break;
|
||||
case 'sha256':
|
||||
$this->hash = MHASH_SHA256;
|
||||
break;
|
||||
case 'sha1':
|
||||
default:
|
||||
$this->hash = MHASH_SHA1;
|
||||
}
|
||||
$this->_computeKey(self::MODE_MHASH);
|
||||
return;
|
||||
case self::MODE_HASH:
|
||||
switch ($hash) {
|
||||
case 'md5':
|
||||
$this->hash = 'md5';
|
||||
return;
|
||||
case 'md2':
|
||||
case 'sha256':
|
||||
case 'sha384':
|
||||
case 'sha512':
|
||||
$this->hash = $hash;
|
||||
return;
|
||||
case 'sha1':
|
||||
default:
|
||||
$this->hash = 'sha1';
|
||||
}
|
||||
$this->_computeKey(self::MODE_HASH);
|
||||
return;
|
||||
}
|
||||
|
||||
switch ($hash) {
|
||||
case 'md2':
|
||||
$this->hash = array($this, '_md2');
|
||||
break;
|
||||
case 'md5':
|
||||
$this->hash = array($this, '_md5');
|
||||
case 'sha512/224':
|
||||
$this->length = 28;
|
||||
break;
|
||||
case 'sha256':
|
||||
$this->hash = array($this, '_sha256');
|
||||
case 'sha512/256':
|
||||
$this->length = 32;
|
||||
break;
|
||||
case 'sha384':
|
||||
case 'sha512':
|
||||
$this->hash = array($this, '_sha512');
|
||||
$this->length = 48;
|
||||
break;
|
||||
case 'sha512':
|
||||
$this->length = 64;
|
||||
break;
|
||||
case 'sha1':
|
||||
default:
|
||||
$this->hash = array($this, '_sha1');
|
||||
// see if the hash isn't "officially" supported see if it can
|
||||
// be "unofficially" supported and calculate the length
|
||||
// accordingly.
|
||||
if (in_array($hash, hash_algos())) {
|
||||
$this->length = strlen(hash($hash, '', true));
|
||||
break;
|
||||
}
|
||||
// if the hash algorithm doens't exist maybe it's a truncated
|
||||
// hash, e.g. whirlpool-12 or some such.
|
||||
if (preg_match('#(-\d+)$#', $hash, $matches)) {
|
||||
$hash = substr($hash, 0, -strlen($matches[1]));
|
||||
if (in_array($hash, hash_algos())) {
|
||||
$this->length = abs($matches[1]) >> 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
throw new UnsupportedAlgorithmException(
|
||||
"$hash is not a supported algorithm"
|
||||
);
|
||||
}
|
||||
|
||||
$this->ipad = str_repeat(chr(0x36), $this->b);
|
||||
$this->opad = str_repeat(chr(0x5C), $this->b);
|
||||
if ($hash == 'sha512/224' || $hash == 'sha512/256') {
|
||||
// from http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf#page=24
|
||||
$this->initial = $hash == 'sha512/256' ?
|
||||
array(
|
||||
'22312194FC2BF72C', '9F555FA3C84C64C2', '2393B86B6F53B151', '963877195940EABD',
|
||||
'96283EE2A88EFFE3', 'BE5E1E2553863992', '2B0199FC2C85B8AA', '0EB72DDC81C52CA2'
|
||||
) :
|
||||
array(
|
||||
'8C3D37C819544DA2', '73E1996689DCD4D6', '1DFAB7AE32FF9C82', '679DD514582F9FCF',
|
||||
'0F6D2B697BD44DA8', '77E36F7304C48942', '3F9D85A86A1D36C8', '1112E6AD91D692A1'
|
||||
);
|
||||
for ($i = 0; $i < 8; $i++) {
|
||||
$this->initial[$i] = new BigInteger($this->initial[$i], 16);
|
||||
$this->initial[$i]->setPrecision(64);
|
||||
}
|
||||
}
|
||||
|
||||
$this->_computeKey(self::MODE_INTERNAL);
|
||||
$this->hash = $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -370,37 +245,35 @@ class Hash
|
|||
*/
|
||||
function hash($text)
|
||||
{
|
||||
if (!empty($this->key) || is_string($this->key)) {
|
||||
switch ($this->engine) {
|
||||
case self::MODE_MHASH:
|
||||
$output = mhash($this->hash, $text, $this->computedKey);
|
||||
break;
|
||||
case self::MODE_HASH:
|
||||
$output = hash_hmac($this->hash, $text, $this->computedKey, true);
|
||||
break;
|
||||
case self::MODE_INTERNAL:
|
||||
$key = str_pad($this->computedKey, $this->b, chr(0)); // step 1
|
||||
$temp = $this->ipad ^ $key; // step 2
|
||||
$temp .= $text; // step 3
|
||||
$temp = call_user_func($this->hash, $temp); // step 4
|
||||
$output = $this->opad ^ $key; // step 5
|
||||
$output.= $temp; // step 6
|
||||
$output = call_user_func($this->hash, $output); // step 7
|
||||
}
|
||||
} else {
|
||||
switch ($this->engine) {
|
||||
case self::MODE_MHASH:
|
||||
$output = mhash($this->hash, $text);
|
||||
break;
|
||||
case self::MODE_HASH:
|
||||
$output = hash($this->hash, $text, true);
|
||||
break;
|
||||
case self::MODE_INTERNAL:
|
||||
$output = call_user_func($this->hash, $text);
|
||||
}
|
||||
}
|
||||
switch ($this->hash) {
|
||||
case 'sha512/224':
|
||||
case 'sha512/256':
|
||||
if (empty($this->key) || !is_string($this->key)) {
|
||||
return substr(self::_sha512($text, $this->initial), 0, $this->length);
|
||||
}
|
||||
/* "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."
|
||||
|
||||
return substr($output, 0, $this->l);
|
||||
-- http://tools.ietf.org/html/rfc2104#section-2 */
|
||||
$key = strlen($this->key) > $this->b ? self::_sha512($this->key, $this->initial) : $this->key;
|
||||
|
||||
$key = str_pad($this->key, 128, chr(0)); // step 1
|
||||
$temp = $this->ipad ^ $this->key; // step 2
|
||||
$temp .= $text; // step 3
|
||||
$temp = self::_sha512($temp, $this->initial); // step 4
|
||||
$output = $this->opad ^ $this->key; // step 5
|
||||
$output.= $temp; // step 6
|
||||
$output = self::_sha512($output, $this->initial); // step 7
|
||||
|
||||
return substr($output, 0, $this->length);
|
||||
}
|
||||
$output = !empty($this->key) || is_string($this->key) ?
|
||||
hash_hmac($this->hash, $text, $this->key, true) :
|
||||
hash($this->hash, $text, true);
|
||||
|
||||
return strlen($output) > $this->length
|
||||
? substr($output, 0, $this->length)
|
||||
: $output;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -411,243 +284,20 @@ class Hash
|
|||
*/
|
||||
function getLength()
|
||||
{
|
||||
return $this->l;
|
||||
return $this->length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for MD5
|
||||
* Pure-PHP implementation of SHA512
|
||||
*
|
||||
* @access private
|
||||
* @param string $m
|
||||
*/
|
||||
function _md5($m)
|
||||
static function _sha512($m, $hash)
|
||||
{
|
||||
return pack('H*', md5($m));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for SHA1
|
||||
*
|
||||
* @access private
|
||||
* @param string $m
|
||||
*/
|
||||
function _sha1($m)
|
||||
{
|
||||
return pack('H*', sha1($m));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pure-PHP implementation of MD2
|
||||
*
|
||||
* See {@link http://tools.ietf.org/html/rfc1319 RFC1319}.
|
||||
*
|
||||
* @access private
|
||||
* @param string $m
|
||||
*/
|
||||
function _md2($m)
|
||||
{
|
||||
static $s = array(
|
||||
41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
|
||||
19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
|
||||
76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
|
||||
138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
|
||||
245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
|
||||
148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
|
||||
39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
|
||||
181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
|
||||
150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
|
||||
112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
|
||||
96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
|
||||
85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
|
||||
234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
|
||||
129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
|
||||
8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
|
||||
203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
|
||||
166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
|
||||
31, 26, 219, 153, 141, 51, 159, 17, 131, 20
|
||||
);
|
||||
|
||||
// Step 1. Append Padding Bytes
|
||||
$pad = 16 - (strlen($m) & 0xF);
|
||||
$m.= str_repeat(chr($pad), $pad);
|
||||
|
||||
$length = strlen($m);
|
||||
|
||||
// Step 2. Append Checksum
|
||||
$c = str_repeat(chr(0), 16);
|
||||
$l = chr(0);
|
||||
for ($i = 0; $i < $length; $i+= 16) {
|
||||
for ($j = 0; $j < 16; $j++) {
|
||||
// RFC1319 incorrectly states that C[j] should be set to S[c xor L]
|
||||
//$c[$j] = chr($s[ord($m[$i + $j] ^ $l)]);
|
||||
// per <http://www.rfc-editor.org/errata_search.php?rfc=1319>, however, C[j] should be set to S[c xor L] xor C[j]
|
||||
$c[$j] = chr($s[ord($m[$i + $j] ^ $l)] ^ ord($c[$j]));
|
||||
$l = $c[$j];
|
||||
}
|
||||
}
|
||||
$m.= $c;
|
||||
|
||||
$length+= 16;
|
||||
|
||||
// Step 3. Initialize MD Buffer
|
||||
$x = str_repeat(chr(0), 48);
|
||||
|
||||
// Step 4. Process Message in 16-Byte Blocks
|
||||
for ($i = 0; $i < $length; $i+= 16) {
|
||||
for ($j = 0; $j < 16; $j++) {
|
||||
$x[$j + 16] = $m[$i + $j];
|
||||
$x[$j + 32] = $x[$j + 16] ^ $x[$j];
|
||||
}
|
||||
$t = chr(0);
|
||||
for ($j = 0; $j < 18; $j++) {
|
||||
for ($k = 0; $k < 48; $k++) {
|
||||
$x[$k] = $t = $x[$k] ^ chr($s[ord($t)]);
|
||||
//$t = $x[$k] = $x[$k] ^ chr($s[ord($t)]);
|
||||
}
|
||||
$t = chr(ord($t) + $j);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5. Output
|
||||
return substr($x, 0, 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pure-PHP implementation of SHA256
|
||||
*
|
||||
* See {@link http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-256_.28a_SHA-2_variant.29_pseudocode SHA-256 (a SHA-2 variant) pseudocode - Wikipedia}.
|
||||
*
|
||||
* @access private
|
||||
* @param string $m
|
||||
*/
|
||||
function _sha256($m)
|
||||
{
|
||||
if (extension_loaded('suhosin')) {
|
||||
return pack('H*', sha256($m));
|
||||
}
|
||||
|
||||
// Initialize variables
|
||||
$hash = array(
|
||||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
||||
);
|
||||
// Initialize table of round constants
|
||||
// (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
|
||||
static $k = array(
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
);
|
||||
|
||||
// Pre-processing
|
||||
$length = strlen($m);
|
||||
// to round to nearest 56 mod 64, we'll add 64 - (length + (64 - 56)) % 64
|
||||
$m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F));
|
||||
$m[$length] = chr(0x80);
|
||||
// we don't support hashing strings 512MB long
|
||||
$m.= pack('N2', 0, $length << 3);
|
||||
|
||||
// Process the message in successive 512-bit chunks
|
||||
$chunks = str_split($m, 64);
|
||||
foreach ($chunks as $chunk) {
|
||||
$w = array();
|
||||
for ($i = 0; $i < 16; $i++) {
|
||||
extract(unpack('Ntemp', $this->_string_shift($chunk, 4)));
|
||||
$w[] = $temp;
|
||||
}
|
||||
|
||||
// Extend the sixteen 32-bit words into sixty-four 32-bit words
|
||||
for ($i = 16; $i < 64; $i++) {
|
||||
// @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
|
||||
list($a, $b, $c, $d, $e, $f, $g, $h) = $hash;
|
||||
|
||||
// Main loop
|
||||
for ($i = 0; $i < 64; $i++) {
|
||||
$s0 = $this->_rightRotate($a, 2) ^
|
||||
$this->_rightRotate($a, 13) ^
|
||||
$this->_rightRotate($a, 22);
|
||||
$maj = ($a & $b) ^
|
||||
($a & $c) ^
|
||||
($b & $c);
|
||||
$t2 = $this->_add($s0, $maj);
|
||||
|
||||
$s1 = $this->_rightRotate($e, 6) ^
|
||||
$this->_rightRotate($e, 11) ^
|
||||
$this->_rightRotate($e, 25);
|
||||
$ch = ($e & $f) ^
|
||||
($this->_not($e) & $g);
|
||||
$t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]);
|
||||
|
||||
$h = $g;
|
||||
$g = $f;
|
||||
$f = $e;
|
||||
$e = $this->_add($d, $t1);
|
||||
$d = $c;
|
||||
$c = $b;
|
||||
$b = $a;
|
||||
$a = $this->_add($t1, $t2);
|
||||
}
|
||||
|
||||
// Add this chunk's hash to result so far
|
||||
$hash = array(
|
||||
$this->_add($hash[0], $a),
|
||||
$this->_add($hash[1], $b),
|
||||
$this->_add($hash[2], $c),
|
||||
$this->_add($hash[3], $d),
|
||||
$this->_add($hash[4], $e),
|
||||
$this->_add($hash[5], $f),
|
||||
$this->_add($hash[6], $g),
|
||||
$this->_add($hash[7], $h)
|
||||
);
|
||||
}
|
||||
|
||||
// Produce the final hash value (big-endian)
|
||||
return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pure-PHP implementation of SHA384 and SHA512
|
||||
*
|
||||
* @access private
|
||||
* @param string $m
|
||||
*/
|
||||
function _sha512($m)
|
||||
{
|
||||
static $init384, $init512, $k;
|
||||
static $k;
|
||||
|
||||
if (!isset($k)) {
|
||||
// Initialize variables
|
||||
$init384 = array( // initial values for SHA384
|
||||
'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939',
|
||||
'67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4'
|
||||
);
|
||||
$init512 = array( // initial values for SHA512
|
||||
'6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1',
|
||||
'510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179'
|
||||
);
|
||||
|
||||
for ($i = 0; $i < 8; $i++) {
|
||||
$init384[$i] = new BigInteger($init384[$i], 16);
|
||||
$init384[$i]->setPrecision(64);
|
||||
$init512[$i] = new BigInteger($init512[$i], 16);
|
||||
$init512[$i]->setPrecision(64);
|
||||
}
|
||||
|
||||
// Initialize table of round constants
|
||||
// (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
|
||||
$k = array(
|
||||
|
@ -678,8 +328,6 @@ class Hash
|
|||
}
|
||||
}
|
||||
|
||||
$hash = $this->l == 48 ? $init384 : $init512;
|
||||
|
||||
// Pre-processing
|
||||
$length = strlen($m);
|
||||
// to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128
|
||||
|
@ -693,7 +341,7 @@ class Hash
|
|||
foreach ($chunks as $chunk) {
|
||||
$w = array();
|
||||
for ($i = 0; $i < 16; $i++) {
|
||||
$temp = new BigInteger($this->_string_shift($chunk, 8), 256);
|
||||
$temp = new BigInteger(self::_string_shift($chunk, 8), 256);
|
||||
$temp->setPrecision(64);
|
||||
$w[] = $temp;
|
||||
}
|
||||
|
@ -714,21 +362,21 @@ class Hash
|
|||
);
|
||||
$s1 = $temp[0]->bitwise_xor($temp[1]);
|
||||
$s1 = $s1->bitwise_xor($temp[2]);
|
||||
$w[$i] = $w[$i - 16]->copy();
|
||||
$w[$i] = clone $w[$i - 16];
|
||||
$w[$i] = $w[$i]->add($s0);
|
||||
$w[$i] = $w[$i]->add($w[$i - 7]);
|
||||
$w[$i] = $w[$i]->add($s1);
|
||||
}
|
||||
|
||||
// Initialize hash value for this chunk
|
||||
$a = $hash[0]->copy();
|
||||
$b = $hash[1]->copy();
|
||||
$c = $hash[2]->copy();
|
||||
$d = $hash[3]->copy();
|
||||
$e = $hash[4]->copy();
|
||||
$f = $hash[5]->copy();
|
||||
$g = $hash[6]->copy();
|
||||
$h = $hash[7]->copy();
|
||||
$a = clone $hash[0];
|
||||
$b = clone $hash[1];
|
||||
$c = clone $hash[2];
|
||||
$d = clone $hash[3];
|
||||
$e = clone $hash[4];
|
||||
$f = clone $hash[5];
|
||||
$g = clone $hash[6];
|
||||
$h = clone $hash[7];
|
||||
|
||||
// Main loop
|
||||
for ($i = 0; $i < 80; $i++) {
|
||||
|
@ -765,13 +413,13 @@ class Hash
|
|||
$t1 = $t1->add($k[$i]);
|
||||
$t1 = $t1->add($w[$i]);
|
||||
|
||||
$h = $g->copy();
|
||||
$g = $f->copy();
|
||||
$f = $e->copy();
|
||||
$h = clone $g;
|
||||
$g = clone $f;
|
||||
$f = clone $e;
|
||||
$e = $d->add($t1);
|
||||
$d = $c->copy();
|
||||
$c = $b->copy();
|
||||
$b = $a->copy();
|
||||
$d = clone $c;
|
||||
$c = clone $b;
|
||||
$b = clone $a;
|
||||
$a = $t1->add($t2);
|
||||
}
|
||||
|
||||
|
@ -791,90 +439,11 @@ class Hash
|
|||
// Produce the final hash value (big-endian)
|
||||
// (\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) {
|
||||
$temp.= $hash[6]->toBytes() . $hash[7]->toBytes();
|
||||
}
|
||||
$hash[4]->toBytes() . $hash[5]->toBytes() . $hash[6]->toBytes() . $hash[7]->toBytes();
|
||||
|
||||
return $temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Right Rotate
|
||||
*
|
||||
* @access private
|
||||
* @param int $int
|
||||
* @param int $amt
|
||||
* @see self::_sha256()
|
||||
* @return int
|
||||
*/
|
||||
function _rightRotate($int, $amt)
|
||||
{
|
||||
$invamt = 32 - $amt;
|
||||
$mask = (1 << $invamt) - 1;
|
||||
return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Right Shift
|
||||
*
|
||||
* @access private
|
||||
* @param int $int
|
||||
* @param int $amt
|
||||
* @see self::_sha256()
|
||||
* @return int
|
||||
*/
|
||||
function _rightShift($int, $amt)
|
||||
{
|
||||
$mask = (1 << (32 - $amt)) - 1;
|
||||
return ($int >> $amt) & $mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not
|
||||
*
|
||||
* @access private
|
||||
* @param int $int
|
||||
* @see self::_sha256()
|
||||
* @return int
|
||||
*/
|
||||
function _not($int)
|
||||
{
|
||||
return ~$int & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add
|
||||
*
|
||||
* _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the
|
||||
* possibility of overflow exists, care has to be taken. BigInteger could be used but this should be faster.
|
||||
*
|
||||
* @param int $...
|
||||
* @return int
|
||||
* @see self::_sha256()
|
||||
* @access private
|
||||
*/
|
||||
function _add()
|
||||
{
|
||||
static $mod;
|
||||
if (!isset($mod)) {
|
||||
$mod = pow(2, 32);
|
||||
}
|
||||
|
||||
$result = 0;
|
||||
$arguments = func_get_args();
|
||||
foreach ($arguments as $argument) {
|
||||
$result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument;
|
||||
}
|
||||
|
||||
if ((php_uname('m') & "\xDF\xDF\xDF") != 'ARM') {
|
||||
return fmod($result, $mod);
|
||||
}
|
||||
|
||||
return (fmod($result, 0x80000000) & 0x7FFFFFFF) |
|
||||
((fmod(floor($result / 0x80000000), 2) & 1) << 31);
|
||||
}
|
||||
|
||||
/**
|
||||
* String Shift
|
||||
*
|
||||
|
@ -885,7 +454,7 @@ class Hash
|
|||
* @return string
|
||||
* @access private
|
||||
*/
|
||||
function _string_shift(&$string, $index = 1)
|
||||
static function _string_shift(&$string, $index = 1)
|
||||
{
|
||||
$substr = substr($string, 0, $index);
|
||||
$string = substr($string, $index);
|
||||
|
|
|
@ -259,6 +259,22 @@ class RC2 extends Base
|
|||
0x70, 0x02, 0xC2, 0x1E, 0xB8, 0x0A, 0xFC, 0xE6
|
||||
);
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* @param int $mode
|
||||
* @access public
|
||||
* @throws \InvalidArgumentException if an invalid / unsupported mode is provided
|
||||
*/
|
||||
function __construct($mode)
|
||||
{
|
||||
if ($mode == self::MODE_STREAM) {
|
||||
throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode');
|
||||
}
|
||||
|
||||
parent::__construct($mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for engine validity
|
||||
*
|
||||
|
@ -292,19 +308,15 @@ class RC2 extends Base
|
|||
*
|
||||
* @access public
|
||||
* @param int $length in bits
|
||||
* @throws \LengthException if the key length isn't supported
|
||||
*/
|
||||
function setKeyLength($length)
|
||||
{
|
||||
if ($length < 8) {
|
||||
$this->default_key_length = 1;
|
||||
} elseif ($length > 1024) {
|
||||
$this->default_key_length = 128;
|
||||
} else {
|
||||
$this->default_key_length = $length;
|
||||
if ($length < 8 || $length > 1024) {
|
||||
throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 1024 bits, inclusive, are supported');
|
||||
}
|
||||
$this->current_key_length = $this->default_key_length;
|
||||
|
||||
parent::setKeyLength($length);
|
||||
$this->default_key_length = $this->current_key_length = $length;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -333,16 +345,20 @@ class RC2 extends Base
|
|||
* @access public
|
||||
* @param string $key
|
||||
* @param int $t1 optional Effective key length in bits.
|
||||
* @throws \LengthException if the key length isn't supported
|
||||
*/
|
||||
function setKey($key, $t1 = 0)
|
||||
function setKey($key, $t1 = false)
|
||||
{
|
||||
$this->orig_key = $key;
|
||||
|
||||
if ($t1 <= 0) {
|
||||
if ($t1 === false) {
|
||||
$t1 = $this->default_key_length;
|
||||
} elseif ($t1 > 1024) {
|
||||
$t1 = 1024;
|
||||
}
|
||||
|
||||
if ($t1 < 1 || $t1 > 1024) {
|
||||
throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 1024 bits, inclusive, are supported');
|
||||
}
|
||||
|
||||
$this->current_key_length = $t1;
|
||||
// Key byte count should be 1..128.
|
||||
$key = strlen($key) ? substr($key, 0, 128) : "\x00";
|
||||
|
@ -565,7 +581,7 @@ class RC2 extends Base
|
|||
// (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);
|
||||
|
||||
// Generation of a unique hash for our generated code
|
||||
// Generation of a uniqe 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);
|
||||
|
|
|
@ -107,7 +107,7 @@ class RC4 extends Base
|
|||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $key;
|
||||
var $key = "\0";
|
||||
|
||||
/**
|
||||
* The Key Stream for decryption and encryption
|
||||
|
@ -121,8 +121,6 @@ class RC4 extends Base
|
|||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* Determines whether or not the mcrypt extension should be used.
|
||||
*
|
||||
* @see \phpseclib\Crypt\Base::__construct()
|
||||
* @return \phpseclib\Crypt\RC4
|
||||
* @access public
|
||||
|
@ -144,10 +142,8 @@ class RC4 extends Base
|
|||
*/
|
||||
function isValidEngine($engine)
|
||||
{
|
||||
if ($engine == Base::ENGINE_OPENSSL) {
|
||||
if (version_compare(PHP_VERSION, '5.3.7') >= 0) {
|
||||
$this->cipher_name_openssl = 'rc4-40';
|
||||
} else {
|
||||
switch ($engine) {
|
||||
case Base::ENGINE_OPENSSL:
|
||||
switch (strlen($this->key)) {
|
||||
case 5:
|
||||
$this->cipher_name_openssl = 'rc4-40';
|
||||
|
@ -161,33 +157,20 @@ class RC4 extends Base
|
|||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return parent::isValidEngine($engine);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy function.
|
||||
* RC4 does not use an IV
|
||||
*
|
||||
* Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1].
|
||||
* If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before
|
||||
* calling setKey().
|
||||
*
|
||||
* [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol,
|
||||
* the IV's are relatively easy to predict, an attack described by
|
||||
* {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir}
|
||||
* can be used to quickly guess at the rest of the key. The following links elaborate:
|
||||
*
|
||||
* {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
|
||||
* {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack}
|
||||
*
|
||||
* @param string $iv
|
||||
* @see self::setKey()
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function setIV($iv)
|
||||
function usesIV()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -197,20 +180,38 @@ class RC4 extends Base
|
|||
*
|
||||
* @access public
|
||||
* @param int $length
|
||||
* @throws \LengthException if the key length is invalid
|
||||
*/
|
||||
function setKeyLength($length)
|
||||
{
|
||||
if ($length < 8) {
|
||||
$this->key_length = 1;
|
||||
} elseif ($length > 2048) {
|
||||
$this->key_length = 256;
|
||||
} else {
|
||||
$this->key_length = $length >> 3;
|
||||
if ($length < 8 || $length > 2048) {
|
||||
throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 256 bytes are supported');
|
||||
}
|
||||
|
||||
$this->key_length = $length >> 3;
|
||||
|
||||
parent::setKeyLength($length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key length
|
||||
*
|
||||
* Keys can be between 1 and 256 bytes long.
|
||||
*
|
||||
* @access public
|
||||
* @param int $length
|
||||
* @throws \LengthException if the key length is invalid
|
||||
*/
|
||||
function setKey($key)
|
||||
{
|
||||
$length = strlen($key);
|
||||
if ($length < 1 || $length > 256) {
|
||||
throw new \LengthException('Key size of ' . $length . ' bytes is not supported by RC4. Keys must be between 1 and 256 bytes long');
|
||||
}
|
||||
|
||||
parent::setKey($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a message.
|
||||
*
|
||||
|
|
2183
vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php
vendored
2183
vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php
vendored
File diff suppressed because it is too large
Load Diff
|
@ -41,72 +41,22 @@ class Random
|
|||
* eg. for RSA key generation.
|
||||
*
|
||||
* @param int $length
|
||||
* @throws \RuntimeException if a symmetric cipher is needed but not loaded
|
||||
* @return string
|
||||
*/
|
||||
static function string($length)
|
||||
{
|
||||
if (!$length) {
|
||||
return '';
|
||||
}
|
||||
|
||||
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 (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,
|
||||
// to quote <http://php.net/ChangeLog-5.php#5.3.4>, "possible blocking behavior". as of 5.3.4
|
||||
// openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both
|
||||
// call php_win32_get_random_bytes():
|
||||
//
|
||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/openssl/openssl.c#L5008
|
||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1392
|
||||
//
|
||||
// php_win32_get_random_bytes() is defined thusly:
|
||||
//
|
||||
// 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 (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
|
||||
return openssl_random_pseudo_bytes($length);
|
||||
}
|
||||
} else {
|
||||
// method 1. the fastest
|
||||
if (extension_loaded('openssl')) {
|
||||
return openssl_random_pseudo_bytes($length);
|
||||
}
|
||||
// method 2
|
||||
static $fp = true;
|
||||
if ($fp === true) {
|
||||
// warning's will be output unles the error suppression operator is used. errors such as
|
||||
// "open_basedir restriction in effect", "Permission denied", "No such file or directory", etc.
|
||||
$fp = @fopen('/dev/urandom', 'rb');
|
||||
}
|
||||
if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource()
|
||||
return fread($fp, $length);
|
||||
}
|
||||
// method 3. pretty much does the same thing as method 2 per the following url:
|
||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391
|
||||
// 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 (extension_loaded('mcrypt')) {
|
||||
return @mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
|
||||
}
|
||||
try {
|
||||
return \random_bytes($length);
|
||||
} catch (\Exception $e) {
|
||||
// random_compat will throw an Exception, which in PHP 5 does not implement Throwable
|
||||
} 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.
|
||||
}
|
||||
// at this point we have no choice but to use a pure-PHP CSPRNG
|
||||
|
||||
|
@ -143,15 +93,14 @@ class Random
|
|||
session_cache_limiter('');
|
||||
session_start();
|
||||
|
||||
$v = $seed = $_SESSION['seed'] = pack('H*', sha1(
|
||||
(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)
|
||||
));
|
||||
$v = (isset($_SERVER) ? self::safe_serialize($_SERVER) : '') .
|
||||
(isset($_POST) ? self::safe_serialize($_POST) : '') .
|
||||
(isset($_GET) ? self::safe_serialize($_GET) : '') .
|
||||
(isset($_COOKIE) ? self::safe_serialize($_COOKIE) : '') .
|
||||
self::safe_serialize($GLOBALS) .
|
||||
self::safe_serialize($_SESSION) .
|
||||
self::safe_serialize($_OLD_SESSION);
|
||||
$v = $seed = $_SESSION['seed'] = sha1($v, true);
|
||||
if (!isset($_SESSION['count'])) {
|
||||
$_SESSION['count'] = 0;
|
||||
}
|
||||
|
@ -182,8 +131,8 @@ class Random
|
|||
// http://tools.ietf.org/html/rfc4253#section-7.2
|
||||
//
|
||||
// see the is_string($crypto) part for an example of how to expand the keys
|
||||
$key = pack('H*', sha1($seed . 'A'));
|
||||
$iv = pack('H*', sha1($seed . 'C'));
|
||||
$key = sha1($seed . 'A', true);
|
||||
$iv = sha1($seed . 'C', true);
|
||||
|
||||
// ciphers are used as per the nist.gov link below. also, see this link:
|
||||
//
|
||||
|
@ -208,8 +157,7 @@ class Random
|
|||
$crypto = new RC4();
|
||||
break;
|
||||
default:
|
||||
user_error(__CLASS__ . ' requires at least one symmetric cipher be loaded');
|
||||
return false;
|
||||
throw new \RuntimeException(__CLASS__ . ' requires at least one symmetric cipher be loaded');
|
||||
}
|
||||
|
||||
$crypto->setKey($key);
|
||||
|
@ -236,19 +184,16 @@ class Random
|
|||
}
|
||||
return substr($result, 0, $length);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('phpseclib_safe_serialize')) {
|
||||
/**
|
||||
* Safely serialize variables
|
||||
*
|
||||
* 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.
|
||||
* If a class has a private __sleep() it'll emit a warning
|
||||
*
|
||||
* @param mixed $arr
|
||||
* @access public
|
||||
*/
|
||||
function phpseclib_safe_serialize(&$arr)
|
||||
function safe_serialize(&$arr)
|
||||
{
|
||||
if (is_object($arr)) {
|
||||
return '';
|
||||
|
@ -265,7 +210,7 @@ if (!function_exists('phpseclib_safe_serialize')) {
|
|||
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]);
|
||||
$safearr[$key] = self::safe_serialize($arr[$key]);
|
||||
}
|
||||
}
|
||||
unset($arr['__phpseclib_marker']);
|
||||
|
|
|
@ -168,11 +168,26 @@ class Rijndael extends Base
|
|||
*/
|
||||
var $kl;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* @param int $mode
|
||||
* @access public
|
||||
* @throws \InvalidArgumentException if an invalid / unsupported mode is provided
|
||||
*/
|
||||
function __construct($mode)
|
||||
{
|
||||
if ($mode == self::MODE_STREAM) {
|
||||
throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode');
|
||||
}
|
||||
|
||||
parent::__construct($mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Valid key lengths are 128, 160, 192, 224, and 256.
|
||||
*
|
||||
* Note: phpseclib extends Rijndael (and AES) for using 160- and 224-bit keys but they are officially not defined
|
||||
* and the most (if not all) implementations are not able using 160/224-bit keys but round/pad them up to
|
||||
|
@ -186,49 +201,75 @@ class Rijndael extends Base
|
|||
* This results then in slower encryption.
|
||||
*
|
||||
* @access public
|
||||
* @throws \LengthException if the key length is invalid
|
||||
* @param int $length
|
||||
*/
|
||||
function setKeyLength($length)
|
||||
{
|
||||
switch (true) {
|
||||
case $length <= 128:
|
||||
$this->key_length = 16;
|
||||
break;
|
||||
case $length <= 160:
|
||||
$this->key_length = 20;
|
||||
break;
|
||||
case $length <= 192:
|
||||
$this->key_length = 24;
|
||||
break;
|
||||
case $length <= 224:
|
||||
$this->key_length = 28;
|
||||
switch ($length) {
|
||||
case 128:
|
||||
case 160:
|
||||
case 192:
|
||||
case 224:
|
||||
case 256:
|
||||
$this->key_length = $length >> 3;
|
||||
break;
|
||||
default:
|
||||
$this->key_length = 32;
|
||||
throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128, 160, 192, 224 or 256 bits are supported');
|
||||
}
|
||||
|
||||
parent::setKeyLength($length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key.
|
||||
*
|
||||
* Rijndael supports five different key lengths
|
||||
*
|
||||
* @see setKeyLength()
|
||||
* @access public
|
||||
* @param string $key
|
||||
* @throws \LengthException if the key length isn't supported
|
||||
*/
|
||||
function setKey($key)
|
||||
{
|
||||
switch (strlen($key)) {
|
||||
case 16:
|
||||
case 20:
|
||||
case 24:
|
||||
case 28:
|
||||
case 32:
|
||||
break;
|
||||
default:
|
||||
throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 20, 24, 28 or 32 are supported');
|
||||
}
|
||||
|
||||
parent::setKey($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the block length
|
||||
*
|
||||
* Valid block 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.
|
||||
* Valid block lengths are 128, 160, 192, 224, and 256.
|
||||
*
|
||||
* @access public
|
||||
* @param int $length
|
||||
*/
|
||||
function setBlockLength($length)
|
||||
{
|
||||
$length >>= 5;
|
||||
if ($length > 8) {
|
||||
$length = 8;
|
||||
} elseif ($length < 4) {
|
||||
$length = 4;
|
||||
switch ($length) {
|
||||
case 128:
|
||||
case 160:
|
||||
case 192:
|
||||
case 224:
|
||||
case 256:
|
||||
break;
|
||||
default:
|
||||
throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128, 160, 192, 224 or 256 bits are supported');
|
||||
}
|
||||
$this->Nb = $length;
|
||||
$this->block_size = $length << 2;
|
||||
|
||||
$this->Nb = $length >> 5;
|
||||
$this->block_size = $length >> 3;
|
||||
$this->changed = true;
|
||||
$this->_setEngine();
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ class TripleDES extends DES
|
|||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* Determines whether or not the mcrypt extension should be used.
|
||||
* Determines whether or not the mcrypt or OpenSSL extensions should be used.
|
||||
*
|
||||
* $mode could be:
|
||||
*
|
||||
|
@ -142,16 +142,14 @@ class TripleDES extends DES
|
|||
*
|
||||
* - \phpseclib\Crypt\Base::MODE_OFB
|
||||
*
|
||||
* - \phpseclib\Crypt\TripleDES::MODE_3CBC
|
||||
*
|
||||
* If not explicitly set, \phpseclib\Crypt\Base::MODE_CBC will be used.
|
||||
* - \phpseclib\Crypt\TripleDES::MODE_3CB
|
||||
*
|
||||
* @see \phpseclib\Crypt\DES::__construct()
|
||||
* @see \phpseclib\Crypt\Base::__construct()
|
||||
* @param int $mode
|
||||
* @access public
|
||||
*/
|
||||
function __construct($mode = Base::MODE_CBC)
|
||||
function __construct($mode)
|
||||
{
|
||||
switch ($mode) {
|
||||
// In case of self::MODE_3CBC, we init as CRYPT_DES_MODE_CBC
|
||||
|
@ -200,10 +198,9 @@ class TripleDES extends DES
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the initialization vector. (optional)
|
||||
* Sets the initialization vector.
|
||||
*
|
||||
* 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.
|
||||
* SetIV is not required when \phpseclib\Crypt\Base::MODE_ECB is being used.
|
||||
*
|
||||
* @see \phpseclib\Crypt\Base::setIV()
|
||||
* @access public
|
||||
|
@ -222,24 +219,23 @@ class TripleDES extends DES
|
|||
/**
|
||||
* Sets the key length.
|
||||
*
|
||||
* Valid key lengths are 64, 128 and 192
|
||||
* Valid key lengths are 128 and 192 bits.
|
||||
*
|
||||
* If you want to use a 64-bit key use DES.php
|
||||
*
|
||||
* @see \phpseclib\Crypt\Base:setKeyLength()
|
||||
* @access public
|
||||
* @throws \LengthException if the key length is invalid
|
||||
* @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;
|
||||
switch ($length) {
|
||||
case 128:
|
||||
case 192:
|
||||
break;
|
||||
default:
|
||||
$this->key_length = 24;
|
||||
throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128 or 192 bits are supported');
|
||||
}
|
||||
|
||||
parent::setKeyLength($length);
|
||||
|
@ -248,36 +244,38 @@ class TripleDES extends DES
|
|||
/**
|
||||
* Sets the key.
|
||||
*
|
||||
* Keys can be of any length. Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or
|
||||
* 192-bit (eg. strlen($key) == 24) keys. This function pads and truncates $key as appropriate.
|
||||
* Triple DES can use 128-bit (eg. strlen($key) == 16) or 192-bit (eg. strlen($key) == 24) keys.
|
||||
*
|
||||
* DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
|
||||
*
|
||||
* If the key is not explicitly set, it'll be assumed to be all null bytes.
|
||||
*
|
||||
* @access public
|
||||
* @see \phpseclib\Crypt\DES::setKey()
|
||||
* @see \phpseclib\Crypt\Base::setKey()
|
||||
* @throws \LengthException if the key length is invalid
|
||||
* @param string $key
|
||||
*/
|
||||
function setKey($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);
|
||||
} else {
|
||||
$key = str_pad($key, 8, chr(0));
|
||||
if ($this->explicit_key_length !== false && strlen($key) != $this->explicit_key_length) {
|
||||
throw new \LengthException('Key length has already been set to ' . $this->explicit_key_length . ' bytes and this key is ' . strlen($key) . ' bytes');
|
||||
}
|
||||
parent::setKey($key);
|
||||
|
||||
// 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.
|
||||
if ($this->mode_3cbc && $length > 8) {
|
||||
switch (strlen($key)) {
|
||||
case 16:
|
||||
$key.= substr($key, 0, 8);
|
||||
case 24:
|
||||
break;
|
||||
default:
|
||||
throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16 or 24 are supported');
|
||||
}
|
||||
|
||||
// copied from Base::setKey()
|
||||
$this->key = $key;
|
||||
$this->key_length = strlen($key);
|
||||
$this->changed = true;
|
||||
$this->_setEngine();
|
||||
|
||||
if ($this->mode_3cbc) {
|
||||
$this->des[0]->setKey(substr($key, 0, 8));
|
||||
$this->des[1]->setKey(substr($key, 8, 8));
|
||||
$this->des[2]->setKey(substr($key, 16, 8));
|
||||
|
|
|
@ -368,6 +368,22 @@ class Twofish extends Base
|
|||
*/
|
||||
var $key_length = 16;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* @param int $mode
|
||||
* @access public
|
||||
* @throws \InvalidArgumentException if an invalid / unsupported mode is provided
|
||||
*/
|
||||
function __construct($mode)
|
||||
{
|
||||
if ($mode == self::MODE_STREAM) {
|
||||
throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode');
|
||||
}
|
||||
|
||||
parent::__construct($mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key length.
|
||||
*
|
||||
|
@ -378,20 +394,42 @@ class Twofish extends Base
|
|||
*/
|
||||
function setKeyLength($length)
|
||||
{
|
||||
switch (true) {
|
||||
case $length <= 128:
|
||||
$this->key_length = 16;
|
||||
break;
|
||||
case $length <= 192:
|
||||
$this->key_length = 24;
|
||||
switch ($length) {
|
||||
case 128:
|
||||
case 192:
|
||||
case 256:
|
||||
break;
|
||||
default:
|
||||
$this->key_length = 32;
|
||||
throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported');
|
||||
}
|
||||
|
||||
parent::setKeyLength($length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key.
|
||||
*
|
||||
* Rijndael supports five different key lengths
|
||||
*
|
||||
* @see setKeyLength()
|
||||
* @access public
|
||||
* @param string $key
|
||||
* @throws \LengthException if the key length isn't supported
|
||||
*/
|
||||
function setKey($key)
|
||||
{
|
||||
switch (strlen($key)) {
|
||||
case 16:
|
||||
case 24:
|
||||
case 32:
|
||||
break;
|
||||
default:
|
||||
throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported');
|
||||
}
|
||||
|
||||
parent::setKey($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the key (expansion)
|
||||
*
|
||||
|
@ -432,10 +470,8 @@ class Twofish extends Base
|
|||
$m2[$q1[$q0[$j] ^ $key[15]] ^ $key[7]] ^
|
||||
$m3[$q1[$q1[$j] ^ $key[16]] ^ $key[8]];
|
||||
$B = ($B << 8) | ($B >> 24 & 0xff);
|
||||
$A = $this->safe_intval($A + $B);
|
||||
$K[] = $A;
|
||||
$A = $this->safe_intval($A + $B);
|
||||
$K[] = ($A << 9 | $A >> 23 & 0x1ff);
|
||||
$K[] = $A+= $B;
|
||||
$K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
|
||||
}
|
||||
for ($i = 0; $i < 256; ++$i) {
|
||||
$S0[$i] = $m0[$q0[$q0[$i] ^ $s4] ^ $s0];
|
||||
|
@ -458,10 +494,8 @@ class Twofish extends Base
|
|||
$m2[$q1[$q0[$q0[$j] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
|
||||
$m3[$q1[$q1[$q0[$j] ^ $key[24]] ^ $key[16]] ^ $key[8]];
|
||||
$B = ($B << 8) | ($B >> 24 & 0xff);
|
||||
$A = $this->safe_intval($A + $B);
|
||||
$K[] = $A;
|
||||
$A = $this->safe_intval($A + $B);
|
||||
$K[] = ($A << 9 | $A >> 23 & 0x1ff);
|
||||
$K[] = $A+= $B;
|
||||
$K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
|
||||
}
|
||||
for ($i = 0; $i < 256; ++$i) {
|
||||
$S0[$i] = $m0[$q0[$q0[$q1[$i] ^ $s8] ^ $s4] ^ $s0];
|
||||
|
@ -485,10 +519,8 @@ class Twofish extends Base
|
|||
$m2[$q1[$q0[$q0[$q0[$j] ^ $key[31]] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
|
||||
$m3[$q1[$q1[$q0[$q1[$j] ^ $key[32]] ^ $key[24]] ^ $key[16]] ^ $key[8]];
|
||||
$B = ($B << 8) | ($B >> 24 & 0xff);
|
||||
$A = $this->safe_intval($A + $B);
|
||||
$K[] = $A;
|
||||
$A = $this->safe_intval($A + $B);
|
||||
$K[] = ($A << 9 | $A >> 23 & 0x1ff);
|
||||
$K[] = $A+= $B;
|
||||
$K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
|
||||
}
|
||||
for ($i = 0; $i < 256; ++$i) {
|
||||
$S0[$i] = $m0[$q0[$q0[$q1[$q1[$i] ^ $sc] ^ $s8] ^ $s4] ^ $s0];
|
||||
|
@ -584,9 +616,9 @@ class Twofish extends Base
|
|||
$S1[ $R1 & 0xff] ^
|
||||
$S2[($R1 >> 8) & 0xff] ^
|
||||
$S3[($R1 >> 16) & 0xff];
|
||||
$R2^= $this->safe_intval($t0 + $t1 + $K[++$ki]);
|
||||
$R2^= $t0 + $t1 + $K[++$ki];
|
||||
$R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
|
||||
$R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ $this->safe_intval($t0 + ($t1 << 1) + $K[++$ki]);
|
||||
$R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
|
||||
|
||||
$t0 = $S0[ $R2 & 0xff] ^
|
||||
$S1[($R2 >> 8) & 0xff] ^
|
||||
|
@ -596,9 +628,9 @@ class Twofish extends Base
|
|||
$S1[ $R3 & 0xff] ^
|
||||
$S2[($R3 >> 8) & 0xff] ^
|
||||
$S3[($R3 >> 16) & 0xff];
|
||||
$R0^= $this->safe_intval($t0 + $t1 + $K[++$ki]);
|
||||
$R0^= ($t0 + $t1 + $K[++$ki]);
|
||||
$R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
|
||||
$R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ $this->safe_intval($t0 + ($t1 << 1) + $K[++$ki]);
|
||||
$R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
|
||||
}
|
||||
|
||||
// @codingStandardsIgnoreStart
|
||||
|
@ -640,9 +672,9 @@ class Twofish extends Base
|
|||
$S1[$R1 & 0xff] ^
|
||||
$S2[$R1 >> 8 & 0xff] ^
|
||||
$S3[$R1 >> 16 & 0xff];
|
||||
$R3^= $this->safe_intval($t0 + ($t1 << 1) + $K[--$ki]);
|
||||
$R3^= $t0 + ($t1 << 1) + $K[--$ki];
|
||||
$R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
|
||||
$R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ $this->safe_intval($t0 + $t1 + $K[--$ki]);
|
||||
$R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + $K[--$ki]);
|
||||
|
||||
$t0 = $S0[$R2 & 0xff] ^
|
||||
$S1[$R2 >> 8 & 0xff] ^
|
||||
|
@ -652,9 +684,9 @@ class Twofish extends Base
|
|||
$S1[$R3 & 0xff] ^
|
||||
$S2[$R3 >> 8 & 0xff] ^
|
||||
$S3[$R3 >> 16 & 0xff];
|
||||
$R1^= $this->safe_intval($t0 + ($t1 << 1) + $K[--$ki]);
|
||||
$R1^= $t0 + ($t1 << 1) + $K[--$ki];
|
||||
$R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
|
||||
$R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ $this->safe_intval($t0 + $t1 + $K[--$ki]);
|
||||
$R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + $K[--$ki]);
|
||||
}
|
||||
|
||||
// @codingStandardsIgnoreStart
|
||||
|
@ -679,14 +711,12 @@ class Twofish extends Base
|
|||
// (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);
|
||||
|
||||
// Generation of a unique hash for our generated code
|
||||
// Generation of a uniqe 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);
|
||||
}
|
||||
|
||||
$safeint = $this->safe_intval_inline();
|
||||
|
||||
if (!isset($lambda_functions[$code_hash])) {
|
||||
switch (true) {
|
||||
case $gen_hi_opt_code:
|
||||
|
@ -735,9 +765,9 @@ class Twofish extends Base
|
|||
$S1[ $R1 & 0xff] ^
|
||||
$S2[($R1 >> 8) & 0xff] ^
|
||||
$S3[($R1 >> 16) & 0xff];
|
||||
$R2^= ' . sprintf($safeint, '$t0 + $t1 + ' . $K[++$ki]) . ';
|
||||
$R2^= ($t0 + $t1 + '.$K[++$ki].');
|
||||
$R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
|
||||
$R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ' . sprintf($safeint, '($t0 + ($t1 << 1) + ' . $K[++$ki] . ')') . ';
|
||||
$R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
|
||||
|
||||
$t0 = $S0[ $R2 & 0xff] ^
|
||||
$S1[($R2 >> 8) & 0xff] ^
|
||||
|
@ -747,16 +777,16 @@ class Twofish extends Base
|
|||
$S1[ $R3 & 0xff] ^
|
||||
$S2[($R3 >> 8) & 0xff] ^
|
||||
$S3[($R3 >> 16) & 0xff];
|
||||
$R0^= ' . sprintf($safeint, '($t0 + $t1 + ' . $K[++$ki] . ')') . ';
|
||||
$R0^= ($t0 + $t1 + '.$K[++$ki].');
|
||||
$R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
|
||||
$R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ' . sprintf($safeint, '($t0 + ($t1 << 1) + ' . $K[++$ki] . ')') . ';
|
||||
$R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
|
||||
';
|
||||
}
|
||||
$encrypt_block.= '
|
||||
$in = pack("V4", ' . $K[4] . ' ^ $R2,
|
||||
' . $K[5] . ' ^ $R3,
|
||||
' . $K[6] . ' ^ $R0,
|
||||
' . $K[7] . ' ^ $R1);
|
||||
$in = pack("V4", '.$K[4].' ^ $R2,
|
||||
'.$K[5].' ^ $R3,
|
||||
'.$K[6].' ^ $R0,
|
||||
'.$K[7].' ^ $R1);
|
||||
';
|
||||
|
||||
// Generating decrypt code:
|
||||
|
@ -777,9 +807,9 @@ class Twofish extends Base
|
|||
$S1[$R1 & 0xff] ^
|
||||
$S2[$R1 >> 8 & 0xff] ^
|
||||
$S3[$R1 >> 16 & 0xff];
|
||||
$R3^= ' . sprintf($safeint, '$t0 + ($t1 << 1) + ' . $K[--$ki]) . ';
|
||||
$R3^= $t0 + ($t1 << 1) + '.$K[--$ki].';
|
||||
$R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
|
||||
$R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ' . sprintf($safeint, '($t0 + $t1 + '.$K[--$ki] . ')') . ';
|
||||
$R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
|
||||
|
||||
$t0 = $S0[$R2 & 0xff] ^
|
||||
$S1[$R2 >> 8 & 0xff] ^
|
||||
|
@ -789,16 +819,16 @@ class Twofish extends Base
|
|||
$S1[$R3 & 0xff] ^
|
||||
$S2[$R3 >> 8 & 0xff] ^
|
||||
$S3[$R3 >> 16 & 0xff];
|
||||
$R1^= ' . sprintf($safeint, '$t0 + ($t1 << 1) + ' . $K[--$ki]) . ';
|
||||
$R1^= $t0 + ($t1 << 1) + '.$K[--$ki].';
|
||||
$R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
|
||||
$R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ' . sprintf($safeint, '($t0 + $t1 + '.$K[--$ki] . ')') . ';
|
||||
$R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
|
||||
';
|
||||
}
|
||||
$decrypt_block.= '
|
||||
$in = pack("V4", ' . $K[0] . ' ^ $R2,
|
||||
' . $K[1] . ' ^ $R3,
|
||||
' . $K[2] . ' ^ $R0,
|
||||
' . $K[3] . ' ^ $R1);
|
||||
$in = pack("V4", '.$K[0].' ^ $R2,
|
||||
'.$K[1].' ^ $R3,
|
||||
'.$K[2].' ^ $R0,
|
||||
'.$K[3].' ^ $R1);
|
||||
';
|
||||
|
||||
$lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
|
||||
|
|
|
@ -305,9 +305,6 @@ class ANSI
|
|||
case preg_match('#\x1B\[(\d+)D#', $this->ansi, $match): // Move cursor left n lines
|
||||
$this->old_x = $this->x;
|
||||
$this->x-= $match[1];
|
||||
if ($this->x < 0) {
|
||||
$this->x = 0;
|
||||
}
|
||||
break;
|
||||
case preg_match('#\x1B\[(\d+);(\d+)r#', $this->ansi, $match): // Set top and bottom lines of a window
|
||||
break;
|
||||
|
@ -419,7 +416,7 @@ class ANSI
|
|||
|
||||
if ($this->x > $this->max_x) {
|
||||
$this->x = 0;
|
||||
$this->_newLine();
|
||||
$this->y++;
|
||||
} else {
|
||||
$this->x++;
|
||||
}
|
||||
|
|
295
vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php
vendored
295
vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php
vendored
|
@ -23,10 +23,9 @@
|
|||
|
||||
namespace phpseclib\File;
|
||||
|
||||
use ParagonIE\ConstantTime\Base64;
|
||||
use phpseclib\File\ASN1\Element;
|
||||
use phpseclib\Math\BigInteger;
|
||||
use DateTime;
|
||||
use DateTimeZone;
|
||||
|
||||
/**
|
||||
* Pure-PHP ASN.1 Parser
|
||||
|
@ -226,15 +225,14 @@ class ASN1
|
|||
*
|
||||
* @param string $encoded
|
||||
* @param int $start
|
||||
* @param int $encoded_pos
|
||||
* @return array
|
||||
* @access private
|
||||
*/
|
||||
function _decode_ber($encoded, $start = 0, $encoded_pos = 0)
|
||||
function _decode_ber($encoded, $start = 0)
|
||||
{
|
||||
$current = array('start' => $start);
|
||||
|
||||
$type = ord($encoded[$encoded_pos++]);
|
||||
$type = ord($this->_string_shift($encoded));
|
||||
$start++;
|
||||
|
||||
$constructed = ($type >> 5) & 1;
|
||||
|
@ -244,27 +242,25 @@ class ASN1
|
|||
$tag = 0;
|
||||
// process septets (since the eighth bit is ignored, it's not an octet)
|
||||
do {
|
||||
$temp = ord($encoded[$encoded_pos++]);
|
||||
$loop = $temp >> 7;
|
||||
$loop = ord($encoded[0]) >> 7;
|
||||
$tag <<= 7;
|
||||
$tag |= $temp & 0x7F;
|
||||
$tag |= ord($this->_string_shift($encoded)) & 0x7F;
|
||||
$start++;
|
||||
} while ($loop);
|
||||
}
|
||||
|
||||
// Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13
|
||||
$length = ord($encoded[$encoded_pos++]);
|
||||
$length = ord($this->_string_shift($encoded));
|
||||
$start++;
|
||||
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) - $encoded_pos;
|
||||
$length = strlen($encoded);
|
||||
} 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 = substr($encoded, $encoded_pos, $length);
|
||||
$encoded_pos += $length;
|
||||
$temp = $this->_string_shift($encoded, $length);
|
||||
// tags of indefinte length don't really have a header length; this length includes the tag
|
||||
$current+= array('headerlength' => $length + 2);
|
||||
$start+= $length;
|
||||
|
@ -273,12 +269,11 @@ class ASN1
|
|||
$current+= array('headerlength' => 2);
|
||||
}
|
||||
|
||||
if ($length > (strlen($encoded) - $encoded_pos)) {
|
||||
if ($length > strlen($encoded)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$content = substr($encoded, $encoded_pos, $length);
|
||||
$content_pos = 0;
|
||||
$content = $this->_string_shift($encoded, $length);
|
||||
|
||||
// at this point $length can be overwritten. it's only accurate for definite length things as is
|
||||
|
||||
|
@ -308,13 +303,10 @@ class ASN1
|
|||
$newcontent = array();
|
||||
$remainingLength = $length;
|
||||
while ($remainingLength > 0) {
|
||||
$temp = $this->_decode_ber($content, $start, $content_pos);
|
||||
if ($temp === false) {
|
||||
break;
|
||||
}
|
||||
$temp = $this->_decode_ber($content, $start);
|
||||
$length = $temp['length'];
|
||||
// end-of-content octets - see paragraph 8.1.5
|
||||
if (substr($content, $content_pos + $length, 2) == "\0\0") {
|
||||
if (substr($content, $length, 2) == "\0\0") {
|
||||
$length+= 2;
|
||||
$start+= $length;
|
||||
$newcontent[] = $temp;
|
||||
|
@ -323,7 +315,7 @@ class ASN1
|
|||
$start+= $length;
|
||||
$remainingLength-= $length;
|
||||
$newcontent[] = $temp;
|
||||
$content_pos += $length;
|
||||
$this->_string_shift($content, $length);
|
||||
}
|
||||
|
||||
return array(
|
||||
|
@ -347,11 +339,11 @@ class ASN1
|
|||
//if (strlen($content) != 1) {
|
||||
// return false;
|
||||
//}
|
||||
$current['content'] = (bool) ord($content[$content_pos]);
|
||||
$current['content'] = (bool) ord($content[0]);
|
||||
break;
|
||||
case self::TYPE_INTEGER:
|
||||
case self::TYPE_ENUMERATED:
|
||||
$current['content'] = new BigInteger(substr($content, $content_pos), -256);
|
||||
$current['content'] = new BigInteger($content, -256);
|
||||
break;
|
||||
case self::TYPE_REAL: // not currently supported
|
||||
return false;
|
||||
|
@ -360,13 +352,10 @@ class ASN1
|
|||
// the number of unused bits in the final subsequent octet. The number shall be in the range zero to
|
||||
// seven.
|
||||
if (!$constructed) {
|
||||
$current['content'] = substr($content, $content_pos);
|
||||
$current['content'] = $content;
|
||||
} else {
|
||||
$temp = $this->_decode_ber($content, $start, $content_pos);
|
||||
if ($temp === false) {
|
||||
return false;
|
||||
}
|
||||
$length-= (strlen($content) - $content_pos);
|
||||
$temp = $this->_decode_ber($content, $start);
|
||||
$length-= strlen($content);
|
||||
$last = count($temp) - 1;
|
||||
for ($i = 0; $i < $last; $i++) {
|
||||
// all subtags should be bit strings
|
||||
|
@ -384,16 +373,13 @@ class ASN1
|
|||
break;
|
||||
case self::TYPE_OCTET_STRING:
|
||||
if (!$constructed) {
|
||||
$current['content'] = substr($content, $content_pos);
|
||||
$current['content'] = $content;
|
||||
} else {
|
||||
$current['content'] = '';
|
||||
$length = 0;
|
||||
while (substr($content, $content_pos, 2) != "\0\0") {
|
||||
$temp = $this->_decode_ber($content, $length + $start, $content_pos);
|
||||
if ($temp === false) {
|
||||
return false;
|
||||
}
|
||||
$content_pos += $temp['length'];
|
||||
while (substr($content, 0, 2) != "\0\0") {
|
||||
$temp = $this->_decode_ber($content, $length + $start);
|
||||
$this->_string_shift($content, $temp['length']);
|
||||
// all subtags should be octet strings
|
||||
//if ($temp['type'] != self::TYPE_OCTET_STRING) {
|
||||
// return false;
|
||||
|
@ -401,7 +387,7 @@ class ASN1
|
|||
$current['content'].= $temp['content'];
|
||||
$length+= $temp['length'];
|
||||
}
|
||||
if (substr($content, $content_pos, 2) == "\0\0") {
|
||||
if (substr($content, 0, 2) == "\0\0") {
|
||||
$length+= 2; // +2 for the EOC
|
||||
}
|
||||
}
|
||||
|
@ -416,25 +402,37 @@ class ASN1
|
|||
case self::TYPE_SET:
|
||||
$offset = 0;
|
||||
$current['content'] = array();
|
||||
$content_len = strlen($content);
|
||||
while ($content_pos < $content_len) {
|
||||
while (strlen($content)) {
|
||||
// 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, $content_pos, 2) == "\0\0") {
|
||||
if (!isset($current['headerlength']) && substr($content, 0, 2) == "\0\0") {
|
||||
$length = $offset + 2; // +2 for the EOC
|
||||
break 2;
|
||||
}
|
||||
$temp = $this->_decode_ber($content, $start + $offset, $content_pos);
|
||||
if ($temp === false) {
|
||||
return false;
|
||||
}
|
||||
$content_pos += $temp['length'];
|
||||
$temp = $this->_decode_ber($content, $start + $offset);
|
||||
$this->_string_shift($content, $temp['length']);
|
||||
$current['content'][] = $temp;
|
||||
$offset+= $temp['length'];
|
||||
}
|
||||
break;
|
||||
case self::TYPE_OBJECT_IDENTIFIER:
|
||||
$current['content'] = $this->_decodeOID(substr($content, $content_pos));
|
||||
$temp = ord($this->_string_shift($content));
|
||||
$current['content'] = sprintf('%d.%d', floor($temp / 40), $temp % 40);
|
||||
$valuen = 0;
|
||||
// process septets
|
||||
while (strlen($content)) {
|
||||
$temp = ord($this->_string_shift($content));
|
||||
$valuen <<= 7;
|
||||
$valuen |= $temp & 0x7F;
|
||||
if (~$temp & 0x80) {
|
||||
$current['content'].= ".$valuen";
|
||||
$valuen = 0;
|
||||
}
|
||||
}
|
||||
// the eighth bit of the last byte should not be 1
|
||||
//if ($temp >> 7) {
|
||||
// return false;
|
||||
//}
|
||||
break;
|
||||
/* Each character string type shall be encoded as if it had been declared:
|
||||
[UNIVERSAL x] IMPLICIT OCTET STRING
|
||||
|
@ -464,11 +462,11 @@ class ASN1
|
|||
case self::TYPE_UTF8_STRING:
|
||||
// ????
|
||||
case self::TYPE_BMP_STRING:
|
||||
$current['content'] = substr($content, $content_pos);
|
||||
$current['content'] = $content;
|
||||
break;
|
||||
case self::TYPE_UTC_TIME:
|
||||
case self::TYPE_GENERALIZED_TIME:
|
||||
$current['content'] = $this->_decodeTime(substr($content, $content_pos), $tag);
|
||||
$current['content'] = $this->_decodeTime($content, $tag);
|
||||
default:
|
||||
}
|
||||
|
||||
|
@ -500,7 +498,7 @@ class ASN1
|
|||
switch (true) {
|
||||
case $mapping['type'] == self::TYPE_ANY:
|
||||
$intype = $decoded['type'];
|
||||
if (isset($decoded['constant']) || !isset($this->ANYmap[$intype]) || (ord($this->encoded[$decoded['start']]) & 0x20)) {
|
||||
if (isset($decoded['constant']) || !isset($this->ANYmap[$intype]) || ($this->encoded[$decoded['start']] & 0x20)) {
|
||||
return new Element(substr($this->encoded, $decoded['start'], $decoded['length']));
|
||||
}
|
||||
$inmap = $this->ANYmap[$intype];
|
||||
|
@ -578,7 +576,7 @@ class ASN1
|
|||
$childClass = $tempClass = self::CLASS_UNIVERSAL;
|
||||
$constant = null;
|
||||
if (isset($temp['constant'])) {
|
||||
$tempClass = $temp['type'];
|
||||
$tempClass = isset($temp['class']) ? $temp['class'] : self::CLASS_CONTEXT_SPECIFIC;
|
||||
}
|
||||
if (isset($child['class'])) {
|
||||
$childClass = $child['class'];
|
||||
|
@ -641,7 +639,7 @@ class ASN1
|
|||
$temp = $decoded['content'][$i];
|
||||
$tempClass = self::CLASS_UNIVERSAL;
|
||||
if (isset($temp['constant'])) {
|
||||
$tempClass = $temp['type'];
|
||||
$tempClass = isset($temp['class']) ? $temp['class'] : self::CLASS_CONTEXT_SPECIFIC;
|
||||
}
|
||||
|
||||
foreach ($mapping['children'] as $key => $child) {
|
||||
|
@ -705,7 +703,7 @@ class ASN1
|
|||
if (isset($mapping['implicit'])) {
|
||||
$decoded['content'] = $this->_decodeTime($decoded['content'], $decoded['type']);
|
||||
}
|
||||
return $decoded['content'] ? $decoded['content']->format($this->format) : false;
|
||||
return @date($this->format, $decoded['content']);
|
||||
case self::TYPE_BIT_STRING:
|
||||
if (isset($mapping['mapping'])) {
|
||||
$offset = ord($decoded['content'][0]);
|
||||
|
@ -736,7 +734,7 @@ class ASN1
|
|||
return $values;
|
||||
}
|
||||
case self::TYPE_OCTET_STRING:
|
||||
return base64_encode($decoded['content']);
|
||||
return Base64::encode($decoded['content']);
|
||||
case self::TYPE_NULL:
|
||||
return '';
|
||||
case self::TYPE_BOOLEAN:
|
||||
|
@ -796,6 +794,7 @@ class ASN1
|
|||
* @param string $mapping
|
||||
* @param int $idx
|
||||
* @return string
|
||||
* @throws \RuntimeException if the input has an error in it
|
||||
* @access private
|
||||
*/
|
||||
function _encode_der($source, $mapping, $idx = null, $special = array())
|
||||
|
@ -822,10 +821,10 @@ class ASN1
|
|||
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) {
|
||||
|
@ -833,21 +832,11 @@ class 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 (!array_key_exists($key, $source)) {
|
||||
if (!isset($child['optional'])) {
|
||||
|
@ -954,8 +943,7 @@ class ASN1
|
|||
case self::TYPE_GENERALIZED_TIME:
|
||||
$format = $mapping['type'] == self::TYPE_UTC_TIME ? 'y' : 'Y';
|
||||
$format.= 'mdHis';
|
||||
$date = new DateTime($source, new DateTimeZone('GMT'));
|
||||
$value = $date->format($format) . 'Z';
|
||||
$value = @gmdate($format, strtotime($source)) . 'Z';
|
||||
break;
|
||||
case self::TYPE_BIT_STRING:
|
||||
if (isset($mapping['mapping'])) {
|
||||
|
@ -994,10 +982,30 @@ class ASN1
|
|||
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);
|
||||
$value = Base64::decode($source);
|
||||
break;
|
||||
case self::TYPE_OBJECT_IDENTIFIER:
|
||||
$value = $this->_encodeOID($source);
|
||||
$oid = preg_match('#(?:\d+\.)+#', $source) ? $source : array_search($source, $this->oids);
|
||||
if ($oid === false) {
|
||||
throw new \RuntimeException('Invalid OID');
|
||||
return false;
|
||||
}
|
||||
$value = '';
|
||||
$parts = explode('.', $oid);
|
||||
$value = chr(40 * $parts[0] + $parts[1]);
|
||||
for ($i = 2; $i < count($parts); $i++) {
|
||||
$temp = '';
|
||||
if (!$parts[$i]) {
|
||||
$temp = "\0";
|
||||
} else {
|
||||
while ($parts[$i]) {
|
||||
$temp = chr(0x80 | ($parts[$i] & 0x7F)) . $temp;
|
||||
$parts[$i] >>= 7;
|
||||
}
|
||||
$temp[strlen($temp) - 1] = $temp[strlen($temp) - 1] & chr(0x7F);
|
||||
}
|
||||
$value.= $temp;
|
||||
}
|
||||
break;
|
||||
case self::TYPE_ANY:
|
||||
$loc = $this->location;
|
||||
|
@ -1032,7 +1040,7 @@ class ASN1
|
|||
$filters = $filters[$part];
|
||||
}
|
||||
if ($filters === false) {
|
||||
user_error('No filters defined for ' . implode('/', $loc));
|
||||
throw new \RuntimeException('No filters defined for ' . implode('/', $loc));
|
||||
return false;
|
||||
}
|
||||
return $this->_encode_der($source, $filters + $mapping, null, $special);
|
||||
|
@ -1056,7 +1064,7 @@ class ASN1
|
|||
$value = $source ? "\xFF" : "\x00";
|
||||
break;
|
||||
default:
|
||||
user_error('Mapping provides no type definition for ' . implode('/', $this->location));
|
||||
throw new \RuntimeException('Mapping provides no type definition for ' . implode('/', $this->location));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1096,108 +1104,6 @@ class ASN1
|
|||
return pack('Ca*', 0x80 | strlen($temp), $temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* BER-decode the OID
|
||||
*
|
||||
* Called by _decode_ber()
|
||||
*
|
||||
* @access private
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
function _decodeOID($content)
|
||||
{
|
||||
static $eighty;
|
||||
if (!$eighty) {
|
||||
$eighty = new BigInteger(80);
|
||||
}
|
||||
|
||||
$oid = array();
|
||||
$pos = 0;
|
||||
$len = strlen($content);
|
||||
$n = new BigInteger();
|
||||
while ($pos < $len) {
|
||||
$temp = ord($content[$pos++]);
|
||||
$n = $n->bitwise_leftShift(7);
|
||||
$n = $n->bitwise_or(new BigInteger($temp & 0x7F));
|
||||
if (~$temp & 0x80) {
|
||||
$oid[] = $n;
|
||||
$n = new BigInteger();
|
||||
}
|
||||
}
|
||||
$part1 = array_shift($oid);
|
||||
$first = floor(ord($content[0]) / 40);
|
||||
/*
|
||||
"This packing of the first two object identifier components recognizes that only three values are allocated from the root
|
||||
node, and at most 39 subsequent values from nodes reached by X = 0 and X = 1."
|
||||
|
||||
-- https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=22
|
||||
*/
|
||||
if ($first <= 2) { // ie. 0 <= ord($content[0]) < 120 (0x78)
|
||||
array_unshift($oid, ord($content[0]) % 40);
|
||||
array_unshift($oid, $first);
|
||||
} else {
|
||||
array_unshift($oid, $part1->subtract($eighty));
|
||||
array_unshift($oid, 2);
|
||||
}
|
||||
|
||||
return implode('.', $oid);
|
||||
}
|
||||
|
||||
/**
|
||||
* DER-encode the OID
|
||||
*
|
||||
* Called by _encode_der()
|
||||
*
|
||||
* @access private
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
function _encodeOID($source)
|
||||
{
|
||||
static $mask, $zero, $forty;
|
||||
if (!$mask) {
|
||||
$mask = new BigInteger(0x7F);
|
||||
$zero = new BigInteger();
|
||||
$forty = new BigInteger(40);
|
||||
}
|
||||
|
||||
$oid = preg_match('#(?:\d+\.)+#', $source) ? $source : array_search($source, $this->oids);
|
||||
if ($oid === false) {
|
||||
user_error('Invalid OID');
|
||||
return false;
|
||||
}
|
||||
$parts = explode('.', $oid);
|
||||
$part1 = array_shift($parts);
|
||||
$part2 = array_shift($parts);
|
||||
|
||||
$first = new BigInteger($part1);
|
||||
$first = $first->multiply($forty);
|
||||
$first = $first->add(new BigInteger($part2));
|
||||
|
||||
array_unshift($parts, $first->toString());
|
||||
|
||||
$value = '';
|
||||
foreach ($parts as $part) {
|
||||
if (!$part) {
|
||||
$temp = "\0";
|
||||
} else {
|
||||
$temp = '';
|
||||
$part = new BigInteger($part);
|
||||
while (!$part->equals($zero)) {
|
||||
$submask = $part->bitwise_and($mask);
|
||||
$submask->setPrecision(8);
|
||||
$temp = (chr(0x80) | $submask->toBytes()) . $temp;
|
||||
$part = $part->bitwise_rightShift(7);
|
||||
}
|
||||
$temp[strlen($temp) - 1] = $temp[strlen($temp) - 1] & chr(0x7F);
|
||||
}
|
||||
$value.= $temp;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* BER-decode the time
|
||||
*
|
||||
|
@ -1218,32 +1124,33 @@ class ASN1
|
|||
http://tools.ietf.org/html/rfc5280#section-4.1.2.5.2
|
||||
http://www.obj-sys.com/asn1tutorial/node14.html */
|
||||
|
||||
$format = 'YmdHis';
|
||||
$pattern = $tag == self::TYPE_UTC_TIME ?
|
||||
'#(..)(..)(..)(..)(..)(..)(.*)#' :
|
||||
'#(....)(..)(..)(..)(..)(..).*([Z+-].*)$#';
|
||||
|
||||
preg_match($pattern, $content, $matches);
|
||||
|
||||
list(, $year, $month, $day, $hour, $minute, $second, $timezone) = $matches;
|
||||
|
||||
if ($tag == self::TYPE_UTC_TIME) {
|
||||
// https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=28 says "the seconds
|
||||
// element shall always be present" but none-the-less I've seen X509 certs where it isn't and if the
|
||||
// browsers parse it phpseclib ought to too
|
||||
if (preg_match('#^(\d{10})(Z|[+-]\d{4})$#', $content, $matches)) {
|
||||
$content = $matches[1] . '00' . $matches[2];
|
||||
$year = $year >= 50 ? "19$year" : "20$year";
|
||||
}
|
||||
|
||||
if ($timezone == 'Z') {
|
||||
$mktime = 'gmmktime';
|
||||
$timezone = 0;
|
||||
} elseif (preg_match('#([+-])(\d\d)(\d\d)#', $timezone, $matches)) {
|
||||
$mktime = 'gmmktime';
|
||||
$timezone = 60 * $matches[3] + 3600 * $matches[2];
|
||||
if ($matches[1] == '-') {
|
||||
$timezone = -$timezone;
|
||||
}
|
||||
$prefix = substr($content, 0, 2) >= 50 ? '19' : '20';
|
||||
$content = $prefix . $content;
|
||||
} elseif (strpos($content, '.') !== false) {
|
||||
$format.= '.u';
|
||||
} else {
|
||||
$mktime = 'mktime';
|
||||
$timezone = 0;
|
||||
}
|
||||
|
||||
if ($content[strlen($content) - 1] == 'Z') {
|
||||
$content = substr($content, 0, -1) . '+0000';
|
||||
}
|
||||
|
||||
if (strpos($content, '-') !== false || strpos($content, '+') !== false) {
|
||||
$format.= 'O';
|
||||
}
|
||||
|
||||
// error supression isn't necessary as of PHP 7.0:
|
||||
// http://php.net/manual/en/migration70.other-changes.php
|
||||
return @DateTime::createFromFormat($format, $content);
|
||||
return @$mktime($hour, $minute, $second, $month, $day, $year) + $timezone;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
524
vendor/phpseclib/phpseclib/phpseclib/File/X509.php
vendored
524
vendor/phpseclib/phpseclib/phpseclib/File/X509.php
vendored
|
@ -26,13 +26,14 @@
|
|||
|
||||
namespace phpseclib\File;
|
||||
|
||||
use ParagonIE\ConstantTime\Base64;
|
||||
use ParagonIE\ConstantTime\Hex;
|
||||
use phpseclib\Crypt\Hash;
|
||||
use phpseclib\Crypt\Random;
|
||||
use phpseclib\Crypt\RSA;
|
||||
use phpseclib\Exception\UnsupportedAlgorithmException;
|
||||
use phpseclib\File\ASN1\Element;
|
||||
use phpseclib\Math\BigInteger;
|
||||
use DateTime;
|
||||
use DateTimeZone;
|
||||
|
||||
/**
|
||||
* Pure-PHP X.509 Parser
|
||||
|
@ -246,7 +247,7 @@ class X509
|
|||
/**
|
||||
* The signature subject
|
||||
*
|
||||
* There's no guarantee \phpseclib\File\X509 is going to re-encode an X.509 cert in the same way it was originally
|
||||
* There's no guarantee \phpseclib\File\X509 is going to reencode 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
|
||||
|
@ -305,22 +306,6 @@ class X509
|
|||
*/
|
||||
var $challenge;
|
||||
|
||||
/**
|
||||
* Recursion Limit
|
||||
*
|
||||
* @var int
|
||||
* @access private
|
||||
*/
|
||||
static $recur_limit = 5;
|
||||
|
||||
/**
|
||||
* URL fetch flag
|
||||
*
|
||||
* @var bool
|
||||
* @access private
|
||||
*/
|
||||
static $disable_url_fetch = false;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
|
@ -1502,9 +1487,7 @@ class X509
|
|||
|
||||
$this->signatureSubject = substr($cert, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
|
||||
|
||||
if ($this->_isSubArrayValid($x509, 'tbsCertificate/extensions')) {
|
||||
$this->_mapInExtensions($x509, 'tbsCertificate/extensions', $asn1);
|
||||
}
|
||||
$this->_mapInExtensions($x509, 'tbsCertificate/extensions', $asn1);
|
||||
$this->_mapInDNs($x509, 'tbsCertificate/issuer/rdnSequence', $asn1);
|
||||
$this->_mapInDNs($x509, 'tbsCertificate/subject/rdnSequence', $asn1);
|
||||
|
||||
|
@ -1543,7 +1526,7 @@ class X509
|
|||
switch ($algorithm) {
|
||||
case 'rsaEncryption':
|
||||
$cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']
|
||||
= base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $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
|
||||
|
||||
|
@ -1593,7 +1576,7 @@ class X509
|
|||
return $cert;
|
||||
// case self::FORMAT_PEM:
|
||||
default:
|
||||
return "-----BEGIN CERTIFICATE-----\r\n" . chunk_split(base64_encode($cert), 64) . '-----END CERTIFICATE-----';
|
||||
return "-----BEGIN CERTIFICATE-----\r\n" . chunk_split(Base64::encode($cert), 64) . '-----END CERTIFICATE-----';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1608,13 +1591,13 @@ class X509
|
|||
*/
|
||||
function _mapInExtensions(&$root, $path, $asn1)
|
||||
{
|
||||
$extensions = &$this->_subArrayUnchecked($root, $path);
|
||||
$extensions = &$this->_subArray($root, $path);
|
||||
|
||||
if ($extensions) {
|
||||
if (is_array($extensions)) {
|
||||
for ($i = 0; $i < count($extensions); $i++) {
|
||||
$id = $extensions[$i]['extnId'];
|
||||
$value = &$extensions[$i]['extnValue'];
|
||||
$value = base64_decode($value);
|
||||
$value = Base64::decode($value);
|
||||
$decoded = $asn1->decodeBER($value);
|
||||
/* [extnValue] contains the DER encoding of an ASN.1 value
|
||||
corresponding to the extension type identified by extnID */
|
||||
|
@ -1641,7 +1624,7 @@ class X509
|
|||
}
|
||||
}
|
||||
} else {
|
||||
$value = base64_encode($value);
|
||||
$value = Base64::encode($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1702,12 +1685,12 @@ class X509
|
|||
$map = $this->_getMapping($id);
|
||||
if (is_bool($map)) {
|
||||
if (!$map) {
|
||||
user_error($id . ' is not a currently supported extension');
|
||||
//user_error($id . ' is not a currently supported extension');
|
||||
unset($extensions[$i]);
|
||||
}
|
||||
} else {
|
||||
$temp = $asn1->encodeDER($value, $map, array('iPAddress' => array($this, '_encodeIP')));
|
||||
$value = base64_encode($temp);
|
||||
$value = Base64::encode($temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1742,11 +1725,11 @@ class X509
|
|||
if ($mapped !== false) {
|
||||
$values[$j] = $mapped;
|
||||
}
|
||||
if ($id == 'pkcs-9-at-extensionRequest' && $this->_isSubArrayValid($values, $j)) {
|
||||
if ($id == 'pkcs-9-at-extensionRequest') {
|
||||
$this->_mapInExtensions($values, $j, $asn1);
|
||||
}
|
||||
} elseif ($map) {
|
||||
$values[$j] = base64_encode($value);
|
||||
$values[$j] = Base64::encode($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1775,7 +1758,7 @@ class X509
|
|||
$id = $attributes[$i]['type'];
|
||||
$map = $this->_getMapping($id);
|
||||
if ($map === false) {
|
||||
user_error($id . ' is not a currently supported attribute', E_USER_NOTICE);
|
||||
//user_error($id . ' is not a currently supported attribute', E_USER_NOTICE);
|
||||
unset($attributes[$i]);
|
||||
} elseif (is_array($attributes[$i]['value'])) {
|
||||
$values = &$attributes[$i]['value'];
|
||||
|
@ -1925,12 +1908,6 @@ class X509
|
|||
// "SET Secure Electronic Transaction Specification"
|
||||
// http://www.maithean.com/docs/set_bk3.pdf
|
||||
case '2.23.42.7.0': // id-set-hashedRootKey
|
||||
// "Certificate Transparency"
|
||||
// https://tools.ietf.org/html/rfc6962
|
||||
case '1.3.6.1.4.1.11129.2.4.2':
|
||||
// "Qualified Certificate statements"
|
||||
// https://tools.ietf.org/html/rfc3739#section-3.2.6
|
||||
case '1.3.6.1.5.5.7.1.3':
|
||||
return true;
|
||||
|
||||
// CSR attributes
|
||||
|
@ -2051,32 +2028,30 @@ class X509
|
|||
}
|
||||
|
||||
if ($names = $this->getExtension('id-ce-subjectAltName')) {
|
||||
foreach ($names as $name) {
|
||||
foreach ($name as $key => $value) {
|
||||
$value = str_replace(array('.', '*'), array('\.', '[^.]*'), $value);
|
||||
switch ($key) {
|
||||
case 'dNSName':
|
||||
/* From RFC2818 "HTTP over TLS":
|
||||
foreach ($names as $key => $value) {
|
||||
$value = str_replace(array('.', '*'), array('\.', '[^.]*'), $value);
|
||||
switch ($key) {
|
||||
case 'dNSName':
|
||||
/* From RFC2818 "HTTP over TLS":
|
||||
|
||||
If a subjectAltName extension of type dNSName is present, that MUST
|
||||
be used as the identity. Otherwise, the (most specific) Common Name
|
||||
field in the Subject field of the certificate MUST be used. Although
|
||||
the use of the Common Name is existing practice, it is deprecated and
|
||||
Certification Authorities are encouraged to use the dNSName instead. */
|
||||
if (preg_match('#^' . $value . '$#', $components['host'])) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 'iPAddress':
|
||||
/* From RFC2818 "HTTP over TLS":
|
||||
If a subjectAltName extension of type dNSName is present, that MUST
|
||||
be used as the identity. Otherwise, the (most specific) Common Name
|
||||
field in the Subject field of the certificate MUST be used. Although
|
||||
the use of the Common Name is existing practice, it is deprecated and
|
||||
Certification Authorities are encouraged to use the dNSName instead. */
|
||||
if (preg_match('#^' . $value . '$#', $components['host'])) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 'iPAddress':
|
||||
/* From RFC2818 "HTTP over TLS":
|
||||
|
||||
In some cases, the URI is specified as an IP address rather than a
|
||||
hostname. In this case, the iPAddress subjectAltName must be present
|
||||
in the certificate and must exactly match the IP in the URI. */
|
||||
if (preg_match('#(?:\d{1-3}\.){4}#', $components['host'] . '.') && preg_match('#^' . $value . '$#', $components['host'])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
In some cases, the URI is specified as an IP address rather than a
|
||||
hostname. In this case, the iPAddress subjectAltName must be present
|
||||
in the certificate and must exactly match the IP in the URI. */
|
||||
if (preg_match('#(?:\d{1-3}\.){4}#', $components['host'] . '.') && preg_match('#^' . $value . '$#', $components['host'])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -2095,7 +2070,7 @@ class X509
|
|||
*
|
||||
* If $date isn't defined it is assumed to be the current date.
|
||||
*
|
||||
* @param \DateTime|string $date optional
|
||||
* @param int $date optional
|
||||
* @access public
|
||||
*/
|
||||
function validateDate($date = null)
|
||||
|
@ -2105,7 +2080,7 @@ class X509
|
|||
}
|
||||
|
||||
if (!isset($date)) {
|
||||
$date = new DateTime(null, new DateTimeZone(@date_default_timezone_get()));
|
||||
$date = time();
|
||||
}
|
||||
|
||||
$notBefore = $this->currentCert['tbsCertificate']['validity']['notBefore'];
|
||||
|
@ -2114,133 +2089,15 @@ class X509
|
|||
$notAfter = $this->currentCert['tbsCertificate']['validity']['notAfter'];
|
||||
$notAfter = isset($notAfter['generalTime']) ? $notAfter['generalTime'] : $notAfter['utcTime'];
|
||||
|
||||
if (is_string($date)) {
|
||||
$date = new DateTime($date, new DateTimeZone(@date_default_timezone_get()));
|
||||
}
|
||||
|
||||
$notBefore = new DateTime($notBefore, new DateTimeZone(@date_default_timezone_get()));
|
||||
$notAfter = new DateTime($notAfter, new DateTimeZone(@date_default_timezone_get()));
|
||||
|
||||
switch (true) {
|
||||
case $date < $notBefore:
|
||||
case $date > $notAfter:
|
||||
case $date < @strtotime($notBefore):
|
||||
case $date > @strtotime($notAfter):
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a URL
|
||||
*
|
||||
* @param string $url
|
||||
* @access private
|
||||
* @return bool|string
|
||||
*/
|
||||
static function _fetchURL($url)
|
||||
{
|
||||
if (self::$disable_url_fetch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parts = parse_url($url);
|
||||
$data = '';
|
||||
switch ($parts['scheme']) {
|
||||
case 'http':
|
||||
$fsock = @fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80);
|
||||
if (!$fsock) {
|
||||
return false;
|
||||
}
|
||||
fputs($fsock, "GET $parts[path] HTTP/1.0\r\n");
|
||||
fputs($fsock, "Host: $parts[host]\r\n\r\n");
|
||||
$line = fgets($fsock, 1024);
|
||||
if (strlen($line) < 3) {
|
||||
return false;
|
||||
}
|
||||
preg_match('#HTTP/1.\d (\d{3})#', $line, $temp);
|
||||
if ($temp[1] != '200') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// skip the rest of the headers in the http response
|
||||
while (!feof($fsock) && fgets($fsock, 1024) != "\r\n") {
|
||||
}
|
||||
|
||||
while (!feof($fsock)) {
|
||||
$data.= fread($fsock, 1024);
|
||||
}
|
||||
|
||||
break;
|
||||
//case 'ftp':
|
||||
//case 'ldap':
|
||||
//default:
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates an intermediate cert as identified via authority info access extension
|
||||
*
|
||||
* See https://tools.ietf.org/html/rfc4325 for more info
|
||||
*
|
||||
* @param bool $caonly
|
||||
* @param int $count
|
||||
* @access private
|
||||
* @return bool
|
||||
*/
|
||||
function _testForIntermediate($caonly, $count)
|
||||
{
|
||||
$opts = $this->getExtension('id-pe-authorityInfoAccess');
|
||||
if (!is_array($opts)) {
|
||||
return false;
|
||||
}
|
||||
foreach ($opts as $opt) {
|
||||
if ($opt['accessMethod'] == 'id-ad-caIssuers') {
|
||||
// accessLocation is a GeneralName. GeneralName fields support stuff like email addresses, IP addresses, LDAP,
|
||||
// etc, but we're only supporting URI's. URI's and LDAP are the only thing https://tools.ietf.org/html/rfc4325
|
||||
// discusses
|
||||
if (isset($opt['accessLocation']['uniformResourceIdentifier'])) {
|
||||
$url = $opt['accessLocation']['uniformResourceIdentifier'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($url)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$cert = static::_fetchURL($url);
|
||||
if (!is_string($cert)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parent = new static();
|
||||
$parent->CAs = $this->CAs;
|
||||
/*
|
||||
"Conforming applications that support HTTP or FTP for accessing
|
||||
certificates MUST be able to accept .cer files and SHOULD be able
|
||||
to accept .p7c files." -- https://tools.ietf.org/html/rfc4325
|
||||
|
||||
A .p7c file is 'a "certs-only" CMS message as specified in RFC 2797"
|
||||
|
||||
These are currently unsupported
|
||||
*/
|
||||
if (!is_array($parent->loadX509($cert))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$parent->_validateSignatureCountable($caonly, ++$count)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->CAs[] = $parent->currentCert;
|
||||
//$this->loadCA($cert);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a signature
|
||||
*
|
||||
|
@ -2257,30 +2114,11 @@ class X509
|
|||
* @return mixed
|
||||
*/
|
||||
function validateSignature($caonly = true)
|
||||
{
|
||||
return $this->_validateSignatureCountable($caonly, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a signature
|
||||
*
|
||||
* Performs said validation whilst keeping track of how many times validation method is called
|
||||
*
|
||||
* @param bool $caonly
|
||||
* @param int $count
|
||||
* @access private
|
||||
* @return mixed
|
||||
*/
|
||||
function _validateSignatureCountable($caonly, $count)
|
||||
{
|
||||
if (!is_array($this->currentCert) || !isset($this->signatureSubject)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($count == self::$recur_limit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* TODO:
|
||||
"emailAddress attribute values are not case-sensitive (e.g., "subscriber@example.com" is the same as "SUBSCRIBER@EXAMPLE.COM")."
|
||||
-- http://tools.ietf.org/html/rfc5280#section-4.1.2.6
|
||||
|
@ -2297,8 +2135,7 @@ class X509
|
|||
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier');
|
||||
switch (true) {
|
||||
case !is_array($authorityKey):
|
||||
case !$subjectKeyID:
|
||||
case isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
|
||||
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
|
||||
$signingCert = $this->currentCert; // working cert
|
||||
}
|
||||
}
|
||||
|
@ -2315,27 +2152,23 @@ class X509
|
|||
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
|
||||
switch (true) {
|
||||
case !is_array($authorityKey):
|
||||
case !$subjectKeyID:
|
||||
case isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
|
||||
if (is_array($authorityKey) && isset($authorityKey['authorityCertSerialNumber']) && !$authorityKey['authorityCertSerialNumber']->equals($ca['tbsCertificate']['serialNumber'])) {
|
||||
break 2; // serial mismatch - check other ca
|
||||
}
|
||||
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
|
||||
$signingCert = $ca; // working cert
|
||||
break 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (count($this->CAs) == $i && $caonly) {
|
||||
return $this->_testForIntermediate($caonly, $count) && $this->validateSignature($caonly);
|
||||
return false;
|
||||
}
|
||||
} elseif (!isset($signingCert) || $caonly) {
|
||||
return $this->_testForIntermediate($caonly, $count) && $this->validateSignature($caonly);
|
||||
return false;
|
||||
}
|
||||
return $this->_validateSignature(
|
||||
$signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'],
|
||||
$signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'],
|
||||
$this->currentCert['signatureAlgorithm']['algorithm'],
|
||||
substr(base64_decode($this->currentCert['signature']), 1),
|
||||
substr(Base64::decode($this->currentCert['signature']), 1),
|
||||
$this->signatureSubject
|
||||
);
|
||||
case isset($this->currentCert['certificationRequestInfo']):
|
||||
|
@ -2343,7 +2176,7 @@ class X509
|
|||
$this->currentCert['certificationRequestInfo']['subjectPKInfo']['algorithm']['algorithm'],
|
||||
$this->currentCert['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'],
|
||||
$this->currentCert['signatureAlgorithm']['algorithm'],
|
||||
substr(base64_decode($this->currentCert['signature']), 1),
|
||||
substr(Base64::decode($this->currentCert['signature']), 1),
|
||||
$this->signatureSubject
|
||||
);
|
||||
case isset($this->currentCert['publicKeyAndChallenge']):
|
||||
|
@ -2351,7 +2184,7 @@ class X509
|
|||
$this->currentCert['publicKeyAndChallenge']['spki']['algorithm']['algorithm'],
|
||||
$this->currentCert['publicKeyAndChallenge']['spki']['subjectPublicKey'],
|
||||
$this->currentCert['signatureAlgorithm']['algorithm'],
|
||||
substr(base64_decode($this->currentCert['signature']), 1),
|
||||
substr(Base64::decode($this->currentCert['signature']), 1),
|
||||
$this->signatureSubject
|
||||
);
|
||||
case isset($this->currentCert['tbsCertList']):
|
||||
|
@ -2365,11 +2198,7 @@ class X509
|
|||
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
|
||||
switch (true) {
|
||||
case !is_array($authorityKey):
|
||||
case !$subjectKeyID:
|
||||
case isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
|
||||
if (is_array($authorityKey) && isset($authorityKey['authorityCertSerialNumber']) && !$authorityKey['authorityCertSerialNumber']->equals($ca['tbsCertificate']['serialNumber'])) {
|
||||
break 2; // serial mismatch - check other ca
|
||||
}
|
||||
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
|
||||
$signingCert = $ca; // working cert
|
||||
break 3;
|
||||
}
|
||||
|
@ -2383,7 +2212,7 @@ class X509
|
|||
$signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'],
|
||||
$signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'],
|
||||
$this->currentCert['signatureAlgorithm']['algorithm'],
|
||||
substr(base64_decode($this->currentCert['signature']), 1),
|
||||
substr(Base64::decode($this->currentCert['signature']), 1),
|
||||
$this->signatureSubject
|
||||
);
|
||||
default:
|
||||
|
@ -2394,7 +2223,8 @@ class X509
|
|||
/**
|
||||
* Validates a signature
|
||||
*
|
||||
* Returns true if the signature is verified, false if it is not correct or null on error
|
||||
* Returns true if the signature is verified and false if it is not correct.
|
||||
* If the algorithms are unsupposed an exception is thrown.
|
||||
*
|
||||
* @param string $publicKeyAlgorithm
|
||||
* @param string $publicKey
|
||||
|
@ -2402,14 +2232,15 @@ class X509
|
|||
* @param string $signature
|
||||
* @param string $signatureSubject
|
||||
* @access private
|
||||
* @return int
|
||||
* @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported
|
||||
* @return bool
|
||||
*/
|
||||
function _validateSignature($publicKeyAlgorithm, $publicKey, $signatureAlgorithm, $signature, $signatureSubject)
|
||||
{
|
||||
switch ($publicKeyAlgorithm) {
|
||||
case 'rsaEncryption':
|
||||
$rsa = new RSA();
|
||||
$rsa->loadKey($publicKey);
|
||||
$rsa->load($publicKey);
|
||||
|
||||
switch ($signatureAlgorithm) {
|
||||
case 'md2WithRSAEncryption':
|
||||
|
@ -2420,57 +2251,21 @@ class X509
|
|||
case 'sha384WithRSAEncryption':
|
||||
case 'sha512WithRSAEncryption':
|
||||
$rsa->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm));
|
||||
$rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);
|
||||
if (!@$rsa->verify($signatureSubject, $signature)) {
|
||||
if (!@$rsa->verify($signatureSubject, $signature, RSA::PADDING_PKCS1)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
throw new UnsupportedAlgorithmException('Signature algorithm unsupported');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
throw new UnsupportedAlgorithmException('Public key algorithm unsupported');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the recursion limit
|
||||
*
|
||||
* When validating a signature it may be necessary to download intermediate certs from URI's.
|
||||
* An intermediate cert that linked to itself would result in an infinite loop so to prevent
|
||||
* that we set a recursion limit. A negative number means that there is no recursion limit.
|
||||
*
|
||||
* @param int $count
|
||||
* @access public
|
||||
*/
|
||||
static function setRecurLimit($count)
|
||||
{
|
||||
self::$recur_limit = $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents URIs from being automatically retrieved
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
static function disableURLFetch()
|
||||
{
|
||||
self::$disable_url_fetch = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows URIs to be automatically retrieved
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
static function enableURLFetch()
|
||||
{
|
||||
self::$disable_url_fetch = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reformat public keys
|
||||
*
|
||||
|
@ -2490,7 +2285,7 @@ class X509
|
|||
// subjectPublicKey is stored as a bit string in X.509 certs. the first byte of a bit string represents how many bits
|
||||
// in the last byte should be ignored. the following only supports non-zero stuff but as none of the X.509 certs Firefox
|
||||
// uses as a cert authority actually use a non-zero bit I think it's safe to assume that none do.
|
||||
chunk_split(base64_encode(substr(base64_decode($key), 1)), 64) .
|
||||
chunk_split(Base64::encode(substr(Base64::decode($key), 1)), 64) .
|
||||
'-----END RSA PUBLIC KEY-----';
|
||||
default:
|
||||
return $key;
|
||||
|
@ -2508,7 +2303,7 @@ class X509
|
|||
*/
|
||||
function _decodeIP($ip)
|
||||
{
|
||||
return inet_ntop(base64_decode($ip));
|
||||
return inet_ntop(Base64::decode($ip));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2522,7 +2317,7 @@ class X509
|
|||
*/
|
||||
function _encodeIP($ip)
|
||||
{
|
||||
return base64_encode(inet_pton($ip));
|
||||
return Base64::encode(inet_pton($ip));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2676,10 +2471,6 @@ class X509
|
|||
}
|
||||
|
||||
$dn = array_values($dn);
|
||||
// fix for https://bugs.php.net/75433 affecting PHP 7.2
|
||||
if (!isset($dn[0])) {
|
||||
$dn = array_splice($dn, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2850,7 +2641,7 @@ class X509
|
|||
$hash = new Hash('sha1');
|
||||
$hash = $hash->hash($dn);
|
||||
extract(unpack('Vhash', $hash));
|
||||
return strtolower(bin2hex(pack('N', $hash)));
|
||||
return strtolower(Hex::encode(pack('N', $hash)));
|
||||
}
|
||||
|
||||
// Default is to return a string.
|
||||
|
@ -2923,14 +2714,12 @@ class X509
|
|||
$value = array_pop($value); // Always strip data type.
|
||||
}
|
||||
} elseif (is_object($value) && $value instanceof Element) {
|
||||
$callback = function ($x) {
|
||||
return "\x" . bin2hex($x[0]);
|
||||
};
|
||||
$callback = create_function('$x', 'return "\x" . bin2hex($x[0]);');
|
||||
$value = strtoupper(preg_replace_callback('#[^\x20-\x7E]#', $callback, $value->element));
|
||||
}
|
||||
$output.= $desc . '=' . $value;
|
||||
$result[$desc] = isset($result[$desc]) ?
|
||||
array_merge((array) $result[$desc], array($value)) :
|
||||
array_merge((array) $dn[$prop], array($value)) :
|
||||
$value;
|
||||
$start = false;
|
||||
}
|
||||
|
@ -3146,7 +2935,7 @@ class X509
|
|||
switch ($keyinfo['algorithm']['algorithm']) {
|
||||
case 'rsaEncryption':
|
||||
$publicKey = new RSA();
|
||||
$publicKey->loadKey($key);
|
||||
$publicKey->load($key);
|
||||
$publicKey->setPublicKey();
|
||||
break;
|
||||
default:
|
||||
|
@ -3224,7 +3013,7 @@ class X509
|
|||
switch ($algorithm) {
|
||||
case 'rsaEncryption':
|
||||
$this->publicKey = new RSA();
|
||||
$this->publicKey->loadKey($key);
|
||||
$this->publicKey->load($key);
|
||||
$this->publicKey->setPublicKey();
|
||||
break;
|
||||
default:
|
||||
|
@ -3259,10 +3048,7 @@ class X509
|
|||
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;
|
||||
= Base64::encode("\0" . Base64::decode(preg_replace('#-.+-|[\r\n]#', '', $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'])));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3285,7 +3071,7 @@ class X509
|
|||
return $csr;
|
||||
// case self::FORMAT_PEM:
|
||||
default:
|
||||
return "-----BEGIN CERTIFICATE REQUEST-----\r\n" . chunk_split(base64_encode($csr), 64) . '-----END CERTIFICATE REQUEST-----';
|
||||
return "-----BEGIN CERTIFICATE REQUEST-----\r\n" . chunk_split(Base64::encode($csr), 64) . '-----END CERTIFICATE REQUEST-----';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3314,9 +3100,9 @@ class X509
|
|||
|
||||
$asn1 = new ASN1();
|
||||
|
||||
// OpenSSL produces SPKAC's that are preceded by the string SPKAC=
|
||||
// OpenSSL produces SPKAC's that are preceeded 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;
|
||||
$temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? Base64::decode($temp) : false;
|
||||
if ($temp != false) {
|
||||
$spkac = $temp;
|
||||
}
|
||||
|
@ -3351,7 +3137,7 @@ class X509
|
|||
switch ($algorithm) {
|
||||
case 'rsaEncryption':
|
||||
$this->publicKey = new RSA();
|
||||
$this->publicKey->loadKey($key);
|
||||
$this->publicKey->load($key);
|
||||
$this->publicKey->setPublicKey();
|
||||
break;
|
||||
default:
|
||||
|
@ -3387,7 +3173,7 @@ class X509
|
|||
switch ($algorithm) {
|
||||
case 'rsaEncryption':
|
||||
$spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']
|
||||
= base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'])));
|
||||
= Base64::encode("\0" . Base64::decode(preg_replace('#-.+-|[\r\n]#', '', $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'])));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3401,9 +3187,9 @@ class X509
|
|||
return $spkac;
|
||||
// case self::FORMAT_PEM:
|
||||
default:
|
||||
// OpenSSL's implementation of SPKAC requires the SPKAC be preceded by SPKAC= and since there are pretty much
|
||||
// OpenSSL's implementation of SPKAC requires the SPKAC be preceeded by SPKAC= and since there are pretty much
|
||||
// no other SPKAC decoders phpseclib will use that same format
|
||||
return 'SPKAC=' . base64_encode($spkac);
|
||||
return 'SPKAC=' . Base64::encode($spkac);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3455,18 +3241,11 @@ class X509
|
|||
$this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
|
||||
|
||||
$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);
|
||||
}
|
||||
}
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3530,7 +3309,7 @@ class X509
|
|||
return $crl;
|
||||
// case self::FORMAT_PEM:
|
||||
default:
|
||||
return "-----BEGIN X509 CRL-----\r\n" . chunk_split(base64_encode($crl), 64) . '-----END X509 CRL-----';
|
||||
return "-----BEGIN X509 CRL-----\r\n" . chunk_split(Base64::encode($crl), 64) . '-----END X509 CRL-----';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3548,11 +3327,7 @@ class X509
|
|||
*/
|
||||
function _timeField($date)
|
||||
{
|
||||
if ($date instanceof Element) {
|
||||
return $date;
|
||||
}
|
||||
$dateObj = new DateTime($date, new DateTimeZone('GMT'));
|
||||
$year = $dateObj->format('Y'); // the same way ASN1.php parses this
|
||||
$year = @gmdate("Y", @strtotime($date)); // the same way ASN1.php parses this
|
||||
if ($year < 2050) {
|
||||
return array('utcTime' => $date);
|
||||
} else {
|
||||
|
@ -3573,7 +3348,7 @@ class X509
|
|||
* @access public
|
||||
* @return mixed
|
||||
*/
|
||||
function sign($issuer, $subject, $signatureAlgorithm = 'sha1WithRSAEncryption')
|
||||
function sign($issuer, $subject, $signatureAlgorithm = 'sha256WithRSAEncryption')
|
||||
{
|
||||
if (!is_object($issuer->privateKey) || empty($issuer->dn)) {
|
||||
return false;
|
||||
|
@ -3617,12 +3392,8 @@ class X509
|
|||
return false;
|
||||
}
|
||||
|
||||
$startDate = new DateTime('now', new DateTimeZone(@date_default_timezone_get()));
|
||||
$startDate = !empty($this->startDate) ? $this->startDate : $startDate->format('D, d M Y H:i:s O');
|
||||
|
||||
$endDate = new DateTime('+1 year', new DateTimeZone(@date_default_timezone_get()));
|
||||
$endDate = !empty($this->endDate) ? $this->endDate : $endDate->format('D, d M Y H:i:s O');
|
||||
|
||||
$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'));
|
||||
/* "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
|
||||
|
@ -3638,7 +3409,7 @@ class X509
|
|||
'tbsCertificate' =>
|
||||
array(
|
||||
'version' => 'v3',
|
||||
'serialNumber' => $serialNumber, // $this->setSerialNumber()
|
||||
'serialNumber' => $serialNumber, // $this->setserialNumber()
|
||||
'signature' => array('algorithm' => $signatureAlgorithm),
|
||||
'issuer' => false, // this is going to be overwritten later
|
||||
'validity' => array(
|
||||
|
@ -3684,8 +3455,8 @@ class X509
|
|||
|
||||
$altName = array();
|
||||
|
||||
if (isset($subject->domains) && count($subject->domains)) {
|
||||
$altName = array_map(array('\phpseclib\File\X509', '_dnsName'), $subject->domains);
|
||||
if (isset($subject->domains) && count($subject->domains) > 1) {
|
||||
$altName = array_map(array('X509', '_dnsName'), $subject->domains);
|
||||
}
|
||||
|
||||
if (isset($subject->ipAddresses) && count($subject->ipAddresses)) {
|
||||
|
@ -3730,7 +3501,7 @@ class X509
|
|||
);
|
||||
|
||||
if (!isset($subject->currentKeyIdentifier)) {
|
||||
$this->setExtension('id-ce-subjectKeyIdentifier', base64_encode($this->computeKeyIdentifier($this->currentCert)), false, false);
|
||||
$this->setExtension('id-ce-subjectKeyIdentifier', Base64::encode($this->computeKeyIdentifier($this->currentCert)), false, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3763,7 +3534,7 @@ class X509
|
|||
$origPublicKey = $this->publicKey;
|
||||
$class = get_class($this->privateKey);
|
||||
$this->publicKey = new $class();
|
||||
$this->publicKey->loadKey($this->privateKey->getPublicKey());
|
||||
$this->publicKey->load($this->privateKey->getPublicKey());
|
||||
$this->publicKey->setPublicKey();
|
||||
if (!($publicKey = $this->_formatSubjectPublicKey())) {
|
||||
return false;
|
||||
|
@ -3821,7 +3592,7 @@ class X509
|
|||
$origPublicKey = $this->publicKey;
|
||||
$class = get_class($this->privateKey);
|
||||
$this->publicKey = new $class();
|
||||
$this->publicKey->loadKey($this->privateKey->getPublicKey());
|
||||
$this->publicKey->load($this->privateKey->getPublicKey());
|
||||
$this->publicKey->setPublicKey();
|
||||
$publicKey = $this->_formatSubjectPublicKey();
|
||||
if (!$publicKey) {
|
||||
|
@ -3890,9 +3661,7 @@ class X509
|
|||
|
||||
$currentCert = isset($this->currentCert) ? $this->currentCert : null;
|
||||
$signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null;
|
||||
|
||||
$thisUpdate = new DateTime('now', new DateTimeZone(@date_default_timezone_get()));
|
||||
$thisUpdate = !empty($this->startDate) ? $this->startDate : $thisUpdate->format('D, d M Y H:i:s O');
|
||||
$thisUpdate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O');
|
||||
|
||||
if (isset($crl->currentCert) && is_array($crl->currentCert) && isset($crl->currentCert['tbsCertList'])) {
|
||||
$this->currentCert = $crl->currentCert;
|
||||
|
@ -4011,6 +3780,7 @@ class X509
|
|||
* @param \phpseclib\File\X509 $subject
|
||||
* @param string $signatureAlgorithm
|
||||
* @access public
|
||||
* @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported
|
||||
* @return mixed
|
||||
*/
|
||||
function _sign($key, $signatureAlgorithm)
|
||||
|
@ -4025,14 +3795,15 @@ class X509
|
|||
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));
|
||||
$this->currentCert['signature'] = Base64::encode("\0" . $key->sign($this->signatureSubject, RSA::PADDING_PKCS1));
|
||||
return $this->currentCert;
|
||||
default:
|
||||
throw new UnsupportedAlgorithmException('Signature algorithm unsupported');
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
throw new UnsupportedAlgorithmException('Unsupported public key algorithm');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4043,11 +3814,7 @@ class X509
|
|||
*/
|
||||
function setStartDate($date)
|
||||
{
|
||||
if (!is_object($date) || !is_a($date, 'DateTime')) {
|
||||
$date = new DateTime($date, new DateTimeZone(@date_default_timezone_get()));
|
||||
}
|
||||
|
||||
$this->startDate = $date->format('D, d M Y H:i:s O');
|
||||
$this->startDate = @date('D, d M Y H:i:s O', @strtotime($date));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4071,11 +3838,7 @@ class X509
|
|||
$temp = chr(ASN1::TYPE_GENERALIZED_TIME) . $asn1->_encodeLength(strlen($temp)) . $temp;
|
||||
$this->endDate = new Element($temp);
|
||||
} else {
|
||||
if (!is_object($date) || !is_a($date, 'DateTime')) {
|
||||
$date = new DateTime($date, new DateTimeZone(@date_default_timezone_get()));
|
||||
}
|
||||
|
||||
$this->endDate = $date->format('D, d M Y H:i:s O');
|
||||
$this->endDate = @date('D, d M Y H:i:s O', @strtotime($date));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4101,74 +3864,6 @@ class 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
|
||||
*
|
||||
|
@ -4285,10 +3980,6 @@ class X509
|
|||
}
|
||||
|
||||
$extensions = array_values($extensions);
|
||||
// fix for https://bugs.php.net/75433 affecting PHP 7.2
|
||||
if (!isset($extensions[0])) {
|
||||
$extensions = array_splice($extensions, 0, 0);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@ -4618,7 +4309,7 @@ class X509
|
|||
if (empty($value)) {
|
||||
unset($this->currentKeyIdentifier);
|
||||
} else {
|
||||
$this->currentKeyIdentifier = base64_encode($value);
|
||||
$this->currentKeyIdentifier = Base64::encode($value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4666,10 +4357,10 @@ class X509
|
|||
if (empty($raw)) {
|
||||
return false;
|
||||
}
|
||||
$raw = base64_decode($raw);
|
||||
$raw = Base64::decode($raw);
|
||||
// If the key is private, compute identifier from its corresponding public key.
|
||||
$key = new RSA();
|
||||
if (!$key->loadKey($raw)) {
|
||||
if (!$key->load($raw)) {
|
||||
return false; // Not an unencrypted RSA key.
|
||||
}
|
||||
if ($key->getPrivateKey() !== false) { // If private.
|
||||
|
@ -4689,7 +4380,7 @@ class X509
|
|||
}
|
||||
return false;
|
||||
default: // Should be a key object (i.e.: \phpseclib\Crypt\RSA).
|
||||
$key = $key->getPublicKey(RSA::PUBLIC_FORMAT_PKCS1);
|
||||
$key = $key->getPublicKey('PKCS1');
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -4719,10 +4410,10 @@ class X509
|
|||
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 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)
|
||||
'subjectPublicKey' => $this->publicKey->getPublicKey('PKCS1')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4809,9 +4500,8 @@ class X509
|
|||
}
|
||||
|
||||
$i = count($rclist);
|
||||
$revocationDate = new DateTime('now', new DateTimeZone(@date_default_timezone_get()));
|
||||
$rclist[] = array('userCertificate' => $serial,
|
||||
'revocationDate' => $this->_timeField($revocationDate->format('D, d M Y H:i:s O')));
|
||||
'revocationDate' => $this->_timeField(@date('D, d M Y H:i:s O')));
|
||||
return $i;
|
||||
}
|
||||
|
||||
|
@ -5023,7 +4713,7 @@ class X509
|
|||
$temp = preg_replace('#-+[^-]+-+#', '', $temp);
|
||||
// remove new lines
|
||||
$temp = str_replace(array("\r", "\n", ' '), '', $temp);
|
||||
$temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
|
||||
$temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? Base64::decode($temp) : false;
|
||||
return $temp != false ? $temp : $str;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
22
vendor/phpseclib/phpseclib/phpseclib/Net/SCP.php
vendored
22
vendor/phpseclib/phpseclib/phpseclib/Net/SCP.php
vendored
|
@ -32,6 +32,8 @@
|
|||
|
||||
namespace phpseclib\Net;
|
||||
|
||||
use phpseclib\Exception\FileNotFoundException;
|
||||
|
||||
/**
|
||||
* Pure-PHP implementations of SCP.
|
||||
*
|
||||
|
@ -99,7 +101,9 @@ class SCP
|
|||
*
|
||||
* Connects to an SSH server
|
||||
*
|
||||
* @param \phpseclib\Net\SSH1|\phpseclib\Net\SSH2 $ssh
|
||||
* @param string $host
|
||||
* @param int $port
|
||||
* @param int $timeout
|
||||
* @return \phpseclib\Net\SCP
|
||||
* @access public
|
||||
*/
|
||||
|
@ -135,6 +139,7 @@ class SCP
|
|||
* @param string $data
|
||||
* @param int $mode
|
||||
* @param callable $callback
|
||||
* @throws \phpseclib\Exception\FileNotFoundException if you're uploading via a file and the file doesn't exist
|
||||
* @return bool
|
||||
* @access public
|
||||
*/
|
||||
|
@ -144,11 +149,6 @@ class SCP
|
|||
return false;
|
||||
}
|
||||
|
||||
if (empty($remote_file)) {
|
||||
user_error('remote_file cannot be blank', E_USER_NOTICE);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->ssh->exec('scp -t ' . escapeshellarg($remote_file), false)) { // -t = to
|
||||
return false;
|
||||
}
|
||||
|
@ -168,8 +168,7 @@ class SCP
|
|||
$size = strlen($data);
|
||||
} else {
|
||||
if (!is_file($data)) {
|
||||
user_error("$data is not a valid file", E_USER_NOTICE);
|
||||
return false;
|
||||
throw new FileNotFoundException("$data is not a valid file");
|
||||
}
|
||||
|
||||
$fp = @fopen($data, 'rb');
|
||||
|
@ -289,6 +288,7 @@ class SCP
|
|||
* Receives a packet from an SSH server
|
||||
*
|
||||
* @return string
|
||||
* @throws \UnexpectedValueException on receipt of an unexpected packet
|
||||
* @access private
|
||||
*/
|
||||
function _receive()
|
||||
|
@ -304,9 +304,6 @@ class SCP
|
|||
$response = $this->ssh->_get_binary_packet();
|
||||
switch ($response[SSH1::RESPONSE_TYPE]) {
|
||||
case NET_SSH1_SMSG_STDOUT_DATA:
|
||||
if (strlen($response[SSH1::RESPONSE_DATA]) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nlength', $response[SSH1::RESPONSE_DATA]));
|
||||
return $this->ssh->_string_shift($response[SSH1::RESPONSE_DATA], $length);
|
||||
case NET_SSH1_SMSG_STDERR_DATA:
|
||||
|
@ -317,8 +314,7 @@ class SCP
|
|||
$this->ssh->bitmap = 0;
|
||||
return false;
|
||||
default:
|
||||
user_error('Unknown packet received', E_USER_NOTICE);
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Unknown packet received');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
373
vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php
vendored
373
vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php
vendored
|
@ -37,6 +37,9 @@
|
|||
|
||||
namespace phpseclib\Net;
|
||||
|
||||
use ParagonIE\ConstantTime\Hex;
|
||||
use phpseclib\Exception\FileNotFoundException;
|
||||
|
||||
/**
|
||||
* Pure-PHP implementations of SFTP.
|
||||
*
|
||||
|
@ -109,11 +112,11 @@ class SFTP extends 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 boolean
|
||||
* @var int
|
||||
* @see self::_send_sftp_packet()
|
||||
* @access private
|
||||
*/
|
||||
var $use_request_id = false;
|
||||
var $request_id = false;
|
||||
|
||||
/**
|
||||
* The Packet Type
|
||||
|
@ -158,7 +161,7 @@ class SFTP extends SSH2
|
|||
* Current working directory
|
||||
*
|
||||
* @var string
|
||||
* @see self::realpath()
|
||||
* @see self::_realpath()
|
||||
* @see self::chdir()
|
||||
* @access private
|
||||
*/
|
||||
|
@ -187,7 +190,7 @@ class SFTP extends SSH2
|
|||
*
|
||||
* @see self::getSFTPErrors()
|
||||
* @see self::getLastSFTPError()
|
||||
* @var array
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $sftp_errors = array();
|
||||
|
@ -236,29 +239,6 @@ class SFTP extends SSH2
|
|||
*/
|
||||
var $sortOptions = array();
|
||||
|
||||
/**
|
||||
* Canonicalization Flag
|
||||
*
|
||||
* Determines whether or not paths should be canonicalized before being
|
||||
* passed on to the remote server.
|
||||
*
|
||||
* @see self::enablePathCanonicalization()
|
||||
* @see self::disablePathCanonicalization()
|
||||
* @see self::realpath()
|
||||
* @var bool
|
||||
* @access private
|
||||
*/
|
||||
var $canonicalize_paths = true;
|
||||
|
||||
/**
|
||||
* Request Buffers
|
||||
*
|
||||
* @see self::_get_sftp_packet()
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
var $requestBuffer = array();
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
|
@ -358,11 +338,11 @@ class SFTP extends SSH2
|
|||
// yields inconsistent behavior depending on how php is compiled. so we left shift -1 (which, in
|
||||
// two's compliment, consists of all 1 bits) by 31. on 64-bit systems this'll yield 0xFFFFFFFF80000000.
|
||||
// that's not a problem, however, and 'anded' and a 32-bit number, as all the leading 1 bits are ignored.
|
||||
(-1 << 31) & 0xFFFFFFFF => 'NET_SFTP_ATTR_EXTENDED'
|
||||
-1 << 31 => 'NET_SFTP_ATTR_EXTENDED'
|
||||
);
|
||||
// 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 similarly alter the constant names.
|
||||
// the array for that $this->open5_flags and similarily alter the constant names.
|
||||
$this->open_flags = array(
|
||||
0x00000001 => 'NET_SFTP_OPEN_READ',
|
||||
0x00000002 => 'NET_SFTP_OPEN_WRITE',
|
||||
|
@ -395,7 +375,7 @@ class SFTP extends SSH2
|
|||
);
|
||||
|
||||
if (!defined('NET_SFTP_QUEUE_SIZE')) {
|
||||
define('NET_SFTP_QUEUE_SIZE', 32);
|
||||
define('NET_SFTP_QUEUE_SIZE', 50);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -404,6 +384,7 @@ class SFTP extends SSH2
|
|||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return bool
|
||||
* @access public
|
||||
*/
|
||||
|
@ -432,7 +413,7 @@ class SFTP extends SSH2
|
|||
|
||||
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN;
|
||||
|
||||
$response = $this->_get_channel_packet(self::CHANNEL, true);
|
||||
$response = $this->_get_channel_packet(self::CHANNEL);
|
||||
if ($response === false) {
|
||||
return false;
|
||||
}
|
||||
|
@ -453,7 +434,7 @@ class SFTP extends SSH2
|
|||
|
||||
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
|
||||
|
||||
$response = $this->_get_channel_packet(self::CHANNEL, true);
|
||||
$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" .
|
||||
|
@ -477,7 +458,7 @@ class SFTP extends SSH2
|
|||
|
||||
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
|
||||
|
||||
$response = $this->_get_channel_packet(self::CHANNEL, true);
|
||||
$response = $this->_get_channel_packet(self::CHANNEL);
|
||||
if ($response === false) {
|
||||
return false;
|
||||
}
|
||||
|
@ -491,24 +472,14 @@ class SFTP extends SSH2
|
|||
|
||||
$response = $this->_get_sftp_packet();
|
||||
if ($this->packet_type != NET_SFTP_VERSION) {
|
||||
user_error('Expected SSH_FXP_VERSION');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_VERSION');
|
||||
}
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nversion', $this->_string_shift($response, 4)));
|
||||
$this->version = $version;
|
||||
while (!empty($response)) {
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
||||
$key = $this->_string_shift($response, $length);
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
||||
$value = $this->_string_shift($response, $length);
|
||||
$this->extensions[$key] = $value;
|
||||
|
@ -528,7 +499,7 @@ class SFTP extends SSH2
|
|||
}
|
||||
*/
|
||||
|
||||
$this->use_request_id = true;
|
||||
$this->request_id = 1;
|
||||
|
||||
/*
|
||||
A Note on SFTPv4/5/6 support:
|
||||
|
@ -598,26 +569,6 @@ class SFTP extends SSH2
|
|||
$this->stat_cache = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable path canonicalization
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function enablePathCanonicalization()
|
||||
{
|
||||
$this->canonicalize_paths = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable path canonicalization
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function disablePathCanonicalization()
|
||||
{
|
||||
$this->canonicalize_paths = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current directory name
|
||||
*
|
||||
|
@ -639,15 +590,12 @@ class SFTP extends SSH2
|
|||
function _logError($response, $status = -1)
|
||||
{
|
||||
if ($status == -1) {
|
||||
if (strlen($response) < 4) {
|
||||
return;
|
||||
}
|
||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||
}
|
||||
|
||||
$error = $this->status_codes[$status];
|
||||
|
||||
if ($this->version > 2 || strlen($response) < 4) {
|
||||
if ($this->version > 2) {
|
||||
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
||||
$this->sftp_errors[] = $error . ': ' . $this->_string_shift($response, $length);
|
||||
} else {
|
||||
|
@ -655,41 +603,20 @@ class SFTP extends 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.
|
||||
*
|
||||
* If canonicalize_paths has been disabled using disablePathCanonicalization(), $path is returned as-is.
|
||||
*
|
||||
* @see self::chdir()
|
||||
* @see self::disablePathCanonicalization()
|
||||
* @param string $path
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return mixed
|
||||
* @access private
|
||||
*/
|
||||
function _realpath($path)
|
||||
{
|
||||
if (!$this->canonicalize_paths) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
if ($this->pwd === false) {
|
||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.9
|
||||
if (!$this->_send_sftp_packet(NET_SFTP_REALPATH, pack('Na*', strlen($path), $path))) {
|
||||
|
@ -703,17 +630,13 @@ class SFTP extends SSH2
|
|||
// should work on all SFTP versions since the only part of the SSH_FXP_NAME packet the following looks
|
||||
// at is the first part and that part is defined the same in SFTP versions 3 through 6.
|
||||
$this->_string_shift($response, 4); // skip over the count - it should be 1, anyway
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
||||
return $this->_string_shift($response, $length);
|
||||
case NET_SFTP_STATUS:
|
||||
$this->_logError($response);
|
||||
return false;
|
||||
default:
|
||||
user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -744,6 +667,7 @@ class SFTP extends SSH2
|
|||
* Changes the current directory
|
||||
*
|
||||
* @param string $dir
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return bool
|
||||
* @access public
|
||||
*/
|
||||
|
@ -788,8 +712,7 @@ class SFTP extends SSH2
|
|||
$this->_logError($response);
|
||||
return false;
|
||||
default:
|
||||
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
if (!$this->_close_handle($handle)) {
|
||||
|
@ -842,7 +765,6 @@ class SFTP extends SSH2
|
|||
}
|
||||
if (is_array($this->_query_stat_cache($this->_realpath($dir . '/' . $value)))) {
|
||||
$temp = $this->_nlist_helper($dir . '/' . $value, true, $relativeDir . $value . '/');
|
||||
$temp = is_array($temp) ? $temp : array();
|
||||
$result = array_merge($result, $temp);
|
||||
} else {
|
||||
$result[] = $relativeDir . $value;
|
||||
|
@ -874,17 +796,7 @@ class SFTP extends SSH2
|
|||
unset($files[$key]);
|
||||
continue;
|
||||
}
|
||||
$is_directory = false;
|
||||
if ($key != '.' && $key != '..') {
|
||||
if ($this->use_stat_cache) {
|
||||
$is_directory = is_array($this->_query_stat_cache($this->_realpath($dir . '/' . $key)));
|
||||
} else {
|
||||
$stat = $this->lstat($dir . '/' . $key);
|
||||
$is_directory = $stat && $stat['type'] === NET_SFTP_TYPE_DIRECTORY;
|
||||
}
|
||||
}
|
||||
|
||||
if ($is_directory) {
|
||||
if ($key != '.' && $key != '..' && is_array($this->_query_stat_cache($this->_realpath($dir . '/' . $key)))) {
|
||||
$depth++;
|
||||
$files[$key] = $this->rawlist($dir . '/' . $key, true);
|
||||
$depth--;
|
||||
|
@ -902,6 +814,7 @@ class SFTP extends SSH2
|
|||
* @param string $dir
|
||||
* @param bool $raw
|
||||
* @return mixed
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @access private
|
||||
*/
|
||||
function _list($dir, $raw = true)
|
||||
|
@ -933,8 +846,7 @@ class SFTP extends SSH2
|
|||
$this->_logError($response);
|
||||
return false;
|
||||
default:
|
||||
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
$this->_update_stat_cache($dir, array());
|
||||
|
@ -951,19 +863,10 @@ class SFTP extends SSH2
|
|||
$response = $this->_get_sftp_packet();
|
||||
switch ($this->packet_type) {
|
||||
case NET_SFTP_NAME:
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Ncount', $this->_string_shift($response, 4)));
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
||||
$shortname = $this->_string_shift($response, $length);
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
||||
$longname = $this->_string_shift($response, $length);
|
||||
$attributes = $this->_parseAttributes($response);
|
||||
|
@ -990,9 +893,6 @@ class SFTP extends SSH2
|
|||
}
|
||||
break;
|
||||
case NET_SFTP_STATUS:
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||
if ($status != NET_SFTP_STATUS_EOF) {
|
||||
$this->_logError($response, $status);
|
||||
|
@ -1000,8 +900,7 @@ class SFTP extends SSH2
|
|||
}
|
||||
break 2;
|
||||
default:
|
||||
user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1167,7 +1066,7 @@ class SFTP extends SSH2
|
|||
$temp[$dir] = array();
|
||||
}
|
||||
if ($i === $max) {
|
||||
if (is_object($temp[$dir]) && is_object($value)) {
|
||||
if (is_object($temp[$dir])) {
|
||||
if (!isset($value->stat) && isset($temp[$dir]->stat)) {
|
||||
$value->stat = $temp[$dir]->stat;
|
||||
}
|
||||
|
@ -1355,11 +1254,12 @@ class SFTP extends SSH2
|
|||
/**
|
||||
* Returns general information about a file or symbolic link
|
||||
*
|
||||
* Determines information without calling \phpseclib\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 int $type
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return mixed
|
||||
* @access private
|
||||
*/
|
||||
|
@ -1380,8 +1280,7 @@ class SFTP extends SSH2
|
|||
return false;
|
||||
}
|
||||
|
||||
user_error('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1407,6 +1306,7 @@ class SFTP extends SSH2
|
|||
* @param string $filename
|
||||
* @param int $time
|
||||
* @param int $atime
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return bool
|
||||
* @access public
|
||||
*/
|
||||
|
@ -1443,8 +1343,7 @@ class SFTP extends SSH2
|
|||
$this->_logError($response);
|
||||
break;
|
||||
default:
|
||||
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
return $this->_setstat($filename, $attr, false);
|
||||
|
@ -1497,6 +1396,7 @@ class SFTP extends SSH2
|
|||
* @param int $mode
|
||||
* @param string $filename
|
||||
* @param bool $recursive
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return mixed
|
||||
* @access public
|
||||
*/
|
||||
|
@ -1516,7 +1416,7 @@ class SFTP extends SSH2
|
|||
return true;
|
||||
}
|
||||
|
||||
$filename = $this->realpath($filename);
|
||||
$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:
|
||||
|
@ -1535,8 +1435,7 @@ class SFTP extends SSH2
|
|||
return false;
|
||||
}
|
||||
|
||||
user_error('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1545,6 +1444,7 @@ class SFTP extends SSH2
|
|||
* @param string $filename
|
||||
* @param string $attr
|
||||
* @param bool $recursive
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return bool
|
||||
* @access private
|
||||
*/
|
||||
|
@ -1583,13 +1483,9 @@ class SFTP extends SSH2
|
|||
*/
|
||||
$response = $this->_get_sftp_packet();
|
||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||
user_error('Expected SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||
if ($status != NET_SFTP_STATUS_OK) {
|
||||
$this->_logError($response, $status);
|
||||
|
@ -1675,6 +1571,7 @@ class SFTP extends SSH2
|
|||
* Return the target of a symbolic link
|
||||
*
|
||||
* @param string $link
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return mixed
|
||||
* @access public
|
||||
*/
|
||||
|
@ -1698,22 +1595,15 @@ class SFTP extends SSH2
|
|||
$this->_logError($response);
|
||||
return false;
|
||||
default:
|
||||
user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Ncount', $this->_string_shift($response, 4)));
|
||||
// the file isn't a symlink
|
||||
if (!$count) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
||||
return $this->_string_shift($response, $length);
|
||||
}
|
||||
|
@ -1725,6 +1615,7 @@ class SFTP extends SSH2
|
|||
*
|
||||
* @param string $target
|
||||
* @param string $link
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return bool
|
||||
* @access public
|
||||
*/
|
||||
|
@ -1734,7 +1625,7 @@ class SFTP extends SSH2
|
|||
return false;
|
||||
}
|
||||
|
||||
//$target = $this->_realpath($target);
|
||||
$target = $this->_realpath($target);
|
||||
$link = $this->_realpath($link);
|
||||
|
||||
$packet = pack('Na*Na*', strlen($target), $target, strlen($link), $link);
|
||||
|
@ -1744,13 +1635,9 @@ class SFTP extends SSH2
|
|||
|
||||
$response = $this->_get_sftp_packet();
|
||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||
user_error('Expected SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||
if ($status != NET_SFTP_STATUS_OK) {
|
||||
$this->_logError($response, $status);
|
||||
|
@ -1800,6 +1687,7 @@ class SFTP extends SSH2
|
|||
*
|
||||
* @param string $dir
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @access private
|
||||
*/
|
||||
function _mkdir_helper($dir, $attr)
|
||||
|
@ -1810,13 +1698,9 @@ class SFTP extends SSH2
|
|||
|
||||
$response = $this->_get_sftp_packet();
|
||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||
user_error('Expected SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||
if ($status != NET_SFTP_STATUS_OK) {
|
||||
$this->_logError($response, $status);
|
||||
|
@ -1830,6 +1714,7 @@ class SFTP extends SSH2
|
|||
* Removes a directory.
|
||||
*
|
||||
* @param string $dir
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return bool
|
||||
* @access public
|
||||
*/
|
||||
|
@ -1850,13 +1735,9 @@ class SFTP extends SSH2
|
|||
|
||||
$response = $this->_get_sftp_packet();
|
||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||
user_error('Expected SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||
if ($status != NET_SFTP_STATUS_OK) {
|
||||
// presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED?
|
||||
|
@ -1914,6 +1795,9 @@ class SFTP extends SSH2
|
|||
* @param int $start
|
||||
* @param int $local_start
|
||||
* @param callable|null $progressCallback
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @throws \BadFunctionCallException if you're uploading via a callback and the callback function is invalid
|
||||
* @throws \phpseclib\Exception\FileNotFoundException if you're uploading via a file and the file doesn't exist
|
||||
* @return bool
|
||||
* @access public
|
||||
* @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - \phpseclib\Net\SFTP::setMode().
|
||||
|
@ -1961,8 +1845,7 @@ class SFTP extends SSH2
|
|||
$this->_logError($response);
|
||||
return false;
|
||||
default:
|
||||
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3
|
||||
|
@ -1970,26 +1853,18 @@ class SFTP extends SSH2
|
|||
switch (true) {
|
||||
case $mode & self::SOURCE_CALLBACK:
|
||||
if (!is_callable($data)) {
|
||||
user_error("\$data should be is_callable() if you specify SOURCE_CALLBACK flag");
|
||||
throw new \BadFunctionCallException("\$data should be is_callable() if you specify SOURCE_CALLBACK flag");
|
||||
}
|
||||
$dataCallback = $data;
|
||||
// do nothing
|
||||
break;
|
||||
case is_resource($data):
|
||||
$mode = $mode & ~self::SOURCE_LOCAL_FILE;
|
||||
$info = stream_get_meta_data($data);
|
||||
if ($info['wrapper_type'] == 'PHP' && $info['stream_type'] == 'Input') {
|
||||
$fp = fopen('php://memory', 'w+');
|
||||
stream_copy_to_stream($data, $fp);
|
||||
rewind($fp);
|
||||
} else {
|
||||
$fp = $data;
|
||||
}
|
||||
$fp = $data;
|
||||
break;
|
||||
case $mode & self::SOURCE_LOCAL_FILE:
|
||||
if (!is_file($data)) {
|
||||
user_error("$data is not a valid file");
|
||||
return false;
|
||||
throw new FileNotFoundException("$data is not a valid file");
|
||||
}
|
||||
$fp = @fopen($data, 'rb');
|
||||
if (!$fp) {
|
||||
|
@ -1999,7 +1874,7 @@ class SFTP extends SSH2
|
|||
|
||||
if (isset($fp)) {
|
||||
$stat = fstat($fp);
|
||||
$size = !empty($stat) ? $stat['size'] : 0;
|
||||
$size = $stat['size'];
|
||||
|
||||
if ($local_start >= 0) {
|
||||
fseek($fp, $local_start);
|
||||
|
@ -2018,7 +1893,7 @@ class SFTP extends 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 ($dataCallback || ($size === 0 || $sent < $size)) {
|
||||
while ($dataCallback || $sent < $size) {
|
||||
if ($dataCallback) {
|
||||
$temp = call_user_func($dataCallback, $sftp_packet_size);
|
||||
if (is_null($temp)) {
|
||||
|
@ -2026,11 +1901,7 @@ class SFTP extends SSH2
|
|||
}
|
||||
} 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)) {
|
||||
|
@ -2078,6 +1949,7 @@ class SFTP extends SSH2
|
|||
*
|
||||
* @param int $i
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @access private
|
||||
*/
|
||||
function _read_put_responses($i)
|
||||
|
@ -2085,13 +1957,9 @@ class SFTP extends SSH2
|
|||
while ($i--) {
|
||||
$response = $this->_get_sftp_packet();
|
||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||
user_error('Expected SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||
if ($status != NET_SFTP_STATUS_OK) {
|
||||
$this->_logError($response, $status);
|
||||
|
@ -2107,6 +1975,7 @@ class SFTP extends SSH2
|
|||
*
|
||||
* @param string $handle
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @access private
|
||||
*/
|
||||
function _close_handle($handle)
|
||||
|
@ -2119,13 +1988,9 @@ class SFTP extends SSH2
|
|||
// -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3
|
||||
$response = $this->_get_sftp_packet();
|
||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||
user_error('Expected SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||
if ($status != NET_SFTP_STATUS_OK) {
|
||||
$this->_logError($response, $status);
|
||||
|
@ -2148,11 +2013,11 @@ class SFTP extends SSH2
|
|||
* @param string $local_file
|
||||
* @param int $offset
|
||||
* @param int $length
|
||||
* @param callable|null $progressCallback
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return mixed
|
||||
* @access public
|
||||
*/
|
||||
function get($remote_file, $local_file = false, $offset = 0, $length = -1, $progressCallback = null)
|
||||
function get($remote_file, $local_file = false, $offset = 0, $length = -1)
|
||||
{
|
||||
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
|
||||
return false;
|
||||
|
@ -2177,8 +2042,7 @@ class SFTP extends SSH2
|
|||
$this->_logError($response);
|
||||
return false;
|
||||
default:
|
||||
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
if (is_resource($local_file)) {
|
||||
|
@ -2210,7 +2074,7 @@ class SFTP extends SSH2
|
|||
$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, $i)) {
|
||||
if (!$this->_send_sftp_packet(NET_SFTP_READ, $packet)) {
|
||||
if ($fclose_check) {
|
||||
fclose($fp);
|
||||
}
|
||||
|
@ -2218,9 +2082,6 @@ class SFTP extends SSH2
|
|||
}
|
||||
$packet = null;
|
||||
$read+= $packet_size;
|
||||
if (is_callable($progressCallback)) {
|
||||
call_user_func($progressCallback, $read);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
||||
|
@ -2228,17 +2089,15 @@ class SFTP extends SSH2
|
|||
break;
|
||||
}
|
||||
|
||||
$packets_sent = $i - 1;
|
||||
|
||||
$clear_responses = false;
|
||||
while ($i > 0) {
|
||||
$i--;
|
||||
|
||||
if ($clear_responses) {
|
||||
$this->_get_sftp_packet($packets_sent - $i);
|
||||
$this->_get_sftp_packet();
|
||||
continue;
|
||||
} else {
|
||||
$response = $this->_get_sftp_packet($packets_sent - $i);
|
||||
$response = $this->_get_sftp_packet();
|
||||
}
|
||||
|
||||
switch ($this->packet_type) {
|
||||
|
@ -2261,7 +2120,7 @@ class SFTP extends SSH2
|
|||
if ($fclose_check) {
|
||||
fclose($fp);
|
||||
}
|
||||
user_error('Expected SSH_FX_DATA or SSH_FXP_STATUS');
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_DATA or SSH_FXP_STATUS');
|
||||
}
|
||||
$response = null;
|
||||
}
|
||||
|
@ -2297,6 +2156,7 @@ class SFTP extends SSH2
|
|||
* @param string $path
|
||||
* @param bool $recursive
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @access public
|
||||
*/
|
||||
function delete($path, $recursive = true)
|
||||
|
@ -2305,15 +2165,6 @@ class SFTP extends SSH2
|
|||
return false;
|
||||
}
|
||||
|
||||
if (is_object($path)) {
|
||||
// It's an object. Cast it as string before we check anything else.
|
||||
$path = (string) $path;
|
||||
}
|
||||
|
||||
if (!is_string($path) || $path == '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$path = $this->_realpath($path);
|
||||
if ($path === false) {
|
||||
return false;
|
||||
|
@ -2326,14 +2177,10 @@ class SFTP extends SSH2
|
|||
|
||||
$response = $this->_get_sftp_packet();
|
||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||
user_error('Expected SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
// if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||
if ($status != NET_SFTP_STATUS_OK) {
|
||||
$this->_logError($response, $status);
|
||||
|
@ -2732,6 +2579,7 @@ class SFTP extends SSH2
|
|||
* @param string $oldname
|
||||
* @param string $newname
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @access public
|
||||
*/
|
||||
function rename($oldname, $newname)
|
||||
|
@ -2754,14 +2602,10 @@ class SFTP extends SSH2
|
|||
|
||||
$response = $this->_get_sftp_packet();
|
||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||
user_error('Expected SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
// if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||
if ($status != NET_SFTP_STATUS_OK) {
|
||||
$this->_logError($response, $status);
|
||||
|
@ -2789,10 +2633,6 @@ class SFTP extends SSH2
|
|||
function _parseAttributes(&$response)
|
||||
{
|
||||
$attr = array();
|
||||
if (strlen($response) < 4) {
|
||||
user_error('Malformed file attributes');
|
||||
return array();
|
||||
}
|
||||
extract(unpack('Nflags', $this->_string_shift($response, 4)));
|
||||
// SFTPv4+ have a type field (a byte) that follows the above flag field
|
||||
foreach ($this->attributes as $key => $value) {
|
||||
|
@ -2804,20 +2644,12 @@ class SFTP extends SSH2
|
|||
// IEEE 754 binary64 "double precision" on such platforms and
|
||||
// as such can represent integers of at least 2^50 without loss
|
||||
// of precision. Interpreted in filesize, 2^50 bytes = 1024 TiB.
|
||||
$attr['size'] = hexdec(bin2hex($this->_string_shift($response, 8)));
|
||||
$attr['size'] = hexdec(Hex::encode($this->_string_shift($response, 8)));
|
||||
break;
|
||||
case NET_SFTP_ATTR_UIDGID: // 0x00000002 (SFTPv3 only)
|
||||
if (strlen($response) < 8) {
|
||||
user_error('Malformed file attributes');
|
||||
return $attr;
|
||||
}
|
||||
$attr+= unpack('Nuid/Ngid', $this->_string_shift($response, 8));
|
||||
break;
|
||||
case NET_SFTP_ATTR_PERMISSIONS: // 0x00000004
|
||||
if (strlen($response) < 4) {
|
||||
user_error('Malformed file attributes');
|
||||
return $attr;
|
||||
}
|
||||
$attr+= unpack('Npermissions', $this->_string_shift($response, 4));
|
||||
// mode == permissions; permissions was the original array key and is retained for bc purposes.
|
||||
// mode was added because that's the more industry standard terminology
|
||||
|
@ -2828,29 +2660,13 @@ class SFTP extends SSH2
|
|||
}
|
||||
break;
|
||||
case NET_SFTP_ATTR_ACCESSTIME: // 0x00000008
|
||||
if (strlen($response) < 8) {
|
||||
user_error('Malformed file attributes');
|
||||
return $attr;
|
||||
}
|
||||
$attr+= unpack('Natime/Nmtime', $this->_string_shift($response, 8));
|
||||
break;
|
||||
case NET_SFTP_ATTR_EXTENDED: // 0x80000000
|
||||
if (strlen($response) < 4) {
|
||||
user_error('Malformed file attributes');
|
||||
return $attr;
|
||||
}
|
||||
extract(unpack('Ncount', $this->_string_shift($response, 4)));
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
if (strlen($response) < 4) {
|
||||
user_error('Malformed file attributes');
|
||||
return $attr;
|
||||
}
|
||||
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
||||
$key = $this->_string_shift($response, $length);
|
||||
if (strlen($response) < 4) {
|
||||
user_error('Malformed file attributes');
|
||||
return $attr;
|
||||
}
|
||||
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
||||
$attr[$key] = $this->_string_shift($response, $length);
|
||||
}
|
||||
|
@ -2947,10 +2763,10 @@ class SFTP extends SSH2
|
|||
* @return bool
|
||||
* @access private
|
||||
*/
|
||||
function _send_sftp_packet($type, $data, $request_id = 1)
|
||||
function _send_sftp_packet($type, $data)
|
||||
{
|
||||
$packet = $this->use_request_id ?
|
||||
pack('NCNa*', strlen($data) + 5, $type, $request_id, $data) :
|
||||
$packet = $this->request_id !== false ?
|
||||
pack('NCNa*', strlen($data) + 5, $type, $this->request_id, $data) :
|
||||
pack('NCa*', strlen($data) + 1, $type, $data);
|
||||
|
||||
$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
|
||||
|
@ -2988,24 +2804,15 @@ class SFTP extends SSH2
|
|||
* @return string
|
||||
* @access private
|
||||
*/
|
||||
function _get_sftp_packet($request_id = null)
|
||||
function _get_sftp_packet()
|
||||
{
|
||||
if (isset($request_id) && isset($this->requestBuffer[$request_id])) {
|
||||
$this->packet_type = $this->requestBuffer[$request_id]['packet_type'];
|
||||
$temp = $this->requestBuffer[$request_id]['packet'];
|
||||
unset($this->requestBuffer[$request_id]);
|
||||
return $temp;
|
||||
}
|
||||
|
||||
// in SSH2.php the timeout is cumulative per function call. eg. exec() will
|
||||
// timeout after 10s. but for SFTP.php it's cumulative per packet
|
||||
$this->curTimeout = $this->timeout;
|
||||
$this->curTimeout = false;
|
||||
|
||||
$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
|
||||
|
||||
// SFTP packet length
|
||||
while (strlen($this->packet_buffer) < 4) {
|
||||
$temp = $this->_get_channel_packet(self::CHANNEL, true);
|
||||
$temp = $this->_get_channel_packet(self::CHANNEL);
|
||||
if (is_bool($temp)) {
|
||||
$this->packet_type = false;
|
||||
$this->packet_buffer = '';
|
||||
|
@ -3013,23 +2820,13 @@ class SFTP extends SSH2
|
|||
}
|
||||
$this->packet_buffer.= $temp;
|
||||
}
|
||||
if (strlen($this->packet_buffer) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nlength', $this->_string_shift($this->packet_buffer, 4)));
|
||||
$tempLength = $length;
|
||||
$tempLength-= strlen($this->packet_buffer);
|
||||
|
||||
|
||||
// 256 * 1024 is what SFTP_MAX_MSG_LENGTH is set to in OpenSSH's sftp-common.h
|
||||
if ($tempLength > 256 * 1024) {
|
||||
user_error('Invalid SFTP packet size');
|
||||
return false;
|
||||
}
|
||||
|
||||
// SFTP packet type and data payload
|
||||
while ($tempLength > 0) {
|
||||
$temp = $this->_get_channel_packet(self::CHANNEL, true);
|
||||
$temp = $this->_get_channel_packet(self::CHANNEL);
|
||||
if (is_bool($temp)) {
|
||||
$this->packet_type = false;
|
||||
$this->packet_buffer = '';
|
||||
|
@ -3043,8 +2840,8 @@ class SFTP extends SSH2
|
|||
|
||||
$this->packet_type = ord($this->_string_shift($this->packet_buffer));
|
||||
|
||||
if ($this->use_request_id) {
|
||||
extract(unpack('Npacket_id', $this->_string_shift($this->packet_buffer, 4))); // remove the request id
|
||||
if ($this->request_id !== false) {
|
||||
$this->_string_shift($this->packet_buffer, 4); // remove the request id
|
||||
$length-= 5; // account for the request id and the packet type
|
||||
} else {
|
||||
$length-= 1; // account for the packet type
|
||||
|
@ -3067,21 +2864,13 @@ class SFTP extends SSH2
|
|||
}
|
||||
}
|
||||
|
||||
if (isset($request_id) && $this->use_request_id && $packet_id != $request_id) {
|
||||
$this->requestBuffer[$packet_id] = array(
|
||||
'packet_type' => $this->packet_type,
|
||||
'packet' => $packet
|
||||
);
|
||||
return $this->_get_sftp_packet($request_id);
|
||||
}
|
||||
|
||||
return $packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a log of the packets that have been sent and received.
|
||||
*
|
||||
* 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')
|
||||
* Returns a string if NET_SFTP_LOGGING == self::LOG_COMPLEX, an array if NET_SFTP_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SFTP_LOGGING')
|
||||
*
|
||||
* @access public
|
||||
* @return string or Array
|
||||
|
@ -3105,7 +2894,7 @@ class SFTP extends SSH2
|
|||
/**
|
||||
* Returns all errors
|
||||
*
|
||||
* @return array
|
||||
* @return string
|
||||
* @access public
|
||||
*/
|
||||
function getSFTPErrors()
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace phpseclib\Net\SFTP;
|
|||
|
||||
use phpseclib\Crypt\RSA;
|
||||
use phpseclib\Net\SFTP;
|
||||
use phpseclib\Net\SSH2;
|
||||
|
||||
/**
|
||||
* SFTP Stream Wrapper
|
||||
|
@ -177,13 +178,12 @@ class Stream
|
|||
}
|
||||
}
|
||||
|
||||
if ($host[0] == '$') {
|
||||
$host = substr($host, 1);
|
||||
global ${$host};
|
||||
if (($$host instanceof SFTP) === false) {
|
||||
if (preg_match('/^{[a-z0-9]+}$/i', $host)) {
|
||||
$host = SSH2::getConnectionByResourceId($host);
|
||||
if ($host === false) {
|
||||
return false;
|
||||
}
|
||||
$this->sftp = $$host;
|
||||
$this->sftp = $host;
|
||||
} else {
|
||||
if (isset($this->context)) {
|
||||
$context = stream_context_get_options($this->context);
|
||||
|
|
127
vendor/phpseclib/phpseclib/phpseclib/Net/SSH1.php
vendored
127
vendor/phpseclib/phpseclib/phpseclib/Net/SSH1.php
vendored
|
@ -48,6 +48,7 @@
|
|||
|
||||
namespace phpseclib\Net;
|
||||
|
||||
use ParagonIE\ConstantTime\Hex;
|
||||
use phpseclib\Crypt\DES;
|
||||
use phpseclib\Crypt\Random;
|
||||
use phpseclib\Crypt\TripleDES;
|
||||
|
@ -537,14 +538,15 @@ class SSH1
|
|||
* Connect to an SSHv1 server
|
||||
*
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @throws \RuntimeException on other errors
|
||||
* @access private
|
||||
*/
|
||||
function _connect()
|
||||
{
|
||||
$this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->connectionTimeout);
|
||||
if (!$this->fsock) {
|
||||
user_error(rtrim("Cannot connect to {$this->host}:{$this->port}. Error $errno. $errstr"));
|
||||
return false;
|
||||
throw new \RuntimeException(rtrim("Cannot connect to $host. Error $errno. $errstr"));
|
||||
}
|
||||
|
||||
$this->server_identification = $init_line = fgets($this->fsock, 255);
|
||||
|
@ -555,66 +557,45 @@ class SSH1
|
|||
}
|
||||
|
||||
if (!preg_match('#SSH-([0-9\.]+)-(.+)#', $init_line, $parts)) {
|
||||
user_error('Can only connect to SSH servers');
|
||||
return false;
|
||||
throw new \RuntimeException('Can only connect to SSH servers');
|
||||
}
|
||||
if ($parts[1][0] != 1) {
|
||||
user_error("Cannot connect to SSH $parts[1] servers");
|
||||
return false;
|
||||
throw new \RuntimeException("Cannot connect to $parts[1] servers");
|
||||
}
|
||||
|
||||
fputs($this->fsock, $this->identifier."\r\n");
|
||||
|
||||
$response = $this->_get_binary_packet();
|
||||
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
|
||||
user_error('Expected SSH_SMSG_PUBLIC_KEY');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_SMSG_PUBLIC_KEY');
|
||||
}
|
||||
|
||||
$anti_spoofing_cookie = $this->_string_shift($response[self::RESPONSE_DATA], 8);
|
||||
|
||||
$this->_string_shift($response[self::RESPONSE_DATA], 4);
|
||||
|
||||
if (strlen($response[self::RESPONSE_DATA]) < 2) {
|
||||
return false;
|
||||
}
|
||||
$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;
|
||||
|
||||
if (strlen($response[self::RESPONSE_DATA]) < 2) {
|
||||
return false;
|
||||
}
|
||||
$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[self::RESPONSE_DATA], 4);
|
||||
|
||||
if (strlen($response[self::RESPONSE_DATA]) < 2) {
|
||||
return false;
|
||||
}
|
||||
$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;
|
||||
|
||||
if (strlen($response[self::RESPONSE_DATA]) < 2) {
|
||||
return false;
|
||||
}
|
||||
$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[self::RESPONSE_DATA], 4);
|
||||
|
||||
// get a list of the supported ciphers
|
||||
if (strlen($response[self::RESPONSE_DATA]) < 4) {
|
||||
return false;
|
||||
}
|
||||
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]);
|
||||
|
@ -622,9 +603,6 @@ class SSH1
|
|||
}
|
||||
|
||||
// get a list of the supported authentications
|
||||
if (strlen($response[self::RESPONSE_DATA]) < 4) {
|
||||
return false;
|
||||
}
|
||||
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) {
|
||||
|
@ -632,7 +610,7 @@ class SSH1
|
|||
}
|
||||
}
|
||||
|
||||
$session_id = pack('H*', md5($host_key_public_modulus->toBytes() . $server_key_public_modulus->toBytes() . $anti_spoofing_cookie));
|
||||
$session_id = md5($host_key_public_modulus->toBytes() . $server_key_public_modulus->toBytes() . $anti_spoofing_cookie, true);
|
||||
|
||||
$session_key = Random::string(32);
|
||||
$double_encrypted_session_key = $session_key ^ str_pad($session_id, 32, chr(0));
|
||||
|
@ -673,8 +651,7 @@ class SSH1
|
|||
$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)) {
|
||||
user_error('Error sending SSH_CMSG_SESSION_KEY');
|
||||
return false;
|
||||
throw new \RuntimeException('Error sending SSH_CMSG_SESSION_KEY');
|
||||
}
|
||||
|
||||
switch ($cipher) {
|
||||
|
@ -682,16 +659,20 @@ class SSH1
|
|||
// $this->crypto = new \phpseclib\Crypt\Null();
|
||||
// break;
|
||||
case self::CIPHER_DES:
|
||||
$this->crypto = new DES();
|
||||
$this->crypto = new DES(DES::MODE_CBC);
|
||||
$this->crypto->disablePadding();
|
||||
$this->crypto->enableContinuousBuffer();
|
||||
$this->crypto->setKey(substr($session_key, 0, 8));
|
||||
// "The iv (initialization vector) is initialized to all zeroes."
|
||||
$this->crypto->setIV(str_repeat("\0", 8));
|
||||
break;
|
||||
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));
|
||||
// "All three initialization vectors are initialized to zero."
|
||||
$this->crypto->setIV(str_repeat("\0", 8));
|
||||
break;
|
||||
//case self::CIPHER_RC4:
|
||||
// $this->crypto = new RC4();
|
||||
|
@ -703,8 +684,7 @@ class SSH1
|
|||
$response = $this->_get_binary_packet();
|
||||
|
||||
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
|
||||
user_error('Expected SSH_SMSG_SUCCESS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS');
|
||||
}
|
||||
|
||||
$this->bitmap = self::MASK_CONNECTED;
|
||||
|
@ -718,6 +698,8 @@ class SSH1
|
|||
* @param string $username
|
||||
* @param string $password
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @throws \RuntimeException on other errors
|
||||
* @access public
|
||||
*/
|
||||
function login($username, $password = '')
|
||||
|
@ -736,8 +718,7 @@ class SSH1
|
|||
$data = pack('CNa*', NET_SSH1_CMSG_USER, strlen($username), $username);
|
||||
|
||||
if (!$this->_send_binary_packet($data)) {
|
||||
user_error('Error sending SSH_CMSG_USER');
|
||||
return false;
|
||||
throw new \RuntimeException('Error sending SSH_CMSG_USER');
|
||||
}
|
||||
|
||||
$response = $this->_get_binary_packet();
|
||||
|
@ -749,15 +730,13 @@ class SSH1
|
|||
$this->bitmap |= self::MASK_LOGIN;
|
||||
return true;
|
||||
} elseif ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) {
|
||||
user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
|
||||
}
|
||||
|
||||
$data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen($password), $password);
|
||||
|
||||
if (!$this->_send_binary_packet($data)) {
|
||||
user_error('Error sending SSH_CMSG_AUTH_PASSWORD');
|
||||
return false;
|
||||
throw new \RuntimeException('Error sending SSH_CMSG_AUTH_PASSWORD');
|
||||
}
|
||||
|
||||
// remove the username and password from the last logged packet
|
||||
|
@ -777,8 +756,7 @@ class SSH1
|
|||
} elseif ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) {
|
||||
return false;
|
||||
} else {
|
||||
user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -813,20 +791,19 @@ class SSH1
|
|||
* @see self::interactiveWrite()
|
||||
* @param string $cmd
|
||||
* @return mixed
|
||||
* @throws \RuntimeException on error sending command
|
||||
* @access public
|
||||
*/
|
||||
function exec($cmd, $block = true)
|
||||
{
|
||||
if (!($this->bitmap & self::MASK_LOGIN)) {
|
||||
user_error('Operation disallowed prior to login()');
|
||||
return false;
|
||||
throw new \RuntimeException('Operation disallowed prior to login()');
|
||||
}
|
||||
|
||||
$data = pack('CNa*', NET_SSH1_CMSG_EXEC_CMD, strlen($cmd), $cmd);
|
||||
|
||||
if (!$this->_send_binary_packet($data)) {
|
||||
user_error('Error sending SSH_CMSG_EXEC_CMD');
|
||||
return false;
|
||||
throw new \RuntimeException('Error sending SSH_CMSG_EXEC_CMD');
|
||||
}
|
||||
|
||||
if (!$block) {
|
||||
|
@ -862,6 +839,8 @@ class SSH1
|
|||
* @see self::interactiveRead()
|
||||
* @see self::interactiveWrite()
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @throws \RuntimeException on other errors
|
||||
* @access private
|
||||
*/
|
||||
function _initShell()
|
||||
|
@ -872,8 +851,7 @@ class SSH1
|
|||
$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');
|
||||
return false;
|
||||
throw new \RuntimeException('Error sending SSH_CMSG_REQUEST_PTY');
|
||||
}
|
||||
|
||||
$response = $this->_get_binary_packet();
|
||||
|
@ -882,15 +860,13 @@ class SSH1
|
|||
return false;
|
||||
}
|
||||
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
|
||||
user_error('Expected SSH_SMSG_SUCCESS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS');
|
||||
}
|
||||
|
||||
$data = pack('C', NET_SSH1_CMSG_EXEC_SHELL);
|
||||
|
||||
if (!$this->_send_binary_packet($data)) {
|
||||
user_error('Error sending SSH_CMSG_EXEC_SHELL');
|
||||
return false;
|
||||
throw new \RuntimeException('Error sending SSH_CMSG_EXEC_SHELL');
|
||||
}
|
||||
|
||||
$this->bitmap |= self::MASK_SHELL;
|
||||
|
@ -916,30 +892,29 @@ class 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 == self::READ_REGEX,
|
||||
* $expect can take the form of a string literal or, if $mode == self::READ__REGEX,
|
||||
* a regular expression.
|
||||
*
|
||||
* @see self::write()
|
||||
* @param string $expect
|
||||
* @param int $mode
|
||||
* @return bool
|
||||
* @throws \RuntimeException on connection error
|
||||
* @access public
|
||||
*/
|
||||
function read($expect, $mode = self::READ_SIMPLE)
|
||||
function read($expect, $mode = self::READ__SIMPLE)
|
||||
{
|
||||
if (!($this->bitmap & self::MASK_LOGIN)) {
|
||||
user_error('Operation disallowed prior to login()');
|
||||
return false;
|
||||
throw new \RuntimeException('Operation disallowed prior to login()');
|
||||
}
|
||||
|
||||
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
|
||||
user_error('Unable to initiate an interactive shell session');
|
||||
return false;
|
||||
throw new \RuntimeException('Unable to initiate an interactive shell session');
|
||||
}
|
||||
|
||||
$match = $expect;
|
||||
while (true) {
|
||||
if ($mode == self::READ_REGEX) {
|
||||
if ($mode == self::READ__REGEX) {
|
||||
preg_match($expect, $this->interactiveBuffer, $matches);
|
||||
$match = isset($matches[0]) ? $matches[0] : '';
|
||||
}
|
||||
|
@ -962,25 +937,23 @@ class SSH1
|
|||
* @see self::interactiveRead()
|
||||
* @param string $cmd
|
||||
* @return bool
|
||||
* @throws \RuntimeException on connection error
|
||||
* @access public
|
||||
*/
|
||||
function interactiveWrite($cmd)
|
||||
{
|
||||
if (!($this->bitmap & self::MASK_LOGIN)) {
|
||||
user_error('Operation disallowed prior to login()');
|
||||
return false;
|
||||
throw new \RuntimeException('Operation disallowed prior to login()');
|
||||
}
|
||||
|
||||
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
|
||||
user_error('Unable to initiate an interactive shell session');
|
||||
return false;
|
||||
throw new \RuntimeException('Unable to initiate an interactive shell session');
|
||||
}
|
||||
|
||||
$data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($cmd), $cmd);
|
||||
|
||||
if (!$this->_send_binary_packet($data)) {
|
||||
user_error('Error sending SSH_CMSG_STDIN');
|
||||
return false;
|
||||
throw new \RuntimeException('Error sending SSH_CMSG_STDIN');
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -997,18 +970,17 @@ class SSH1
|
|||
*
|
||||
* @see self::interactiveRead()
|
||||
* @return string
|
||||
* @throws \RuntimeException on connection error
|
||||
* @access public
|
||||
*/
|
||||
function interactiveRead()
|
||||
{
|
||||
if (!($this->bitmap & self::MASK_LOGIN)) {
|
||||
user_error('Operation disallowed prior to login()');
|
||||
return false;
|
||||
throw new \RuntimeException('Operation disallowed prior to login()');
|
||||
}
|
||||
|
||||
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
|
||||
user_error('Unable to initiate an interactive shell session');
|
||||
return false;
|
||||
throw new \RuntimeException('Unable to initiate an interactive shell session');
|
||||
}
|
||||
|
||||
$read = array($this->fsock);
|
||||
|
@ -1112,11 +1084,7 @@ class SSH1
|
|||
}
|
||||
|
||||
$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
|
||||
$data = fread($this->fsock, 4);
|
||||
if (strlen($data) < 4) {
|
||||
return false;
|
||||
}
|
||||
$temp = unpack('Nlength', $data);
|
||||
$temp = unpack('Nlength', fread($this->fsock, 4));
|
||||
|
||||
$padding_length = 8 - ($temp['length'] & 7);
|
||||
$length = $temp['length'] + $padding_length;
|
||||
|
@ -1137,9 +1105,6 @@ class SSH1
|
|||
$type = $raw[$padding_length];
|
||||
$data = substr($raw, $padding_length + 1, -4);
|
||||
|
||||
if (strlen($raw) < 4) {
|
||||
return false;
|
||||
}
|
||||
$temp = unpack('Ncrc', substr($raw, -4));
|
||||
|
||||
//if ( $temp['crc'] != $this->_crc($padding . $type . $data) ) {
|
||||
|
@ -1341,9 +1306,9 @@ class SSH1
|
|||
{
|
||||
/*
|
||||
$rsa = new RSA();
|
||||
$rsa->loadKey($key, RSA::PUBLIC_FORMAT_RAW);
|
||||
$rsa->setEncryptionMode(RSA::ENCRYPTION_PKCS1);
|
||||
return $rsa->encrypt($m);
|
||||
$rsa->load($key, 'raw');
|
||||
$rsa->setHash('sha1');
|
||||
return $rsa->encrypt($m, RSA::PADDING_PKCS1);
|
||||
*/
|
||||
|
||||
// To quote from protocol-1.5.txt:
|
||||
|
|
1257
vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php
vendored
1257
vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php
vendored
File diff suppressed because it is too large
Load Diff
|
@ -33,7 +33,9 @@
|
|||
|
||||
namespace phpseclib\System\SSH;
|
||||
|
||||
use ParagonIE\ConstantTime\Base64;
|
||||
use phpseclib\Crypt\RSA;
|
||||
use phpseclib\Exception\BadConfigurationException;
|
||||
use phpseclib\System\SSH\Agent\Identity;
|
||||
|
||||
/**
|
||||
|
@ -43,7 +45,7 @@ use phpseclib\System\SSH\Agent\Identity;
|
|||
*
|
||||
* @package SSH\Agent
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @access public
|
||||
* @access internal
|
||||
*/
|
||||
class Agent
|
||||
{
|
||||
|
@ -115,27 +117,26 @@ class Agent
|
|||
* Default Constructor
|
||||
*
|
||||
* @return \phpseclib\System\SSH\Agent
|
||||
* @throws \phpseclib\Exception\BadConfigurationException if SSH_AUTH_SOCK cannot be found
|
||||
* @throws \RuntimeException on connection errors
|
||||
* @access public
|
||||
*/
|
||||
function __construct($address = null)
|
||||
function __construct()
|
||||
{
|
||||
if (!$address) {
|
||||
switch (true) {
|
||||
case isset($_SERVER['SSH_AUTH_SOCK']):
|
||||
$address = $_SERVER['SSH_AUTH_SOCK'];
|
||||
break;
|
||||
case isset($_ENV['SSH_AUTH_SOCK']):
|
||||
$address = $_ENV['SSH_AUTH_SOCK'];
|
||||
break;
|
||||
default:
|
||||
user_error('SSH_AUTH_SOCK not found');
|
||||
return false;
|
||||
}
|
||||
switch (true) {
|
||||
case isset($_SERVER['SSH_AUTH_SOCK']):
|
||||
$address = $_SERVER['SSH_AUTH_SOCK'];
|
||||
break;
|
||||
case isset($_ENV['SSH_AUTH_SOCK']):
|
||||
$address = $_ENV['SSH_AUTH_SOCK'];
|
||||
break;
|
||||
default:
|
||||
throw new BadConfigurationException('SSH_AUTH_SOCK not found');
|
||||
}
|
||||
|
||||
$this->fsock = fsockopen('unix://' . $address, 0, $errno, $errstr);
|
||||
if (!$this->fsock) {
|
||||
user_error("Unable to connect to ssh-agent (Error $errno: $errstr)");
|
||||
throw new \RuntimeException("Unable to connect to ssh-agent (Error $errno: $errstr)");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,6 +147,7 @@ class Agent
|
|||
* Returns an array containing zero or more \phpseclib\System\SSH\Agent\Identity objects
|
||||
*
|
||||
* @return array
|
||||
* @throws \RuntimeException on receipt of unexpected packets
|
||||
* @access public
|
||||
*/
|
||||
function requestIdentities()
|
||||
|
@ -156,15 +158,13 @@ class Agent
|
|||
|
||||
$packet = pack('NC', 1, self::SSH_AGENTC_REQUEST_IDENTITIES);
|
||||
if (strlen($packet) != fputs($this->fsock, $packet)) {
|
||||
user_error('Connection closed while requesting identities');
|
||||
return array();
|
||||
throw new \RuntimeException('Connection closed while requesting identities');
|
||||
}
|
||||
|
||||
$length = current(unpack('N', fread($this->fsock, 4)));
|
||||
$type = ord(fread($this->fsock, 1));
|
||||
if ($type != self::SSH_AGENT_IDENTITIES_ANSWER) {
|
||||
user_error('Unable to request identities');
|
||||
return array();
|
||||
throw new \RuntimeException('Unable to request identities');
|
||||
}
|
||||
|
||||
$identities = array();
|
||||
|
@ -172,7 +172,7 @@ class 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);
|
||||
$key_str = 'ssh-rsa ' . Base64::encode($key_blob);
|
||||
$length = current(unpack('N', fread($this->fsock, 4)));
|
||||
if ($length) {
|
||||
$key_str.= ' ' . fread($this->fsock, $length);
|
||||
|
@ -182,7 +182,7 @@ class Agent
|
|||
switch ($key_type) {
|
||||
case 'ssh-rsa':
|
||||
$key = new RSA();
|
||||
$key->loadKey($key_str);
|
||||
$key->load($key_str);
|
||||
break;
|
||||
case 'ssh-dss':
|
||||
// not currently supported
|
||||
|
@ -278,6 +278,7 @@ class Agent
|
|||
*
|
||||
* @param string $data
|
||||
* @return data from SSH Agent
|
||||
* @throws \RuntimeException on connection errors
|
||||
* @access private
|
||||
*/
|
||||
function _forward_data($data)
|
||||
|
@ -296,7 +297,7 @@ class Agent
|
|||
}
|
||||
|
||||
if (strlen($this->socket_buffer) != fwrite($this->fsock, $this->socket_buffer)) {
|
||||
user_error('Connection closed attempting to forward data to SSH agent');
|
||||
throw new \RuntimeException('Connection closed attempting to forward data to SSH agent');
|
||||
}
|
||||
|
||||
$this->socket_buffer = '';
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
namespace phpseclib\System\SSH\Agent;
|
||||
|
||||
use phpseclib\Crypt\RSA;
|
||||
use phpseclib\Exception\UnsupportedAlgorithmException;
|
||||
use phpseclib\System\SSH\Agent;
|
||||
|
||||
/**
|
||||
|
@ -32,17 +34,6 @@ use phpseclib\System\SSH\Agent;
|
|||
*/
|
||||
class Identity
|
||||
{
|
||||
/**@+
|
||||
* Signature Flags
|
||||
*
|
||||
* See https://tools.ietf.org/html/draft-miller-ssh-agent-00#section-5.3
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
const SSH_AGENT_RSA2_256 = 2;
|
||||
const SSH_AGENT_RSA2_512 = 4;
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* Key Object
|
||||
*
|
||||
|
@ -70,16 +61,6 @@ class Identity
|
|||
*/
|
||||
var $fsock;
|
||||
|
||||
/**
|
||||
* Signature flags
|
||||
*
|
||||
* @var int
|
||||
* @access private
|
||||
* @see self::sign()
|
||||
* @see self::setHash()
|
||||
*/
|
||||
var $flags = 0;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
|
@ -125,50 +106,28 @@ class Identity
|
|||
*
|
||||
* Wrapper for $this->key->getPublicKey()
|
||||
*
|
||||
* @param int $format optional
|
||||
* @param int $type optional
|
||||
* @return mixed
|
||||
* @access public
|
||||
*/
|
||||
function getPublicKey($format = null)
|
||||
function getPublicKey($type = 'PKCS8')
|
||||
{
|
||||
return !isset($format) ? $this->key->getPublicKey() : $this->key->getPublicKey($format);
|
||||
return $this->key->getPublicKey($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Signature Mode
|
||||
* Sets the hash
|
||||
*
|
||||
* 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
|
||||
* ssh-agent only supports signatures with sha1 hashes but to maintain BC with RSA.php this function exists
|
||||
*
|
||||
* @param int $mode
|
||||
* @param string $hash optional
|
||||
* @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported
|
||||
* @access public
|
||||
*/
|
||||
function setSignatureMode($mode)
|
||||
function setHash($hash = 'sha1')
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Hash
|
||||
*
|
||||
* ssh-agent doesn't support using hashes for RSA other than SHA1
|
||||
*
|
||||
* @param string $hash
|
||||
* @access public
|
||||
*/
|
||||
function setHash($hash)
|
||||
{
|
||||
$this->flags = 0;
|
||||
switch ($hash) {
|
||||
case 'sha1':
|
||||
break;
|
||||
case 'sha256':
|
||||
$this->flags = self::SSH_AGENT_RSA2_256;
|
||||
break;
|
||||
case 'sha512':
|
||||
$this->flags = self::SSH_AGENT_RSA2_512;
|
||||
break;
|
||||
default:
|
||||
user_error('The only supported hashes for RSA are sha1, sha256 and sha512');
|
||||
if ($hash != 'sha1') {
|
||||
throw new UnsupportedAlgorithmException('ssh-agent can only be used with the sha1 hash');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,53 +137,34 @@ class Identity
|
|||
* See "2.6.2 Protocol 2 private key signature request"
|
||||
*
|
||||
* @param string $message
|
||||
* @param int $padding optional
|
||||
* @return string
|
||||
* @throws \RuntimeException on connection errors
|
||||
* @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported
|
||||
* @access public
|
||||
*/
|
||||
function sign($message)
|
||||
function sign($message, $padding = RSA::PADDING_PKCS1)
|
||||
{
|
||||
if ($padding != RSA::PADDING_PKCS1 && $padding != RSA::PADDING_RELAXED_PKCS1) {
|
||||
throw new UnsupportedAlgorithmException('ssh-agent can only create PKCS1 signatures');
|
||||
}
|
||||
|
||||
// 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, $this->flags);
|
||||
$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');
|
||||
throw new \RuntimeException('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');
|
||||
throw new \RuntimeException('Unable to retreive signature');
|
||||
}
|
||||
|
||||
$signature_blob = fread($this->fsock, $length - 1);
|
||||
$length = current(unpack('N', $this->_string_shift($signature_blob, 4)));
|
||||
if ($length != strlen($signature_blob)) {
|
||||
user_error('Malformed signature blob');
|
||||
}
|
||||
$length = current(unpack('N', $this->_string_shift($signature_blob, 4)));
|
||||
if ($length > strlen($signature_blob) + 4) {
|
||||
user_error('Malformed signature blob');
|
||||
}
|
||||
$type = $this->_string_shift($signature_blob, $length);
|
||||
$this->_string_shift($signature_blob, 4);
|
||||
|
||||
return $signature_blob;
|
||||
}
|
||||
|
||||
/**
|
||||
* String Shift
|
||||
*
|
||||
* Inspired by array_shift
|
||||
*
|
||||
* @param string $string
|
||||
* @param int $index
|
||||
* @return string
|
||||
* @access private
|
||||
*/
|
||||
function _string_shift(&$string, $index = 1)
|
||||
{
|
||||
$substr = substr($string, 0, $index);
|
||||
$string = substr($string, $index);
|
||||
return $substr;
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Bootstrapping File for phpseclib
|
||||
*
|
||||
* composer isn't a requirement for phpseclib 2.0 but this file isn't really required
|
||||
* either. it's a bonus for those using composer but if you're not phpseclib will
|
||||
* still work
|
||||
*
|
||||
* @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(
|
||||
throw new UnexpectedValueException(
|
||||
'Overloading of string functions using mbstring.func_overload ' .
|
||||
'is not supported by phpseclib.'
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue
Block a user